aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/quick/qtquick.qdoc52
-rw-r--r--examples/declarative/cppextensions/networkaccessmanagerfactory/main.cpp2
-rw-r--r--examples/declarative/cppextensions/networkaccessmanagerfactory/networkaccessmanagerfactory.pro2
-rw-r--r--examples/declarative/minehunt/main.cpp2
-rw-r--r--examples/declarative/minehunt/minehunt.pro2
-rw-r--r--examples/declarative/modelviews/abstractitemmodel/abstractitemmodel.pro4
-rw-r--r--examples/declarative/modelviews/abstractitemmodel/main.cpp4
-rw-r--r--examples/declarative/modelviews/objectlistmodel/main.cpp4
-rw-r--r--examples/declarative/modelviews/objectlistmodel/objectlistmodel.pro2
-rw-r--r--examples/declarative/modelviews/stringlistmodel/main.cpp4
-rw-r--r--examples/declarative/modelviews/stringlistmodel/stringlistmodel.pro2
-rw-r--r--examples/declarative/openglunderqml/main.cpp2
-rw-r--r--examples/declarative/openglunderqml/openglunderqml.pro2
-rw-r--r--examples/declarative/openglunderqml/squircle.cpp4
-rw-r--r--examples/declarative/openglunderqml/squircle.h2
-rw-r--r--examples/declarative/painteditem/smile/main.cpp4
-rw-r--r--examples/declarative/painteditem/smile/smile.pro2
-rw-r--r--examples/declarative/painteditem/textballoons/textballoon.h2
-rw-r--r--examples/declarative/painteditem/textballoons/textballoons.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter1-basics/main.cpp2
-rw-r--r--examples/declarative/tutorials/extending/chapter1-basics/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter2-methods/chapter2-methods.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter2-methods/main.cpp2
-rw-r--r--examples/declarative/tutorials/extending/chapter2-methods/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter3-bindings/chapter3-bindings.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter3-bindings/main.cpp2
-rw-r--r--examples/declarative/tutorials/extending/chapter3-bindings/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp2
-rw-r--r--examples/declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter5-listproperties/main.cpp2
-rw-r--r--examples/declarative/tutorials/extending/chapter5-listproperties/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter5-listproperties/pieslice.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro2
-rw-r--r--examples/declarative/tutorials/extending/chapter6-plugins/piechart.h2
-rw-r--r--examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h2
-rw-r--r--modules/qt_quick.pri17
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice_p.h2
-rw-r--r--src/declarative/declarative.pro7
-rw-r--r--src/declarative/designer/designersupport.cpp408
-rw-r--r--src/declarative/designer/designersupport.h153
-rw-r--r--src/declarative/items/context2d/qquickcanvasitem.cpp714
-rw-r--r--src/declarative/items/context2d/qquickcanvasitem_p.h149
-rw-r--r--src/declarative/items/context2d/qquickcontext2d.cpp3540
-rw-r--r--src/declarative/items/context2d/qquickcontext2d_p.h211
-rw-r--r--src/declarative/items/context2d/qquickcontext2dcommandbuffer_p.h268
-rw-r--r--src/declarative/items/context2d/qquickcontext2dnode.cpp124
-rw-r--r--src/declarative/items/context2d/qquickcontext2dnode_p.h86
-rw-r--r--src/declarative/items/context2d/qquickcontext2dtexture.cpp778
-rw-r--r--src/declarative/items/context2d/qquickcontext2dtexture_p.h205
-rw-r--r--src/declarative/items/context2d/qquickcontext2dtile_p.h112
-rw-r--r--src/declarative/items/qquickanchors_p.h201
-rw-r--r--src/declarative/items/qquickanimatedimage_p.h117
-rw-r--r--src/declarative/items/qquickanimation_p.h209
-rw-r--r--src/declarative/items/qquickborderimage_p.h110
-rw-r--r--src/declarative/items/qquickcanvas.cpp2644
-rw-r--r--src/declarative/items/qquickcanvas.h164
-rw-r--r--src/declarative/items/qquickcanvas_p.h323
-rw-r--r--src/declarative/items/qquickclipnode_p.h71
-rw-r--r--src/declarative/items/qquickdrag.cpp462
-rw-r--r--src/declarative/items/qquickdrag_p.h208
-rw-r--r--src/declarative/items/qquickdroparea_p.h167
-rw-r--r--src/declarative/items/qquickevents_p_p.h144
-rw-r--r--src/declarative/items/qquickflickable_p.h277
-rw-r--r--src/declarative/items/qquickflipable_p.h104
-rw-r--r--src/declarative/items/qquickfocusscope_p.h68
-rw-r--r--src/declarative/items/qquickgridview_p.h146
-rw-r--r--src/declarative/items/qquickimage.cpp746
-rw-r--r--src/declarative/items/qquickimage_p.h122
-rw-r--r--src/declarative/items/qquickimagebase_p_p.h93
-rw-r--r--src/declarative/items/qquickitem.cpp5236
-rw-r--r--src/declarative/items/qquickitem.h421
-rw-r--r--src/declarative/items/qquickitem_p.h752
-rw-r--r--src/declarative/items/qquickitemsmodule.cpp241
-rw-r--r--src/declarative/items/qquickitemsmodule_p.h65
-rw-r--r--src/declarative/items/qquickitemview_p.h296
-rw-r--r--src/declarative/items/qquickitemview_p_p.h260
-rw-r--r--src/declarative/items/qquicklistview_p.h215
-rw-r--r--src/declarative/items/qquickloader_p.h123
-rw-r--r--src/declarative/items/qquickmousearea_p.h231
-rw-r--r--src/declarative/items/qquickmultipointtoucharea.cpp729
-rw-r--r--src/declarative/items/qquickmultipointtoucharea_p.h267
-rw-r--r--src/declarative/items/qquickninepatchnode_p.h98
-rw-r--r--src/declarative/items/qquickpainteditem.cpp528
-rw-r--r--src/declarative/items/qquickpainteditem.h130
-rw-r--r--src/declarative/items/qquickpathview.cpp1781
-rw-r--r--src/declarative/items/qquickpathview_p.h259
-rw-r--r--src/declarative/items/qquickpincharea_p.h315
-rw-r--r--src/declarative/items/qquickpositioners.cpp1532
-rw-r--r--src/declarative/items/qquickpositioners_p.h295
-rw-r--r--src/declarative/items/qquickpositioners_p_p.h164
-rw-r--r--src/declarative/items/qquickrectangle.cpp556
-rw-r--r--src/declarative/items/qquickrectangle_p.h189
-rw-r--r--src/declarative/items/qquickrepeater_p.h112
-rw-r--r--src/declarative/items/qquickscalegrid_p_p.h134
-rw-r--r--src/declarative/items/qquickshadereffect.cpp763
-rw-r--r--src/declarative/items/qquickshadereffect_p.h158
-rw-r--r--src/declarative/items/qquickshadereffectmesh.cpp216
-rw-r--r--src/declarative/items/qquickshadereffectmesh_p.h103
-rw-r--r--src/declarative/items/qquickshadereffectnode.cpp317
-rw-r--r--src/declarative/items/qquickshadereffectnode_p.h151
-rw-r--r--src/declarative/items/qquickshadereffectsource.cpp921
-rw-r--r--src/declarative/items/qquickshadereffectsource_p.h259
-rw-r--r--src/declarative/items/qquicksprite_p.h136
-rw-r--r--src/declarative/items/qquickspriteengine_p.h323
-rw-r--r--src/declarative/items/qquickspriteimage.cpp455
-rw-r--r--src/declarative/items/qquickspriteimage_p.h140
-rw-r--r--src/declarative/items/qquickstateoperations_p.h275
-rw-r--r--src/declarative/items/qquicktext.cpp1950
-rw-r--r--src/declarative/items/qquicktext_p.h252
-rw-r--r--src/declarative/items/qquicktextedit.cpp2091
-rw-r--r--src/declarative/items/qquicktextedit_p.h314
-rw-r--r--src/declarative/items/qquicktextinput.cpp2007
-rw-r--r--src/declarative/items/qquicktextinput_p.h302
-rw-r--r--src/declarative/items/qquicktextnode.cpp1344
-rw-r--r--src/declarative/items/qquicktextnode_p.h110
-rw-r--r--src/declarative/items/qquicktranslate_p.h162
-rw-r--r--src/declarative/items/qquickview.cpp539
-rw-r--r--src/declarative/items/qquickview.h120
-rw-r--r--src/declarative/items/qquickview_p.h105
-rw-r--r--src/declarative/items/qquickvisualdatamodel_p.h242
-rw-r--r--src/declarative/items/qquickvisualitemmodel_p.h175
-rw-r--r--src/declarative/items/qquickwindowmodule.cpp55
-rw-r--r--src/declarative/particles/qquickage_p.h102
-rw-r--r--src/declarative/particles/qquickangledirection_p.h133
-rw-r--r--src/declarative/particles/qquickcumulativedirection_p.h69
-rw-r--r--src/declarative/particles/qquickcustomaffector_p.h164
-rw-r--r--src/declarative/particles/qquickcustomparticle.cpp596
-rw-r--r--src/declarative/particles/qquickcustomparticle_p.h121
-rw-r--r--src/declarative/particles/qquickdirection_p.h71
-rw-r--r--src/declarative/particles/qquickellipseextruder_p.h86
-rw-r--r--src/declarative/particles/qquickfriction_p.h104
-rw-r--r--src/declarative/particles/qquickgravity_p.h118
-rw-r--r--src/declarative/particles/qquickgroupgoal_p.h102
-rw-r--r--src/declarative/particles/qquickimageparticle.cpp1803
-rw-r--r--src/declarative/particles/qquickimageparticle_p.h429
-rw-r--r--src/declarative/particles/qquickitemparticle.cpp269
-rw-r--r--src/declarative/particles/qquickitemparticle_p.h138
-rw-r--r--src/declarative/particles/qquickmaskextruder_p.h97
-rw-r--r--src/declarative/particles/qquickparticleaffector_p.h201
-rw-r--r--src/declarative/particles/qquickparticleemitter_p.h351
-rw-r--r--src/declarative/particles/qquickparticleextruder_p.h73
-rw-r--r--src/declarative/particles/qquickparticlepainter_p.h132
-rw-r--r--src/declarative/particles/qquickparticlesmodule_p.h63
-rw-r--r--src/declarative/particles/qquickparticlesystem.cpp1106
-rw-r--r--src/declarative/particles/qquickparticlesystem_p.h380
-rw-r--r--src/declarative/particles/qquickpointattractor_p.h169
-rw-r--r--src/declarative/particles/qquickpointdirection_p.h135
-rw-r--r--src/declarative/particles/qquickrectangleextruder_p.h88
-rw-r--r--src/declarative/particles/qquickspritegoal_p.h125
-rw-r--r--src/declarative/particles/qquicktargetdirection_p.h191
-rw-r--r--src/declarative/particles/qquicktrailemitter_p.h171
-rw-r--r--src/declarative/particles/qquickturbulence_p.h119
-rw-r--r--src/declarative/particles/qquickv8particledata_p.h69
-rw-r--r--src/declarative/particles/qquickwander_p.h161
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp6
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h2
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp1
-rw-r--r--src/declarative/qtquick2.cpp193
-rw-r--r--src/declarative/qtquick2_p.h63
-rw-r--r--src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h123
-rw-r--r--src/declarative/scenegraph/coreapi/qsggeometry.h295
-rw-r--r--src/declarative/scenegraph/coreapi/qsgmaterial.h144
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnode.cpp1264
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnode.h348
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h86
-rw-r--r--src/declarative/scenegraph/coreapi/qsgrenderer_p.h234
-rw-r--r--src/declarative/scenegraph/qsgadaptationlayer.cpp315
-rw-r--r--src/declarative/scenegraph/qsgadaptationlayer_p.h257
-rw-r--r--src/declarative/scenegraph/qsgcontext.cpp512
-rw-r--r--src/declarative/scenegraph/qsgcontext_p.h144
-rw-r--r--src/declarative/scenegraph/qsgcontextplugin.cpp104
-rw-r--r--src/declarative/scenegraph/qsgcontextplugin_p.h81
-rw-r--r--src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp324
-rw-r--r--src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h165
-rw-r--r--src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp306
-rw-r--r--src/declarative/scenegraph/qsgdefaultglyphnode_p.h87
-rw-r--r--src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h96
-rw-r--r--src/declarative/scenegraph/qsgdefaultimagenode.cpp293
-rw-r--r--src/declarative/scenegraph/qsgdefaultimagenode_p.h90
-rw-r--r--src/declarative/scenegraph/qsgdefaultrectanglenode.cpp548
-rw-r--r--src/declarative/scenegraph/qsgdefaultrectanglenode_p.h108
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp316
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp725
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h107
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h140
-rw-r--r--src/declarative/scenegraph/qsgflashnode_p.h69
-rw-r--r--src/declarative/scenegraph/util/qsgareaallocator_p.h73
-rw-r--r--src/declarative/scenegraph/util/qsgdistancefieldutil.cpp805
-rw-r--r--src/declarative/scenegraph/util/qsgdistancefieldutil_p.h111
-rw-r--r--src/declarative/scenegraph/util/qsgengine.cpp115
-rw-r--r--src/declarative/scenegraph/util/qsgengine.h102
-rw-r--r--src/declarative/scenegraph/util/qsgflatcolormaterial.cpp202
-rw-r--r--src/declarative/scenegraph/util/qsgflatcolormaterial.h74
-rw-r--r--src/declarative/scenegraph/util/qsgpainternode.cpp464
-rw-r--r--src/declarative/scenegraph/util/qsgpainternode_p.h160
-rw-r--r--src/declarative/scenegraph/util/qsgsimplematerial.h222
-rw-r--r--src/declarative/scenegraph/util/qsgsimplerectnode.h77
-rw-r--r--src/declarative/scenegraph/util/qsgsimpletexturenode.cpp154
-rw-r--r--src/declarative/scenegraph/util/qsgsimpletexturenode.h82
-rw-r--r--src/declarative/scenegraph/util/qsgtexture.cpp541
-rw-r--r--src/declarative/scenegraph/util/qsgtexture.h133
-rw-r--r--src/declarative/scenegraph/util/qsgtexture_p.h118
-rw-r--r--src/declarative/scenegraph/util/qsgtexturematerial.h102
-rw-r--r--src/declarative/scenegraph/util/qsgtexturematerial_p.h73
-rw-r--r--src/declarative/scenegraph/util/qsgtextureprovider_p.h68
-rw-r--r--src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp173
-rw-r--r--src/declarative/scenegraph/util/qsgvertexcolormaterial.h69
-rw-r--r--src/declarative/util/qdeclarativeanimation_p.h458
-rw-r--r--src/declarative/util/qdeclarativebehavior_p.h97
-rw-r--r--src/declarative/util/qdeclarativebind_p.h98
-rw-r--r--src/declarative/util/qdeclarativeconnections_p.h102
-rw-r--r--src/declarative/util/qdeclarativefontloader_p.h97
-rw-r--r--src/declarative/util/qdeclarativelistaccessor_p.h80
-rw-r--r--src/declarative/util/qdeclarativepackage_p.h98
-rw-r--r--src/declarative/util/qdeclarativepath_p.h452
-rw-r--r--src/declarative/util/qdeclarativepathinterpolator_p.h100
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp1241
-rw-r--r--src/declarative/util/qdeclarativepixmapcache_p.h143
-rw-r--r--src/declarative/util/qdeclarativepropertychanges_p.h112
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation_p.h103
-rw-r--r--src/declarative/util/qdeclarativespringanimation_p.h111
-rw-r--r--src/declarative/util/qdeclarativestate_p.h210
-rw-r--r--src/declarative/util/qdeclarativestategroup_p.h97
-rw-r--r--src/declarative/util/qdeclarativestateoperations_p.h88
-rw-r--r--src/declarative/util/qdeclarativesystempalette_p.h122
-rw-r--r--src/declarative/util/qdeclarativetimer_p.h115
-rw-r--r--src/declarative/util/qdeclarativetransition_p.h111
-rw-r--r--src/declarative/util/qdeclarativeutilmodule_p.h63
-rw-r--r--src/declarative/util/util.pri60
-rw-r--r--src/imports/etcprovider/etcprovider.pro2
-rw-r--r--src/imports/etcprovider/qetcprovider.h2
-rw-r--r--src/imports/imports.pro4
-rw-r--r--src/imports/qtquick2/plugin.cpp68
-rw-r--r--src/imports/qtquick2/qmldir1
-rw-r--r--src/imports/qtquick2/qtquick2.pro19
-rw-r--r--src/imports/testlib/main.cpp2
-rw-r--r--src/imports/testlib/testlib.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/sghighlight.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/sgselectiontool.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/sgviewinspector.cpp6
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/qmltest/quicktest.cpp2
-rw-r--r--src/qmltest/quicktestevent.cpp4
-rw-r--r--src/quick/designer/designer.pri (renamed from src/declarative/designer/designer.pri)0
-rw-r--r--src/quick/designer/designersupport.cpp408
-rw-r--r--src/quick/designer/designersupport.h152
-rwxr-xr-xsrc/quick/items/checksync.pl (renamed from src/declarative/items/checksync.pl)0
-rw-r--r--src/quick/items/context2d/context2d.pri (renamed from src/declarative/items/context2d/context2d.pri)0
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp714
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h148
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp3540
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h210
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp (renamed from src/declarative/items/context2d/qquickcontext2dcommandbuffer.cpp)0
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h266
-rw-r--r--src/quick/items/context2d/qquickcontext2dnode.cpp124
-rw-r--r--src/quick/items/context2d/qquickcontext2dnode_p.h84
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp778
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h203
-rw-r--r--src/quick/items/context2d/qquickcontext2dtile.cpp (renamed from src/declarative/items/context2d/qquickcontext2dtile.cpp)0
-rw-r--r--src/quick/items/context2d/qquickcontext2dtile_p.h110
-rw-r--r--src/quick/items/items.pri (renamed from src/declarative/items/items.pri)0
-rw-r--r--src/quick/items/qquickanchors.cpp (renamed from src/declarative/items/qquickanchors.cpp)0
-rw-r--r--src/quick/items/qquickanchors_p.h199
-rw-r--r--src/quick/items/qquickanchors_p_p.h (renamed from src/declarative/items/qquickanchors_p_p.h)0
-rw-r--r--src/quick/items/qquickanimatedimage.cpp (renamed from src/declarative/items/qquickanimatedimage.cpp)0
-rw-r--r--src/quick/items/qquickanimatedimage_p.h115
-rw-r--r--src/quick/items/qquickanimatedimage_p_p.h (renamed from src/declarative/items/qquickanimatedimage_p_p.h)0
-rw-r--r--src/quick/items/qquickanimation.cpp (renamed from src/declarative/items/qquickanimation.cpp)0
-rw-r--r--src/quick/items/qquickanimation_p.h207
-rw-r--r--src/quick/items/qquickanimation_p_p.h (renamed from src/declarative/items/qquickanimation_p_p.h)0
-rw-r--r--src/quick/items/qquickborderimage.cpp (renamed from src/declarative/items/qquickborderimage.cpp)0
-rw-r--r--src/quick/items/qquickborderimage_p.h108
-rw-r--r--src/quick/items/qquickborderimage_p_p.h (renamed from src/declarative/items/qquickborderimage_p_p.h)0
-rw-r--r--src/quick/items/qquickcanvas.cpp2646
-rw-r--r--src/quick/items/qquickcanvas.h163
-rw-r--r--src/quick/items/qquickcanvas_p.h323
-rw-r--r--src/quick/items/qquickclipnode.cpp (renamed from src/declarative/items/qquickclipnode.cpp)0
-rw-r--r--src/quick/items/qquickclipnode_p.h71
-rw-r--r--src/quick/items/qquickdrag.cpp462
-rw-r--r--src/quick/items/qquickdrag_p.h206
-rw-r--r--src/quick/items/qquickdroparea.cpp (renamed from src/declarative/items/qquickdroparea.cpp)0
-rw-r--r--src/quick/items/qquickdroparea_p.h165
-rw-r--r--src/quick/items/qquickevents.cpp (renamed from src/declarative/items/qquickevents.cpp)0
-rw-r--r--src/quick/items/qquickevents_p_p.h145
-rw-r--r--src/quick/items/qquickflickable.cpp (renamed from src/declarative/items/qquickflickable.cpp)0
-rw-r--r--src/quick/items/qquickflickable_p.h275
-rw-r--r--src/quick/items/qquickflickable_p_p.h (renamed from src/declarative/items/qquickflickable_p_p.h)0
-rw-r--r--src/quick/items/qquickflipable.cpp (renamed from src/declarative/items/qquickflipable.cpp)0
-rw-r--r--src/quick/items/qquickflipable_p.h102
-rw-r--r--src/quick/items/qquickfocusscope.cpp (renamed from src/declarative/items/qquickfocusscope.cpp)0
-rw-r--r--src/quick/items/qquickfocusscope_p.h66
-rw-r--r--src/quick/items/qquickgridview.cpp (renamed from src/declarative/items/qquickgridview.cpp)0
-rw-r--r--src/quick/items/qquickgridview_p.h145
-rw-r--r--src/quick/items/qquickimage.cpp746
-rw-r--r--src/quick/items/qquickimage_p.h120
-rw-r--r--src/quick/items/qquickimage_p_p.h (renamed from src/declarative/items/qquickimage_p_p.h)0
-rw-r--r--src/quick/items/qquickimagebase.cpp (renamed from src/declarative/items/qquickimagebase.cpp)0
-rw-r--r--src/quick/items/qquickimagebase_p.h (renamed from src/declarative/items/qquickimagebase_p.h)0
-rw-r--r--src/quick/items/qquickimagebase_p_p.h93
-rw-r--r--src/quick/items/qquickimplicitsizeitem.cpp (renamed from src/declarative/items/qquickimplicitsizeitem.cpp)0
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p.h (renamed from src/declarative/items/qquickimplicitsizeitem_p.h)0
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p_p.h (renamed from src/declarative/items/qquickimplicitsizeitem_p_p.h)0
-rw-r--r--src/quick/items/qquickitem.cpp5238
-rw-r--r--src/quick/items/qquickitem.h420
-rw-r--r--src/quick/items/qquickitem_p.h752
-rw-r--r--src/quick/items/qquickitemchangelistener_p.h (renamed from src/declarative/items/qquickitemchangelistener_p.h)0
-rw-r--r--src/quick/items/qquickitemsmodule.cpp241
-rw-r--r--src/quick/items/qquickitemsmodule_p.h63
-rw-r--r--src/quick/items/qquickitemview.cpp (renamed from src/declarative/items/qquickitemview.cpp)0
-rw-r--r--src/quick/items/qquickitemview_p.h294
-rw-r--r--src/quick/items/qquickitemview_p_p.h258
-rw-r--r--src/quick/items/qquicklistview.cpp (renamed from src/declarative/items/qquicklistview.cpp)0
-rw-r--r--src/quick/items/qquicklistview_p.h213
-rw-r--r--src/quick/items/qquickloader.cpp (renamed from src/declarative/items/qquickloader.cpp)0
-rw-r--r--src/quick/items/qquickloader_p.h121
-rw-r--r--src/quick/items/qquickloader_p_p.h (renamed from src/declarative/items/qquickloader_p_p.h)0
-rw-r--r--src/quick/items/qquickmousearea.cpp (renamed from src/declarative/items/qquickmousearea.cpp)0
-rw-r--r--src/quick/items/qquickmousearea_p.h229
-rw-r--r--src/quick/items/qquickmousearea_p_p.h (renamed from src/declarative/items/qquickmousearea_p_p.h)0
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp729
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h265
-rw-r--r--src/quick/items/qquickninepatchnode.cpp (renamed from src/declarative/items/qquickninepatchnode.cpp)0
-rw-r--r--src/quick/items/qquickninepatchnode_p.h98
-rw-r--r--src/quick/items/qquickpainteditem.cpp528
-rw-r--r--src/quick/items/qquickpainteditem.h130
-rw-r--r--src/quick/items/qquickpainteditem_p.h (renamed from src/declarative/items/qquickpainteditem_p.h)0
-rw-r--r--src/quick/items/qquickpathview.cpp1781
-rw-r--r--src/quick/items/qquickpathview_p.h257
-rw-r--r--src/quick/items/qquickpathview_p_p.h (renamed from src/declarative/items/qquickpathview_p_p.h)0
-rw-r--r--src/quick/items/qquickpincharea.cpp (renamed from src/declarative/items/qquickpincharea.cpp)0
-rw-r--r--src/quick/items/qquickpincharea_p.h313
-rw-r--r--src/quick/items/qquickpincharea_p_p.h (renamed from src/declarative/items/qquickpincharea_p_p.h)0
-rw-r--r--src/quick/items/qquickpositioners.cpp1532
-rw-r--r--src/quick/items/qquickpositioners_p.h293
-rw-r--r--src/quick/items/qquickpositioners_p_p.h164
-rw-r--r--src/quick/items/qquickrectangle.cpp556
-rw-r--r--src/quick/items/qquickrectangle_p.h188
-rw-r--r--src/quick/items/qquickrectangle_p_p.h (renamed from src/declarative/items/qquickrectangle_p_p.h)0
-rw-r--r--src/quick/items/qquickrepeater.cpp (renamed from src/declarative/items/qquickrepeater.cpp)0
-rw-r--r--src/quick/items/qquickrepeater_p.h110
-rw-r--r--src/quick/items/qquickrepeater_p_p.h (renamed from src/declarative/items/qquickrepeater_p_p.h)0
-rw-r--r--src/quick/items/qquickscalegrid.cpp (renamed from src/declarative/items/qquickscalegrid.cpp)0
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h132
-rw-r--r--src/quick/items/qquickshadereffect.cpp763
-rw-r--r--src/quick/items/qquickshadereffect_p.h156
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp216
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h102
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp317
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h149
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp921
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h257
-rw-r--r--src/quick/items/qquicksprite.cpp (renamed from src/declarative/items/qquicksprite.cpp)0
-rw-r--r--src/quick/items/qquicksprite_p.h133
-rw-r--r--src/quick/items/qquickspriteengine.cpp (renamed from src/declarative/items/qquickspriteengine.cpp)0
-rw-r--r--src/quick/items/qquickspriteengine_p.h321
-rw-r--r--src/quick/items/qquickspriteimage.cpp455
-rw-r--r--src/quick/items/qquickspriteimage_p.h138
-rw-r--r--src/quick/items/qquickstateoperations.cpp (renamed from src/declarative/items/qquickstateoperations.cpp)0
-rw-r--r--src/quick/items/qquickstateoperations_p.h273
-rw-r--r--src/quick/items/qquicktext.cpp1950
-rw-r--r--src/quick/items/qquicktext_p.h251
-rw-r--r--src/quick/items/qquicktext_p_p.h (renamed from src/declarative/items/qquicktext_p_p.h)0
-rw-r--r--src/quick/items/qquicktextedit.cpp2091
-rw-r--r--src/quick/items/qquicktextedit_p.h312
-rw-r--r--src/quick/items/qquicktextedit_p_p.h (renamed from src/declarative/items/qquicktextedit_p_p.h)0
-rw-r--r--src/quick/items/qquicktextinput.cpp2007
-rw-r--r--src/quick/items/qquicktextinput_p.h300
-rw-r--r--src/quick/items/qquicktextinput_p_p.h (renamed from src/declarative/items/qquicktextinput_p_p.h)0
-rw-r--r--src/quick/items/qquicktextnode.cpp1344
-rw-r--r--src/quick/items/qquicktextnode_p.h110
-rw-r--r--src/quick/items/qquicktranslate.cpp (renamed from src/declarative/items/qquicktranslate.cpp)0
-rw-r--r--src/quick/items/qquicktranslate_p.h160
-rw-r--r--src/quick/items/qquickview.cpp541
-rw-r--r--src/quick/items/qquickview.h118
-rw-r--r--src/quick/items/qquickview_p.h103
-rw-r--r--src/quick/items/qquickvisualadaptormodel.cpp (renamed from src/declarative/items/qquickvisualadaptormodel.cpp)0
-rw-r--r--src/quick/items/qquickvisualadaptormodel_p.h (renamed from src/declarative/items/qquickvisualadaptormodel_p.h)0
-rw-r--r--src/quick/items/qquickvisualdatamodel.cpp (renamed from src/declarative/items/qquickvisualdatamodel.cpp)0
-rw-r--r--src/quick/items/qquickvisualdatamodel_p.h239
-rw-r--r--src/quick/items/qquickvisualitemmodel.cpp (renamed from src/declarative/items/qquickvisualitemmodel.cpp)0
-rw-r--r--src/quick/items/qquickvisualitemmodel_p.h174
-rw-r--r--src/quick/items/qquickwindowmodule.cpp55
-rw-r--r--src/quick/items/qquickwindowmodule_p.h (renamed from src/declarative/items/qquickwindowmodule_p.h)0
-rw-r--r--src/quick/items/syncexcludes (renamed from src/declarative/items/syncexcludes)0
-rw-r--r--src/quick/particles/particleresources/noise.png (renamed from src/declarative/particles/particleresources/noise.png)bin19477 -> 19477 bytes
-rw-r--r--src/quick/particles/particles.pri (renamed from src/declarative/particles/particles.pri)0
-rw-r--r--src/quick/particles/particles.qrc (renamed from src/declarative/particles/particles.qrc)0
-rw-r--r--src/quick/particles/qquickage.cpp (renamed from src/declarative/particles/qquickage.cpp)0
-rw-r--r--src/quick/particles/qquickage_p.h99
-rw-r--r--src/quick/particles/qquickangledirection.cpp (renamed from src/declarative/particles/qquickangledirection.cpp)0
-rw-r--r--src/quick/particles/qquickangledirection_p.h131
-rw-r--r--src/quick/particles/qquickcumulativedirection.cpp (renamed from src/declarative/particles/qquickcumulativedirection.cpp)0
-rw-r--r--src/quick/particles/qquickcumulativedirection_p.h67
-rw-r--r--src/quick/particles/qquickcustomaffector.cpp (renamed from src/declarative/particles/qquickcustomaffector.cpp)0
-rw-r--r--src/quick/particles/qquickcustomaffector_p.h162
-rw-r--r--src/quick/particles/qquickcustomparticle.cpp596
-rw-r--r--src/quick/particles/qquickcustomparticle_p.h119
-rw-r--r--src/quick/particles/qquickdirection.cpp (renamed from src/declarative/particles/qquickdirection.cpp)0
-rw-r--r--src/quick/particles/qquickdirection_p.h68
-rw-r--r--src/quick/particles/qquickellipseextruder.cpp (renamed from src/declarative/particles/qquickellipseextruder.cpp)0
-rw-r--r--src/quick/particles/qquickellipseextruder_p.h83
-rw-r--r--src/quick/particles/qquickfriction.cpp (renamed from src/declarative/particles/qquickfriction.cpp)0
-rw-r--r--src/quick/particles/qquickfriction_p.h101
-rw-r--r--src/quick/particles/qquickgravity.cpp (renamed from src/declarative/particles/qquickgravity.cpp)0
-rw-r--r--src/quick/particles/qquickgravity_p.h115
-rw-r--r--src/quick/particles/qquickgroupgoal.cpp (renamed from src/declarative/particles/qquickgroupgoal.cpp)0
-rw-r--r--src/quick/particles/qquickgroupgoal_p.h100
-rw-r--r--src/quick/particles/qquickimageparticle.cpp1804
-rw-r--r--src/quick/particles/qquickimageparticle_p.h427
-rw-r--r--src/quick/particles/qquickitemparticle.cpp269
-rw-r--r--src/quick/particles/qquickitemparticle_p.h137
-rw-r--r--src/quick/particles/qquicklineextruder.cpp (renamed from src/declarative/particles/qquicklineextruder.cpp)0
-rw-r--r--src/quick/particles/qquicklineextruder_p.h (renamed from src/declarative/particles/qquicklineextruder_p.h)0
-rw-r--r--src/quick/particles/qquickmaskextruder.cpp (renamed from src/declarative/particles/qquickmaskextruder.cpp)0
-rw-r--r--src/quick/particles/qquickmaskextruder_p.h95
-rw-r--r--src/quick/particles/qquickparticleaffector.cpp (renamed from src/declarative/particles/qquickparticleaffector.cpp)0
-rw-r--r--src/quick/particles/qquickparticleaffector_p.h199
-rw-r--r--src/quick/particles/qquickparticleemitter.cpp (renamed from src/declarative/particles/qquickparticleemitter.cpp)0
-rw-r--r--src/quick/particles/qquickparticleemitter_p.h349
-rw-r--r--src/quick/particles/qquickparticleextruder.cpp (renamed from src/declarative/particles/qquickparticleextruder.cpp)0
-rw-r--r--src/quick/particles/qquickparticleextruder_p.h71
-rw-r--r--src/quick/particles/qquickparticlegroup.cpp (renamed from src/declarative/particles/qquickparticlegroup.cpp)0
-rw-r--r--src/quick/particles/qquickparticlegroup_p.h (renamed from src/declarative/particles/qquickparticlegroup_p.h)0
-rw-r--r--src/quick/particles/qquickparticlepainter.cpp (renamed from src/declarative/particles/qquickparticlepainter.cpp)0
-rw-r--r--src/quick/particles/qquickparticlepainter_p.h129
-rw-r--r--src/quick/particles/qquickparticlesmodule.cpp (renamed from src/declarative/particles/qquickparticlesmodule.cpp)0
-rw-r--r--src/quick/particles/qquickparticlesmodule_p.h61
-rw-r--r--src/quick/particles/qquickparticlesystem.cpp1106
-rw-r--r--src/quick/particles/qquickparticlesystem_p.h378
-rw-r--r--src/quick/particles/qquickpointattractor.cpp (renamed from src/declarative/particles/qquickpointattractor.cpp)0
-rw-r--r--src/quick/particles/qquickpointattractor_p.h167
-rw-r--r--src/quick/particles/qquickpointdirection.cpp (renamed from src/declarative/particles/qquickpointdirection.cpp)0
-rw-r--r--src/quick/particles/qquickpointdirection_p.h133
-rw-r--r--src/quick/particles/qquickrectangleextruder.cpp (renamed from src/declarative/particles/qquickrectangleextruder.cpp)0
-rw-r--r--src/quick/particles/qquickrectangleextruder_p.h86
-rw-r--r--src/quick/particles/qquickspritegoal.cpp (renamed from src/declarative/particles/qquickspritegoal.cpp)0
-rw-r--r--src/quick/particles/qquickspritegoal_p.h123
-rw-r--r--src/quick/particles/qquicktargetdirection.cpp (renamed from src/declarative/particles/qquicktargetdirection.cpp)0
-rw-r--r--src/quick/particles/qquicktargetdirection_p.h189
-rw-r--r--src/quick/particles/qquicktrailemitter.cpp (renamed from src/declarative/particles/qquicktrailemitter.cpp)0
-rw-r--r--src/quick/particles/qquicktrailemitter_p.h168
-rw-r--r--src/quick/particles/qquickturbulence.cpp (renamed from src/declarative/particles/qquickturbulence.cpp)0
-rw-r--r--src/quick/particles/qquickturbulence_p.h116
-rw-r--r--src/quick/particles/qquickv8particledata.cpp (renamed from src/declarative/particles/qquickv8particledata.cpp)0
-rw-r--r--src/quick/particles/qquickv8particledata_p.h67
-rw-r--r--src/quick/particles/qquickwander.cpp (renamed from src/declarative/particles/qquickwander.cpp)0
-rw-r--r--src/quick/particles/qquickwander_p.h158
-rw-r--r--src/quick/qtquick2.cpp193
-rw-r--r--src/quick/qtquick2_p.h61
-rw-r--r--src/quick/qtquickglobal.h67
-rw-r--r--src/quick/qtquickglobal_p.h60
-rw-r--r--src/quick/quick.pro47
-rw-r--r--src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp (renamed from src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp)0
-rw-r--r--src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h119
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp (renamed from src/declarative/scenegraph/coreapi/qsggeometry.cpp)0
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.h294
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry_p.h (renamed from src/declarative/scenegraph/coreapi/qsggeometry_p.h)0
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp (renamed from src/declarative/scenegraph/coreapi/qsgmaterial.cpp)0
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.h143
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp1264
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h346
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater.cpp (renamed from src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp)0
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater_p.h86
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp (renamed from src/declarative/scenegraph/coreapi/qsgrenderer.cpp)0
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h232
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp315
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h255
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp513
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h142
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp104
-rw-r--r--src/quick/scenegraph/qsgcontextplugin_p.h80
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp324
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h165
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode.cpp (renamed from src/declarative/scenegraph/qsgdefaultglyphnode.cpp)0
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp306
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h85
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p_p.h96
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp293
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode_p.h88
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode.cpp548
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode_p.h106
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp316
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp725
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h105
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h140
-rw-r--r--src/quick/scenegraph/qsgflashnode.cpp (renamed from src/declarative/scenegraph/qsgflashnode.cpp)0
-rw-r--r--src/quick/scenegraph/qsgflashnode_p.h67
-rw-r--r--src/quick/scenegraph/qsgpathsimplifier.cpp (renamed from src/declarative/scenegraph/qsgpathsimplifier.cpp)0
-rw-r--r--src/quick/scenegraph/qsgpathsimplifier_p.h (renamed from src/declarative/scenegraph/qsgpathsimplifier_p.h)0
-rw-r--r--src/quick/scenegraph/scenegraph.pri (renamed from src/declarative/scenegraph/scenegraph.pri)0
-rw-r--r--src/quick/scenegraph/util/qsgareaallocator.cpp (renamed from src/declarative/scenegraph/util/qsgareaallocator.cpp)0
-rw-r--r--src/quick/scenegraph/util/qsgareaallocator_p.h74
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp805
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil_p.h111
-rw-r--r--src/quick/scenegraph/util/qsgengine.cpp115
-rw-r--r--src/quick/scenegraph/util/qsgengine.h100
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp202
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.h72
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp464
-rw-r--r--src/quick/scenegraph/util/qsgpainternode_p.h158
-rw-r--r--src/quick/scenegraph/util/qsgsimplematerial.h220
-rw-r--r--src/quick/scenegraph/util/qsgsimplerectnode.cpp (renamed from src/declarative/scenegraph/util/qsgsimplerectnode.cpp)0
-rw-r--r--src/quick/scenegraph/util/qsgsimplerectnode.h75
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp154
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.h80
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp541
-rw-r--r--src/quick/scenegraph/util/qsgtexture.h132
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h119
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp (renamed from src/declarative/scenegraph/util/qsgtexturematerial.cpp)0
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.h99
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h71
-rw-r--r--src/quick/scenegraph/util/qsgtextureprovider.cpp (renamed from src/declarative/scenegraph/util/qsgtextureprovider.cpp)0
-rw-r--r--src/quick/scenegraph/util/qsgtextureprovider_p.h66
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp173
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.h67
-rw-r--r--src/quick/util/qdeclarativeanimation.cpp (renamed from src/declarative/util/qdeclarativeanimation.cpp)0
-rw-r--r--src/quick/util/qdeclarativeanimation_p.h456
-rw-r--r--src/quick/util/qdeclarativeanimation_p_p.h (renamed from src/declarative/util/qdeclarativeanimation_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativebehavior.cpp (renamed from src/declarative/util/qdeclarativebehavior.cpp)0
-rw-r--r--src/quick/util/qdeclarativebehavior_p.h95
-rw-r--r--src/quick/util/qdeclarativebind.cpp (renamed from src/declarative/util/qdeclarativebind.cpp)0
-rw-r--r--src/quick/util/qdeclarativebind_p.h96
-rw-r--r--src/quick/util/qdeclarativechangeset.cpp (renamed from src/declarative/util/qdeclarativechangeset.cpp)0
-rw-r--r--src/quick/util/qdeclarativechangeset_p.h (renamed from src/declarative/util/qdeclarativechangeset_p.h)0
-rw-r--r--src/quick/util/qdeclarativeconnections.cpp (renamed from src/declarative/util/qdeclarativeconnections.cpp)0
-rw-r--r--src/quick/util/qdeclarativeconnections_p.h100
-rw-r--r--src/quick/util/qdeclarativefontloader.cpp (renamed from src/declarative/util/qdeclarativefontloader.cpp)0
-rw-r--r--src/quick/util/qdeclarativefontloader_p.h95
-rw-r--r--src/quick/util/qdeclarativelistaccessor.cpp (renamed from src/declarative/util/qdeclarativelistaccessor.cpp)0
-rw-r--r--src/quick/util/qdeclarativelistaccessor_p.h78
-rw-r--r--src/quick/util/qdeclarativelistcompositor.cpp (renamed from src/declarative/util/qdeclarativelistcompositor.cpp)0
-rw-r--r--src/quick/util/qdeclarativelistcompositor_p.h (renamed from src/declarative/util/qdeclarativelistcompositor_p.h)0
-rw-r--r--src/quick/util/qdeclarativepackage.cpp (renamed from src/declarative/util/qdeclarativepackage.cpp)0
-rw-r--r--src/quick/util/qdeclarativepackage_p.h96
-rw-r--r--src/quick/util/qdeclarativepath.cpp (renamed from src/declarative/util/qdeclarativepath.cpp)0
-rw-r--r--src/quick/util/qdeclarativepath_p.h450
-rw-r--r--src/quick/util/qdeclarativepath_p_p.h (renamed from src/declarative/util/qdeclarativepath_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativepathinterpolator.cpp (renamed from src/declarative/util/qdeclarativepathinterpolator.cpp)0
-rw-r--r--src/quick/util/qdeclarativepathinterpolator_p.h98
-rw-r--r--src/quick/util/qdeclarativepixmapcache.cpp1241
-rw-r--r--src/quick/util/qdeclarativepixmapcache_p.h142
-rw-r--r--src/quick/util/qdeclarativepropertychanges.cpp (renamed from src/declarative/util/qdeclarativepropertychanges.cpp)0
-rw-r--r--src/quick/util/qdeclarativepropertychanges_p.h110
-rw-r--r--src/quick/util/qdeclarativesmoothedanimation.cpp (renamed from src/declarative/util/qdeclarativesmoothedanimation.cpp)0
-rw-r--r--src/quick/util/qdeclarativesmoothedanimation_p.h101
-rw-r--r--src/quick/util/qdeclarativesmoothedanimation_p_p.h (renamed from src/declarative/util/qdeclarativesmoothedanimation_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativespringanimation.cpp (renamed from src/declarative/util/qdeclarativespringanimation.cpp)0
-rw-r--r--src/quick/util/qdeclarativespringanimation_p.h109
-rw-r--r--src/quick/util/qdeclarativestate.cpp (renamed from src/declarative/util/qdeclarativestate.cpp)0
-rw-r--r--src/quick/util/qdeclarativestate_p.h208
-rw-r--r--src/quick/util/qdeclarativestate_p_p.h (renamed from src/declarative/util/qdeclarativestate_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativestategroup.cpp (renamed from src/declarative/util/qdeclarativestategroup.cpp)0
-rw-r--r--src/quick/util/qdeclarativestategroup_p.h95
-rw-r--r--src/quick/util/qdeclarativestateoperations.cpp (renamed from src/declarative/util/qdeclarativestateoperations.cpp)0
-rw-r--r--src/quick/util/qdeclarativestateoperations_p.h85
-rw-r--r--src/quick/util/qdeclarativestyledtext.cpp (renamed from src/declarative/util/qdeclarativestyledtext.cpp)0
-rw-r--r--src/quick/util/qdeclarativestyledtext_p.h (renamed from src/declarative/util/qdeclarativestyledtext_p.h)0
-rw-r--r--src/quick/util/qdeclarativesvgparser.cpp (renamed from src/declarative/util/qdeclarativesvgparser.cpp)0
-rw-r--r--src/quick/util/qdeclarativesvgparser_p.h (renamed from src/declarative/util/qdeclarativesvgparser_p.h)0
-rw-r--r--src/quick/util/qdeclarativesystempalette.cpp (renamed from src/declarative/util/qdeclarativesystempalette.cpp)0
-rw-r--r--src/quick/util/qdeclarativesystempalette_p.h120
-rw-r--r--src/quick/util/qdeclarativetimeline.cpp (renamed from src/declarative/util/qdeclarativetimeline.cpp)0
-rw-r--r--src/quick/util/qdeclarativetimeline_p_p.h (renamed from src/declarative/util/qdeclarativetimeline_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativetimer.cpp (renamed from src/declarative/util/qdeclarativetimer.cpp)0
-rw-r--r--src/quick/util/qdeclarativetimer_p.h113
-rw-r--r--src/quick/util/qdeclarativetransition.cpp (renamed from src/declarative/util/qdeclarativetransition.cpp)0
-rw-r--r--src/quick/util/qdeclarativetransition_p.h109
-rw-r--r--src/quick/util/qdeclarativetransitionmanager.cpp (renamed from src/declarative/util/qdeclarativetransitionmanager.cpp)0
-rw-r--r--src/quick/util/qdeclarativetransitionmanager_p_p.h (renamed from src/declarative/util/qdeclarativetransitionmanager_p_p.h)0
-rw-r--r--src/quick/util/qdeclarativeutilmodule.cpp (renamed from src/declarative/util/qdeclarativeutilmodule.cpp)0
-rw-r--r--src/quick/util/qdeclarativeutilmodule_p.h61
-rw-r--r--src/quick/util/util.pri59
-rw-r--r--src/src.pro2
-rw-r--r--sync.profile83
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/declarative/debugger/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativeenginedebug/qdeclarativeenginedebug.pro2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativeinspector/app/app.pro2
-rw-r--r--tests/auto/declarative/debugger/qdeclarativeinspector/app/main.cpp2
-rw-r--r--tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp2
-rw-r--r--tests/auto/declarative/declarative.pro52
-rw-r--r--tests/auto/declarative/examples/examples.pro10
-rw-r--r--tests/auto/declarative/examples/tst_examples.cpp253
-rw-r--r--tests/auto/declarative/geometry/geometry.pro9
-rw-r--r--tests/auto/declarative/geometry/tst_geometry.cpp181
-rw-r--r--tests/auto/declarative/nodes/nodes.pro9
-rw-r--r--tests/auto/declarative/nodes/tst_nodestest.cpp354
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro12
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp1106
-rw-r--r--tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro7
-rw-r--r--tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp143
-rw-r--r--tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro12
-rw-r--r--tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp474
-rw-r--r--tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro2
-rw-r--r--tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativechangeset/qdeclarativechangeset.pro2
-rw-r--r--tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro6
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeerror/tst_qdeclarativeerror.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeexpression/tst_qdeclarativeexpression.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro14
-rw-r--r--tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp254
-rw-r--r--tests/auto/declarative/qdeclarativeimageprovider/qdeclarativeimageprovider.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeincubator/tst_qdeclarativeincubator.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeinfo/tst_qdeclarativeinfo.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro6
-rw-r--r--tests/auto/declarative/qdeclarativelistcompositor/qdeclarativelistcompositor.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp6
-rw-r--r--tests/auto/declarative/qdeclarativelistreference/tst_qdeclarativelistreference.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro4
-rw-r--r--tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro13
-rw-r--r--tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp164
-rw-r--r--tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro20
-rw-r--r--tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp458
-rw-r--r--tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativepropertymap/qdeclarativepropertymap.pro2
-rw-r--r--tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro13
-rw-r--r--tests/auto/declarative/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp211
-rw-r--r--tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro13
-rw-r--r--tests/auto/declarative/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp131
-rw-r--r--tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro2
-rw-r--r--tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro12
-rw-r--r--tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp1596
-rw-r--r--tests/auto/declarative/qdeclarativestyledtext/qdeclarativestyledtext.pro8
-rw-r--r--tests/auto/declarative/qdeclarativesystempalette/qdeclarativesystempalette.pro8
-rw-r--r--tests/auto/declarative/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp185
-rw-r--r--tests/auto/declarative/qdeclarativetimer/qdeclarativetimer.pro8
-rw-r--r--tests/auto/declarative/qdeclarativetimer/tst_qdeclarativetimer.cpp334
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro6
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp961
-rw-r--r--tests/auto/declarative/qmlmin/tst_qmlmin.cpp2
-rw-r--r--tests/auto/declarative/qquickanchors/qquickanchors.pro12
-rw-r--r--tests/auto/declarative/qquickanchors/tst_qquickanchors.cpp692
-rw-r--r--tests/auto/declarative/qquickanimatedimage/qquickanimatedimage.pro13
-rw-r--r--tests/auto/declarative/qquickanimatedimage/tst_qquickanimatedimage.cpp378
-rw-r--r--tests/auto/declarative/qquickborderimage/qquickborderimage.pro14
-rw-r--r--tests/auto/declarative/qquickborderimage/tst_qquickborderimage.cpp376
-rw-r--r--tests/auto/declarative/qquickcanvas/qquickcanvas.pro8
-rw-r--r--tests/auto/declarative/qquickcanvas/tst_qquickcanvas.cpp557
-rw-r--r--tests/auto/declarative/qquickdrag/qquickdrag.pro9
-rw-r--r--tests/auto/declarative/qquickdrag/tst_qquickdrag.cpp827
-rw-r--r--tests/auto/declarative/qquickdroparea/qquickdroparea.pro9
-rw-r--r--tests/auto/declarative/qquickdroparea/tst_qquickdroparea.cpp1117
-rw-r--r--tests/auto/declarative/qquickflickable/qquickflickable.pro12
-rw-r--r--tests/auto/declarative/qquickflickable/tst_qquickflickable.cpp662
-rw-r--r--tests/auto/declarative/qquickflipable/qquickflipable.pro13
-rw-r--r--tests/auto/declarative/qquickflipable/tst_qquickflipable.cpp150
-rw-r--r--tests/auto/declarative/qquickfocusscope/qquickfocusscope.pro10
-rw-r--r--tests/auto/declarative/qquickfocusscope/tst_qquickfocusscope.cpp668
-rw-r--r--tests/auto/declarative/qquickgridview/qquickgridview.pro13
-rw-r--r--tests/auto/declarative/qquickgridview/tst_qquickgridview.cpp3705
-rw-r--r--tests/auto/declarative/qquickimage/qquickimage.pro13
-rw-r--r--tests/auto/declarative/qquickimage/tst_qquickimage.cpp732
-rw-r--r--tests/auto/declarative/qquickitem/qquickitem.pro12
-rw-r--r--tests/auto/declarative/qquickitem/tst_qquickitem.cpp1190
-rw-r--r--tests/auto/declarative/qquickitem2/qquickitem2.pro13
-rw-r--r--tests/auto/declarative/qquickitem2/tst_qquickitem.cpp1254
-rw-r--r--tests/auto/declarative/qquicklistview/qquicklistview.pro13
-rw-r--r--tests/auto/declarative/qquicklistview/tst_qquicklistview.cpp4379
-rw-r--r--tests/auto/declarative/qquickloader/qquickloader.pro16
-rw-r--r--tests/auto/declarative/qquickloader/tst_qquickloader.cpp969
-rw-r--r--tests/auto/declarative/qquickmousearea/qquickmousearea.pro14
-rw-r--r--tests/auto/declarative/qquickmousearea/tst_qquickmousearea.cpp824
-rw-r--r--tests/auto/declarative/qquickmultipointtoucharea/qquickmultipointtoucharea.pro11
-rw-r--r--tests/auto/declarative/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp586
-rw-r--r--tests/auto/declarative/qquickpathview/qquickpathview.pro12
-rw-r--r--tests/auto/declarative/qquickpathview/tst_qquickpathview.cpp1629
-rw-r--r--tests/auto/declarative/qquickpincharea/qquickpincharea.pro13
-rw-r--r--tests/auto/declarative/qquickpincharea/tst_qquickpincharea.cpp395
-rw-r--r--tests/auto/declarative/qquickpositioners/qquickpositioners.pro11
-rw-r--r--tests/auto/declarative/qquickpositioners/tst_qquickpositioners.cpp1473
-rw-r--r--tests/auto/declarative/qquickrepeater/qquickrepeater.pro12
-rw-r--r--tests/auto/declarative/qquickrepeater/tst_qquickrepeater.cpp765
-rw-r--r--tests/auto/declarative/qquickshadereffect/qquickshadereffect.pro8
-rw-r--r--tests/auto/declarative/qquickspriteimage/qquickspriteimage.pro12
-rw-r--r--tests/auto/declarative/qquickspriteimage/tst_qquickspriteimage.cpp81
-rw-r--r--tests/auto/declarative/qquicktext/qquicktext.pro17
-rw-r--r--tests/auto/declarative/qquicktext/tst_qquicktext.cpp1460
-rw-r--r--tests/auto/declarative/qquicktextedit/qquicktextedit.pro12
-rw-r--r--tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp3555
-rw-r--r--tests/auto/declarative/qquicktextinput/qquicktextinput.pro11
-rw-r--r--tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp3310
-rw-r--r--tests/auto/declarative/qquickview/qquickview.pro11
-rw-r--r--tests/auto/declarative/qquickview/tst_qquickview.cpp207
-rw-r--r--tests/auto/declarative/qquickvisualdatamodel/qquickvisualdatamodel.pro13
-rw-r--r--tests/auto/declarative/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp1865
-rw-r--r--tests/auto/declarative/v4/tst_v4.cpp2
-rw-r--r--tests/auto/particles/qquickage/qquickage.pro2
-rw-r--r--tests/auto/particles/qquickangleddirection/qquickangleddirection.pro2
-rw-r--r--tests/auto/particles/qquickcumulativedirection/qquickcumulativedirection.pro2
-rw-r--r--tests/auto/particles/qquickcustomaffector/qquickcustomaffector.pro2
-rw-r--r--tests/auto/particles/qquickcustomparticle/qquickcustomparticle.pro2
-rw-r--r--tests/auto/particles/qquickellipseextruder/qquickellipseextruder.pro2
-rw-r--r--tests/auto/particles/qquickfriction/qquickfriction.pro2
-rw-r--r--tests/auto/particles/qquickgravity/qquickgravity.pro2
-rw-r--r--tests/auto/particles/qquickimageparticle/qquickimageparticle.pro2
-rw-r--r--tests/auto/particles/qquickitemparticle/qquickitemparticle.pro2
-rw-r--r--tests/auto/particles/qquicklineextruder/qquicklineextruder.pro2
-rw-r--r--tests/auto/particles/qquickmaskextruder/qquickmaskextruder.pro2
-rw-r--r--tests/auto/particles/qquickparticlegroup/qquickparticlegroup.pro2
-rw-r--r--tests/auto/particles/qquickparticlesystem/qquickparticlesystem.pro2
-rw-r--r--tests/auto/particles/qquickpointattractor/qquickpointattractor.pro2
-rw-r--r--tests/auto/particles/qquickpointdirection/qquickpointdirection.pro2
-rw-r--r--tests/auto/particles/qquickrectangleextruder/qquickrectangleextruder.pro2
-rw-r--r--tests/auto/particles/qquicktargetdirection/qquicktargetdirection.pro2
-rw-r--r--tests/auto/particles/qquicktrailemitter/qquicktrailemitter.pro2
-rw-r--r--tests/auto/particles/qquickturbulence/qquickturbulence.pro2
-rw-r--r--tests/auto/particles/qquickwander/qquickwander.pro2
-rw-r--r--tests/auto/particles/shared/particlestestsshared.h2
-rw-r--r--tests/auto/qtquick1/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp2
-rw-r--r--tests/auto/qtquick1/qdeclarativeborderimage/qdeclarativeborderimage.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp2
-rw-r--r--tests/auto/qtquick1/qdeclarativefontloader/qdeclarativefontloader.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativefontloader/tst_qdeclarativefontloader.cpp2
-rw-r--r--tests/auto/qtquick1/qdeclarativeimage/qdeclarativeimage.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativeimage/tst_qdeclarativeimage.cpp2
-rw-r--r--tests/auto/qtquick1/qdeclarativeloader/qdeclarativeloader.pro6
-rw-r--r--tests/auto/qtquick1/qdeclarativemousearea/qdeclarativemousearea.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro6
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro4
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp2
-rw-r--r--tests/auto/qtquick2/examples/data/dummytest.qml (renamed from tests/auto/declarative/examples/data/dummytest.qml)0
-rw-r--r--tests/auto/qtquick2/examples/data/webbrowser/webbrowser.qml (renamed from tests/auto/declarative/examples/data/webbrowser/webbrowser.qml)0
-rw-r--r--tests/auto/qtquick2/examples/examples.pro10
-rw-r--r--tests/auto/qtquick2/examples/tst_examples.cpp253
-rw-r--r--tests/auto/qtquick2/geometry/geometry.pro9
-rw-r--r--tests/auto/qtquick2/geometry/tst_geometry.cpp181
-rw-r--r--tests/auto/qtquick2/nodes/nodes.pro9
-rw-r--r--tests/auto/qtquick2/nodes/tst_nodestest.cpp354
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/Double.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/Double.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/attached.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/attached.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badproperty1.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badproperty1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badproperty2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badproperty2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badtype1.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badtype1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badtype2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badtype2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badtype3.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badtype3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/badtype4.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/badtype4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/disabledTransition.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/disabledTransition.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/dontAutoStart.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/dontAutoStart.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/dontStart.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/dontStart.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/dontStart2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/dontStart2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/dotproperty.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/dotproperty.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/doubleRegistrationBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype1.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/mixedtype1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/mixedtype2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/nonTransitionBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/nonTransitionBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathAnimation2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimationNoStart.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathAnimationNoStart.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolator.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathInterpolatorBack.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathTransition.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pauseBindingBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pauseBindingBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pauseBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/pauseBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/properties.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/properties.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/properties2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/properties2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/properties3.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/properties3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/properties4.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/properties4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/properties5.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/properties5.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition3.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition4.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition5.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition5.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition6.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition6.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition7.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition7.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/registrationBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/rotation.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/rotation.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/runningTrueBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/runningTrueBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/transitionAssignmentBug.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/transitionAssignmentBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/valuesource.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/valuesource.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/valuesource2.qml (renamed from tests/auto/declarative/qdeclarativeanimations/data/valuesource2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/qdeclarativeanimations.pro12
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp1106
-rw-r--r--tests/auto/qtquick2/qdeclarativeapplication/qdeclarativeapplication.pro7
-rw-r--r--tests/auto/qtquick2/qdeclarativeapplication/tst_qdeclarativeapplication.cpp143
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/binding.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/binding.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/color.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/color.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/cpptrigger.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/cpptrigger.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/delayedRegistration.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/disabled.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/disabled.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/dontStart.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/empty.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/empty.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/explicit.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/explicit.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/groupProperty.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty2.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/groupProperty2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/groupedPropertyCrash.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/groupedPropertyCrash.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/loop.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/loop.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/nonSelecting2.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/nonSelecting2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/parent.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/parent.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/qtbug12295.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/reassignedAnimation.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/runningTrue.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/runningTrue.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/scripttrigger.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/scripttrigger.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/simple.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/simple.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/startOnCompleted.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/startOnCompleted.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/startup.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/startup.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/startup2.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/startup2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/data/valueType.qml (renamed from tests/auto/declarative/qdeclarativebehaviors/data/valueType.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/qdeclarativebehaviors.pro12
-rw-r--r--tests/auto/qtquick2/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp474
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/data/daniel.ttf (renamed from tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf)bin51984 -> 51984 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/data/dummy.ttf (renamed from tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf)0
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/data/qtbug-20268.qml (renamed from tests/auto/declarative/qdeclarativefontloader/data/qtbug-20268.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/data/tarzeau_ocr_a.ttf (renamed from tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf)bin24544 -> 24544 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/qdeclarativefontloader.pro14
-rw-r--r--tests/auto/qtquick2/qdeclarativefontloader/tst_qdeclarativefontloader.cpp254
-rw-r--r--tests/auto/qtquick2/qdeclarativepath/data/arc.qml (renamed from tests/auto/declarative/qdeclarativepath/data/arc.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativepath/data/curve.qml (renamed from tests/auto/declarative/qdeclarativepath/data/curve.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativepath/data/svg.qml (renamed from tests/auto/declarative/qdeclarativepath/data/svg.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativepath/qdeclarativepath.pro13
-rw-r--r--tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp164
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/exists.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/exists.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/exists1.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/exists1.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/exists2.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/exists2.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists1.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists1.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists2.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists2.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists3.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists3.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists4.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists4.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists5.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists5.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists6.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists6.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists7.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists7.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists8.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/http/exists8.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/data/massive.png (renamed from tests/auto/declarative/qdeclarativepixmapcache/data/massive.png)bin31834 -> 31834 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/qdeclarativepixmapcache.pro20
-rw-r--r--tests/auto/qtquick2/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp458
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation1.qml (renamed from tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation2.qml (renamed from tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation3.qml (renamed from tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml (renamed from tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml (renamed from tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro13
-rw-r--r--tests/auto/qtquick2/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp211
-rw-r--r--tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation1.qml (renamed from tests/auto/declarative/qdeclarativespringanimation/data/springanimation1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation2.qml (renamed from tests/auto/declarative/qdeclarativespringanimation/data/springanimation2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation3.qml (renamed from tests/auto/declarative/qdeclarativespringanimation/data/springanimation3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativespringanimation/qdeclarativespringanimation.pro13
-rw-r--r--tests/auto/qtquick2/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp131
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/ExtendedRectangle.qml (renamed from tests/auto/declarative/qdeclarativestates/data/ExtendedRectangle.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/Implementation/MyType.qml (renamed from tests/auto/declarative/qdeclarativestates/data/Implementation/MyType.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/Implementation/images/qt-logo.png (renamed from tests/auto/declarative/qdeclarativestates/data/Implementation/images/qt-logo.png)bin5149 -> 5149 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/QTBUG-14830.qml (renamed from tests/auto/declarative/qdeclarativestates/data/QTBUG-14830.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChanges1.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChanges1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChanges2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChanges2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChanges3.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChanges3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChanges4.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChanges4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChanges5.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChanges5.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorChangesCrash.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorChangesCrash.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorRewindBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/attachedPropertyChanges.qml (renamed from tests/auto/declarative/qdeclarativestates/data/attachedPropertyChanges.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml (renamed from tests/auto/declarative/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/avoidFastForward.qml (renamed from tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicBinding.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicBinding.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicBinding2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicBinding2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicBinding3.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicBinding3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicBinding4.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicBinding4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicChanges.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicChanges.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicChanges2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicChanges2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicChanges3.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicChanges3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicChanges4.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/basicExtension.qml (renamed from tests/auto/declarative/qdeclarativestates/data/basicExtension.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/deleting.qml (renamed from tests/auto/declarative/qdeclarativestates/data/deleting.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/deletingState.qml (renamed from tests/auto/declarative/qdeclarativestates/data/deletingState.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/editProperties.qml (renamed from tests/auto/declarative/qdeclarativestates/data/editProperties.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/explicit.qml (renamed from tests/auto/declarative/qdeclarativestates/data/explicit.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/extendsBug.qml (renamed from tests/auto/declarative/qdeclarativestates/data/extendsBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/fakeExtension.qml (renamed from tests/auto/declarative/qdeclarativestates/data/fakeExtension.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/illegalObj.qml (renamed from tests/auto/declarative/qdeclarativestates/data/illegalObj.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/illegalTempState.qml (renamed from tests/auto/declarative/qdeclarativestates/data/illegalTempState.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/image.png (renamed from tests/auto/declarative/qdeclarativestates/data/image.png)bin173 -> 173 bytes
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/legalTempState.qml (renamed from tests/auto/declarative/qdeclarativestates/data/legalTempState.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/nonExistantProp.qml (renamed from tests/auto/declarative/qdeclarativestates/data/nonExistantProp.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange1.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange1.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange3.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange4.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange4.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange5.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange5.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/parentChange6.qml (renamed from tests/auto/declarative/qdeclarativestates/data/parentChange6.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/propertyErrors.qml (renamed from tests/auto/declarative/qdeclarativestates/data/propertyErrors.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/reset.qml (renamed from tests/auto/declarative/qdeclarativestates/data/reset.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/restoreEntryValues.qml (renamed from tests/auto/declarative/qdeclarativestates/data/restoreEntryValues.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/returnToBase.qml (renamed from tests/auto/declarative/qdeclarativestates/data/returnToBase.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/revertListBug.qml (renamed from tests/auto/declarative/qdeclarativestates/data/revertListBug.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/script.qml (renamed from tests/auto/declarative/qdeclarativestates/data/script.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/signalOverride.qml (renamed from tests/auto/declarative/qdeclarativestates/data/signalOverride.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/signalOverride2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/signalOverride2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash.qml (renamed from tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash2.qml (renamed from tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash2.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash3.qml (renamed from tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash3.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/unnamedWhen.qml (renamed from tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/urlResolution.qml (renamed from tests/auto/declarative/qdeclarativestates/data/urlResolution.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/data/whenOrdering.qml (renamed from tests/auto/declarative/qdeclarativestates/data/whenOrdering.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/qdeclarativestates.pro12
-rw-r--r--tests/auto/qtquick2/qdeclarativestates/tst_qdeclarativestates.cpp1596
-rw-r--r--tests/auto/qtquick2/qdeclarativestyledtext/qdeclarativestyledtext.pro8
-rw-r--r--tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp (renamed from tests/auto/declarative/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp)0
-rw-r--r--tests/auto/qtquick2/qdeclarativesystempalette/qdeclarativesystempalette.pro8
-rw-r--r--tests/auto/qtquick2/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp185
-rw-r--r--tests/auto/qtquick2/qdeclarativetimer/qdeclarativetimer.pro8
-rw-r--r--tests/auto/qtquick2/qdeclarativetimer/tst_qdeclarativetimer.cpp334
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/empty.xml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/empty.xml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/get.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/get.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.xml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/model2.xml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/model2.xml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/propertychanges.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/propertychanges.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.xml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleCrash.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/roleCrash.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleErrors.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleKeys.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/testtypes.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/data/unique.qml (renamed from tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro (renamed from tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro)0
-rw-r--r--tests/auto/qtquick2/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp961
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/anchors.qml (renamed from tests/auto/declarative/qquickanchors/data/anchors.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/centerin.qml (renamed from tests/auto/declarative/qquickanchors/data/centerin.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/centerinRotation.qml (renamed from tests/auto/declarative/qquickanchors/data/centerinRotation.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/crash1.qml (renamed from tests/auto/declarative/qquickanchors/data/crash1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/fill.qml (renamed from tests/auto/declarative/qquickanchors/data/fill.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/hvCenter.qml (renamed from tests/auto/declarative/qquickanchors/data/hvCenter.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/loop1.qml (renamed from tests/auto/declarative/qquickanchors/data/loop1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/loop2.qml (renamed from tests/auto/declarative/qquickanchors/data/loop2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/data/margins.qml (renamed from tests/auto/declarative/qquickanchors/data/margins.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanchors/qquickanchors.pro12
-rw-r--r--tests/auto/qtquick2/qquickanchors/tst_qquickanchors.cpp692
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/colors.gif (renamed from tests/auto/declarative/qquickanimatedimage/data/colors.gif)bin505 -> 505 bytes
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/colors.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/colors.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/hearts.gif (renamed from tests/auto/declarative/qquickanimatedimage/data/hearts.gif)bin6524 -> 6524 bytes
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/hearts.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/hearts.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/qmldir (renamed from tests/auto/declarative/qquickanimatedimage/data/qmldir)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/qtbug-16520.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/qtbug-16520.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickman.gif (renamed from tests/auto/declarative/qquickanimatedimage/data/stickman.gif)bin164923 -> 164923 bytes
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickman.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/stickman.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickmanerror1.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/stickmanerror1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickmanpause.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/stickmanpause.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickmanscaled.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/stickmanscaled.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/data/stickmanstopped.qml (renamed from tests/auto/declarative/qquickanimatedimage/data/stickmanstopped.qml)0
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/qquickanimatedimage.pro13
-rw-r--r--tests/auto/qtquick2/qquickanimatedimage/tst_qquickanimatedimage.cpp378
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/colors-mirror.png (renamed from tests/auto/declarative/qquickborderimage/data/colors-mirror.png)bin5554 -> 5554 bytes
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/colors-round-quotes.sci (renamed from tests/auto/declarative/qquickborderimage/data/colors-round-quotes.sci)0
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/colors-round-remote.sci (renamed from tests/auto/declarative/qquickborderimage/data/colors-round-remote.sci)0
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/colors-round.sci (renamed from tests/auto/declarative/qquickborderimage/data/colors-round.sci)0
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/colors.png (renamed from tests/auto/declarative/qquickborderimage/data/colors.png)bin1655 -> 1655 bytes
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/heart200.png (renamed from tests/auto/declarative/qquickborderimage/data/heart200.png)bin7943 -> 7943 bytes
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/invalid.sci (renamed from tests/auto/declarative/qquickborderimage/data/invalid.sci)0
-rw-r--r--tests/auto/qtquick2/qquickborderimage/data/mirror.qml (renamed from tests/auto/declarative/qquickborderimage/data/mirror.qml)0
-rw-r--r--tests/auto/qtquick2/qquickborderimage/qquickborderimage.pro14
-rw-r--r--tests/auto/qtquick2/qquickborderimage/tst_qquickborderimage.cpp376
-rw-r--r--tests/auto/qtquick2/qquickcanvas/data/window.qml (renamed from tests/auto/declarative/qquickcanvas/data/window.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvas/qquickcanvas.pro8
-rw-r--r--tests/auto/qtquick2/qquickcanvas/tst_qquickcanvas.cpp557
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.gif (renamed from tests/auto/declarative/qquickcanvasitem/data/anim-gr.gif)bin241 -> 241 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.png (renamed from tests/auto/declarative/qquickcanvasitem/data/anim-gr.png)bin460 -> 460 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/anim-poster-gr.png (renamed from tests/auto/declarative/qquickcanvasitem/data/anim-poster-gr.png)bin422 -> 422 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/background.png (renamed from tests/auto/declarative/qquickcanvasitem/data/background.png)bin86 -> 86 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/broken.png (renamed from tests/auto/declarative/qquickcanvasitem/data/broken.png)bin87 -> 87 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/ggrr-256x256.png (renamed from tests/auto/declarative/qquickcanvasitem/data/ggrr-256x256.png)bin120 -> 120 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/green-16x16.png (renamed from tests/auto/declarative/qquickcanvasitem/data/green-16x16.png)bin92 -> 92 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/green-1x1.png (renamed from tests/auto/declarative/qquickcanvasitem/data/green-1x1.png)bin82 -> 82 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/green-256x256.png (renamed from tests/auto/declarative/qquickcanvasitem/data/green-256x256.png)bin103 -> 103 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/green-2x2.png (renamed from tests/auto/declarative/qquickcanvasitem/data/green-2x2.png)bin118 -> 118 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/green.png (renamed from tests/auto/declarative/qquickcanvasitem/data/green.png)bin87 -> 87 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/grgr-256x256.png (renamed from tests/auto/declarative/qquickcanvasitem/data/grgr-256x256.png)bin130 -> 130 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/red-16x16.png (renamed from tests/auto/declarative/qquickcanvasitem/data/red-16x16.png)bin130 -> 130 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/red.png (renamed from tests/auto/declarative/qquickcanvasitem/data/red.png)bin87 -> 87 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/redtransparent.png (renamed from tests/auto/declarative/qquickcanvasitem/data/redtransparent.png)bin109 -> 109 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/rgrg-256x256.png (renamed from tests/auto/declarative/qquickcanvasitem/data/rgrg-256x256.png)bin131 -> 131 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/rrgg-256x256.png (renamed from tests/auto/declarative/qquickcanvasitem/data/rrgg-256x256.png)bin120 -> 120 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/testhelper.js (renamed from tests/auto/declarative/qquickcanvasitem/data/testhelper.js)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/transparent.png (renamed from tests/auto/declarative/qquickcanvasitem/data/transparent.png)bin100 -> 100 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/transparent50.png (renamed from tests/auto/declarative/qquickcanvasitem/data/transparent50.png)bin155 -> 155 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_arc.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_arc.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_arcto.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_arcto.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_canvas.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_canvas.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_composite.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_composite.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_drawimage.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_drawimage.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_fillStyle.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_fillStyle.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_fillrect.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_fillrect.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_gradient.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_gradient.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_line.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_line.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_path.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_path.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_pattern.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_pattern.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_pixel.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_pixel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_shadow.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_shadow.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_state.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_state.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_strokeStyle.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_strokeStyle.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_text.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_text.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/tst_transform.qml (renamed from tests/auto/declarative/qquickcanvasitem/data/tst_transform.qml)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/yellow.png (renamed from tests/auto/declarative/qquickcanvasitem/data/yellow.png)bin95 -> 95 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/data/yellow75.png (renamed from tests/auto/declarative/qquickcanvasitem/data/yellow75.png)bin150 -> 150 bytes
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/qquickcanvasitem.pro (renamed from tests/auto/declarative/qquickcanvasitem/qquickcanvasitem.pro)0
-rw-r--r--tests/auto/qtquick2/qquickcanvasitem/tst_qquickcanvasitem.cpp (renamed from tests/auto/declarative/qquickcanvasitem/tst_qquickcanvasitem.cpp)0
-rw-r--r--tests/auto/qtquick2/qquickdrag/qquickdrag.pro9
-rw-r--r--tests/auto/qtquick2/qquickdrag/tst_qquickdrag.cpp827
-rw-r--r--tests/auto/qtquick2/qquickdroparea/qquickdroparea.pro9
-rw-r--r--tests/auto/qtquick2/qquickdroparea/tst_qquickdroparea.cpp1117
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/disabled.qml (renamed from tests/auto/declarative/qquickflickable/data/disabled.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/flickable01.qml (renamed from tests/auto/declarative/qquickflickable/data/flickable01.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/flickable02.qml (renamed from tests/auto/declarative/qquickflickable/data/flickable02.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/flickable03.qml (renamed from tests/auto/declarative/qquickflickable/data/flickable03.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/flickable04.qml (renamed from tests/auto/declarative/qquickflickable/data/flickable04.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/flickableqgraphicswidget.qml (renamed from tests/auto/declarative/qquickflickable/data/flickableqgraphicswidget.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/margins.qml (renamed from tests/auto/declarative/qquickflickable/data/margins.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/nestedPressDelay.qml (renamed from tests/auto/declarative/qquickflickable/data/nestedPressDelay.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/resize.qml (renamed from tests/auto/declarative/qquickflickable/data/resize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/data/wheel.qml (renamed from tests/auto/declarative/qquickflickable/data/wheel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflickable/qquickflickable.pro12
-rw-r--r--tests/auto/qtquick2/qquickflickable/tst_qquickflickable.cpp662
-rw-r--r--tests/auto/qtquick2/qquickflipable/data/crash.qml (renamed from tests/auto/declarative/qquickflipable/data/crash.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflipable/data/flipable-abort.qml (renamed from tests/auto/declarative/qquickflipable/data/flipable-abort.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflipable/data/test-flipable.qml (renamed from tests/auto/declarative/qquickflipable/data/test-flipable.qml)0
-rw-r--r--tests/auto/qtquick2/qquickflipable/qquickflipable.pro13
-rw-r--r--tests/auto/qtquick2/qquickflipable/tst_qquickflipable.cpp150
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/canvasFocus.qml (renamed from tests/auto/declarative/qquickfocusscope/data/canvasFocus.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/chain.qml (renamed from tests/auto/declarative/qquickfocusscope/data/chain.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/forceActiveFocus.qml (renamed from tests/auto/declarative/qquickfocusscope/data/forceActiveFocus.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/forcefocus.qml (renamed from tests/auto/declarative/qquickfocusscope/data/forcefocus.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/qtBug13380.qml (renamed from tests/auto/declarative/qquickfocusscope/data/qtBug13380.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/signalEmission.qml (renamed from tests/auto/declarative/qquickfocusscope/data/signalEmission.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/test.qml (renamed from tests/auto/declarative/qquickfocusscope/data/test.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/test2.qml (renamed from tests/auto/declarative/qquickfocusscope/data/test2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/test3.qml (renamed from tests/auto/declarative/qquickfocusscope/data/test3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/test4.qml (renamed from tests/auto/declarative/qquickfocusscope/data/test4.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/data/test5.qml (renamed from tests/auto/declarative/qquickfocusscope/data/test5.qml)0
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/qquickfocusscope.pro10
-rw-r--r--tests/auto/qtquick2/qquickfocusscope/tst_qquickfocusscope.cpp668
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/ComponentView.qml (renamed from tests/auto/declarative/qquickgridview/data/ComponentView.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/asyncloader.qml (renamed from tests/auto/declarative/qquickgridview/data/asyncloader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/attachedSignals.qml (renamed from tests/auto/declarative/qquickgridview/data/attachedSignals.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/creationContext.qml (renamed from tests/auto/declarative/qquickgridview/data/creationContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/displaygrid.qml (renamed from tests/auto/declarative/qquickgridview/data/displaygrid.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/footer.qml (renamed from tests/auto/declarative/qquickgridview/data/footer.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview-enforcerange.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview-enforcerange.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview-initCurrent.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview-initCurrent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview-noCurrent.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview-noCurrent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview1.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview2.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview3.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/gridview4.qml (renamed from tests/auto/declarative/qquickgridview/data/gridview4.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/header.qml (renamed from tests/auto/declarative/qquickgridview/data/header.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/manual-highlight.qml (renamed from tests/auto/declarative/qquickgridview/data/manual-highlight.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/margins.qml (renamed from tests/auto/declarative/qquickgridview/data/margins.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/mirroring.qml (renamed from tests/auto/declarative/qquickgridview/data/mirroring.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/propertychangestest.qml (renamed from tests/auto/declarative/qquickgridview/data/propertychangestest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/resizeview.qml (renamed from tests/auto/declarative/qquickgridview/data/resizeview.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/setindex.qml (renamed from tests/auto/declarative/qquickgridview/data/setindex.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/snapToRow.qml (renamed from tests/auto/declarative/qquickgridview/data/snapToRow.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/data/unaligned.qml (renamed from tests/auto/declarative/qquickgridview/data/unaligned.qml)0
-rw-r--r--tests/auto/qtquick2/qquickgridview/qquickgridview.pro13
-rw-r--r--tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp3705
-rw-r--r--tests/auto/qtquick2/qquickimage/data/aspectratio.qml (renamed from tests/auto/declarative/qquickimage/data/aspectratio.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/big.jpeg (renamed from tests/auto/declarative/qquickimage/data/big.jpeg)bin1700081 -> 1700081 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/big256.png (renamed from tests/auto/declarative/qquickimage/data/big256.png)bin3566 -> 3566 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/colors.png (renamed from tests/auto/declarative/qquickimage/data/colors.png)bin1655 -> 1655 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/colors1.png (renamed from tests/auto/declarative/qquickimage/data/colors1.png)bin1655 -> 1655 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/green.png (renamed from tests/auto/declarative/qquickimage/data/green.png)bin314 -> 314 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/heart-win32.png (renamed from tests/auto/declarative/qquickimage/data/heart-win32.png)bin12621 -> 12621 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/heart.png (renamed from tests/auto/declarative/qquickimage/data/heart.png)bin12577 -> 12577 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/heart.svg (renamed from tests/auto/declarative/qquickimage/data/heart.svg)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/heart200-win32.png (renamed from tests/auto/declarative/qquickimage/data/heart200-win32.png)bin8062 -> 8062 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/heart200.png (renamed from tests/auto/declarative/qquickimage/data/heart200.png)bin8063 -> 8063 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/htiling.qml (renamed from tests/auto/declarative/qquickimage/data/htiling.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/mirror.qml (renamed from tests/auto/declarative/qquickimage/data/mirror.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/nullpixmap.qml (renamed from tests/auto/declarative/qquickimage/data/nullpixmap.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/pattern.png (renamed from tests/auto/declarative/qquickimage/data/pattern.png)bin1371 -> 1371 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/qtbug_16389.qml (renamed from tests/auto/declarative/qquickimage/data/qtbug_16389.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/qtbug_22125.qml (renamed from tests/auto/declarative/qquickimage/data/qtbug_22125.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/data/rect.png (renamed from tests/auto/declarative/qquickimage/data/rect.png)bin171 -> 171 bytes
-rw-r--r--tests/auto/qtquick2/qquickimage/data/vtiling.qml (renamed from tests/auto/declarative/qquickimage/data/vtiling.qml)0
-rw-r--r--tests/auto/qtquick2/qquickimage/qquickimage.pro13
-rw-r--r--tests/auto/qtquick2/qquickimage/tst_qquickimage.cpp732
-rw-r--r--tests/auto/qtquick2/qquickitem/data/order.1.qml (renamed from tests/auto/declarative/qquickitem/data/order.1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem/data/order.2.qml (renamed from tests/auto/declarative/qquickitem/data/order.2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem/qquickitem.pro12
-rw-r--r--tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp1190
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/childrenProperty.qml (renamed from tests/auto/declarative/qquickitem2/data/childrenProperty.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/childrenRect.qml (renamed from tests/auto/declarative/qquickitem2/data/childrenRect.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/childrenRectBug.qml (renamed from tests/auto/declarative/qquickitem2/data/childrenRectBug.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/childrenRectBug2.qml (renamed from tests/auto/declarative/qquickitem2/data/childrenRectBug2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/childrenRectBug3.qml (renamed from tests/auto/declarative/qquickitem2/data/childrenRectBug3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/implicitsize.qml (renamed from tests/auto/declarative/qquickitem2/data/implicitsize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/keynavigationtest.qml (renamed from tests/auto/declarative/qquickitem2/data/keynavigationtest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/keynavigationtest_implicit.qml (renamed from tests/auto/declarative/qquickitem2/data/keynavigationtest_implicit.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/keyspriority.qml (renamed from tests/auto/declarative/qquickitem2/data/keyspriority.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/keystest.qml (renamed from tests/auto/declarative/qquickitem2/data/keystest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/layoutmirroring.qml (renamed from tests/auto/declarative/qquickitem2/data/layoutmirroring.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/mapCoordinates.qml (renamed from tests/auto/declarative/qquickitem2/data/mapCoordinates.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/propertychanges.qml (renamed from tests/auto/declarative/qquickitem2/data/propertychanges.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/qtbug_16871.qml (renamed from tests/auto/declarative/qquickitem2/data/qtbug_16871.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/resourcesProperty.qml (renamed from tests/auto/declarative/qquickitem2/data/resourcesProperty.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/data/transformCrash.qml (renamed from tests/auto/declarative/qquickitem2/data/transformCrash.qml)0
-rw-r--r--tests/auto/qtquick2/qquickitem2/qquickitem2.pro13
-rw-r--r--tests/auto/qtquick2/qquickitem2/tst_qquickitem.cpp1254
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/ComponentView.qml (renamed from tests/auto/declarative/qquicklistview/data/ComponentView.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/asyncloader.qml (renamed from tests/auto/declarative/qquicklistview/data/asyncloader.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/attachedSignals.qml (renamed from tests/auto/declarative/qquicklistview/data/attachedSignals.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/creationContext.qml (renamed from tests/auto/declarative/qquicklistview/data/creationContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/displaylist.qml (renamed from tests/auto/declarative/qquicklistview/data/displaylist.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/fillModelOnComponentCompleted.qml (renamed from tests/auto/declarative/qquicklistview/data/fillModelOnComponentCompleted.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/footer.qml (renamed from tests/auto/declarative/qquicklistview/data/footer.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/header.qml (renamed from tests/auto/declarative/qquicklistview/data/header.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/headerfooter.qml (renamed from tests/auto/declarative/qquicklistview/data/headerfooter.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/itemlist.qml (renamed from tests/auto/declarative/qquicklistview/data/itemlist.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-enforcerange-nohighlight.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-enforcerange-nohighlight.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-enforcerange.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-enforcerange.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-initCurrent.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-initCurrent.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-noCurrent.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-noCurrent.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-sections.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-sections.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listview-sections_delegate.qml (renamed from tests/auto/declarative/qquicklistview/data/listview-sections_delegate.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/listviewtest.qml (renamed from tests/auto/declarative/qquicklistview/data/listviewtest.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/manual-highlight.qml (renamed from tests/auto/declarative/qquicklistview/data/manual-highlight.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/margins.qml (renamed from tests/auto/declarative/qquicklistview/data/margins.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/propertychangestest.qml (renamed from tests/auto/declarative/qquicklistview/data/propertychangestest.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/qtbug-21742.qml (renamed from tests/auto/declarative/qquicklistview/data/qtbug-21742.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/qtbug14821.qml (renamed from tests/auto/declarative/qquicklistview/data/qtbug14821.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/qtbug16037.qml (renamed from tests/auto/declarative/qquicklistview/data/qtbug16037.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/resizeview.qml (renamed from tests/auto/declarative/qquicklistview/data/resizeview.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/rightToLeft.qml (renamed from tests/auto/declarative/qquicklistview/data/rightToLeft.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/sizelessthan1.qml (renamed from tests/auto/declarative/qquicklistview/data/sizelessthan1.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/snapToItem.qml (renamed from tests/auto/declarative/qquicklistview/data/snapToItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/data/strictlyenforcerange.qml (renamed from tests/auto/declarative/qquicklistview/data/strictlyenforcerange.qml)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/incrementalmodel.cpp (renamed from tests/auto/declarative/qquicklistview/incrementalmodel.cpp)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/incrementalmodel.h (renamed from tests/auto/declarative/qquicklistview/incrementalmodel.h)0
-rw-r--r--tests/auto/qtquick2/qquicklistview/qquicklistview.pro13
-rw-r--r--tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp4379
-rw-r--r--tests/auto/qtquick2/qquickloader/data/ActiveComponent.qml (renamed from tests/auto/declarative/qquickloader/data/ActiveComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/AnchoredLoader.qml (renamed from tests/auto/declarative/qquickloader/data/AnchoredLoader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/BigComponent.qml (renamed from tests/auto/declarative/qquickloader/data/BigComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/BlueRect.qml (renamed from tests/auto/declarative/qquickloader/data/BlueRect.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/CreationContextLoader.qml (renamed from tests/auto/declarative/qquickloader/data/CreationContextLoader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/GraphicsWidget250x250.qml (renamed from tests/auto/declarative/qquickloader/data/GraphicsWidget250x250.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/GreenRect.qml (renamed from tests/auto/declarative/qquickloader/data/GreenRect.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/InitialPropertyValuesComponent.qml (renamed from tests/auto/declarative/qquickloader/data/InitialPropertyValuesComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/InvalidSourceComponent.qml (renamed from tests/auto/declarative/qquickloader/data/InvalidSourceComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/NoResize.qml (renamed from tests/auto/declarative/qquickloader/data/NoResize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/NoResizeGraphicsWidget.qml (renamed from tests/auto/declarative/qquickloader/data/NoResizeGraphicsWidget.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/QTBUG_16928.qml (renamed from tests/auto/declarative/qquickloader/data/QTBUG_16928.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/QTBUG_17114.qml (renamed from tests/auto/declarative/qquickloader/data/QTBUG_17114.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/Rect120x60.qml (renamed from tests/auto/declarative/qquickloader/data/Rect120x60.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/SetSourceComponent.qml (renamed from tests/auto/declarative/qquickloader/data/SetSourceComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/SizeGraphicsWidgetToLoader.qml (renamed from tests/auto/declarative/qquickloader/data/SizeGraphicsWidgetToLoader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/SizeLoaderToGraphicsWidget.qml (renamed from tests/auto/declarative/qquickloader/data/SizeLoaderToGraphicsWidget.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/SizeToItem.qml (renamed from tests/auto/declarative/qquickloader/data/SizeToItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/SizeToLoader.qml (renamed from tests/auto/declarative/qquickloader/data/SizeToLoader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/VmeError.qml (renamed from tests/auto/declarative/qquickloader/data/VmeError.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.1.qml (renamed from tests/auto/declarative/qquickloader/data/active.1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.2.qml (renamed from tests/auto/declarative/qquickloader/data/active.2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.3.qml (renamed from tests/auto/declarative/qquickloader/data/active.3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.4.qml (renamed from tests/auto/declarative/qquickloader/data/active.4.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.5.qml (renamed from tests/auto/declarative/qquickloader/data/active.5.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.6.qml (renamed from tests/auto/declarative/qquickloader/data/active.6.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.7.qml (renamed from tests/auto/declarative/qquickloader/data/active.7.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/active.8.qml (renamed from tests/auto/declarative/qquickloader/data/active.8.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/asynchronous.qml (renamed from tests/auto/declarative/qquickloader/data/asynchronous.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/crash.qml (renamed from tests/auto/declarative/qquickloader/data/crash.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/creationContext.qml (renamed from tests/auto/declarative/qquickloader/data/creationContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/differentorigin.qml (renamed from tests/auto/declarative/qquickloader/data/differentorigin.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/implicitSize.qml (renamed from tests/auto/declarative/qquickloader/data/implicitSize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.1.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.2.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.3.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.4.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.4.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.5.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.5.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.6.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.6.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.7.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.7.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.8.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.8.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.binding.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.binding.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.1.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.error.1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.2.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.error.2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.3.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.error.3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.4.qml (renamed from tests/auto/declarative/qquickloader/data/initialPropertyValues.error.4.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/nonItem.qml (renamed from tests/auto/declarative/qquickloader/data/nonItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/parented.qml (renamed from tests/auto/declarative/qquickloader/data/parented.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/qmldir (renamed from tests/auto/declarative/qquickloader/data/qmldir)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/sameorigin-load.qml (renamed from tests/auto/declarative/qquickloader/data/sameorigin-load.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/sameorigin.qml (renamed from tests/auto/declarative/qquickloader/data/sameorigin.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/data/vmeErrors.qml (renamed from tests/auto/declarative/qquickloader/data/vmeErrors.qml)0
-rw-r--r--tests/auto/qtquick2/qquickloader/qquickloader.pro16
-rw-r--r--tests/auto/qtquick2/qquickloader/tst_qquickloader.cpp969
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/clickThrough.qml (renamed from tests/auto/declarative/qquickmousearea/data/clickThrough.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/clickThrough2.qml (renamed from tests/auto/declarative/qquickmousearea/data/clickThrough2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/clickandhold.qml (renamed from tests/auto/declarative/qquickmousearea/data/clickandhold.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/clicktwice.qml (renamed from tests/auto/declarative/qquickmousearea/data/clicktwice.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/doubleclick.qml (renamed from tests/auto/declarative/qquickmousearea/data/doubleclick.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/dragging.qml (renamed from tests/auto/declarative/qquickmousearea/data/dragging.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/dragproperties.qml (renamed from tests/auto/declarative/qquickmousearea/data/dragproperties.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/dragreset.qml (renamed from tests/auto/declarative/qquickmousearea/data/dragreset.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/hoverPosition.qml (renamed from tests/auto/declarative/qquickmousearea/data/hoverPosition.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/hoverPropagation.qml (renamed from tests/auto/declarative/qquickmousearea/data/hoverPropagation.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/noclickandhold.qml (renamed from tests/auto/declarative/qquickmousearea/data/noclickandhold.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/pressedCanceled.qml (renamed from tests/auto/declarative/qquickmousearea/data/pressedCanceled.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/pressedOrdering.qml (renamed from tests/auto/declarative/qquickmousearea/data/pressedOrdering.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/preventstealing.qml (renamed from tests/auto/declarative/qquickmousearea/data/preventstealing.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/rejectEvent.qml (renamed from tests/auto/declarative/qquickmousearea/data/rejectEvent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnClick.qml (renamed from tests/auto/declarative/qquickmousearea/data/updateMousePosOnClick.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnResize.qml (renamed from tests/auto/declarative/qquickmousearea/data/updateMousePosOnResize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmousearea/qquickmousearea.pro14
-rw-r--r--tests/auto/qtquick2/qquickmousearea/tst_qquickmousearea.cpp824
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/data/inFlickable.qml (renamed from tests/auto/declarative/qquickmultipointtoucharea/data/inFlickable.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/data/nested.qml (renamed from tests/auto/declarative/qquickmultipointtoucharea/data/nested.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/data/nonOverlapping.qml (renamed from tests/auto/declarative/qquickmultipointtoucharea/data/nonOverlapping.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/data/properties.qml (renamed from tests/auto/declarative/qquickmultipointtoucharea/data/properties.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/data/signalTest.qml (renamed from tests/auto/declarative/qquickmultipointtoucharea/data/signalTest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/qquickmultipointtoucharea.pro11
-rw-r--r--tests/auto/qtquick2/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp586
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/ComponentView.qml (renamed from tests/auto/declarative/qquickpathview/data/ComponentView.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/asyncloader.qml (renamed from tests/auto/declarative/qquickpathview/data/asyncloader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/closedPath.qml (renamed from tests/auto/declarative/qquickpathview/data/closedPath.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/creationContext.qml (renamed from tests/auto/declarative/qquickpathview/data/creationContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/datamodel.qml (renamed from tests/auto/declarative/qquickpathview/data/datamodel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/displaypath.qml (renamed from tests/auto/declarative/qquickpathview/data/displaypath.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/dragpath.qml (renamed from tests/auto/declarative/qquickpathview/data/dragpath.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/emptymodel.qml (renamed from tests/auto/declarative/qquickpathview/data/emptymodel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/missingPercent.qml (renamed from tests/auto/declarative/qquickpathview/data/missingPercent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/openPath.qml (renamed from tests/auto/declarative/qquickpathview/data/openPath.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathUpdate.qml (renamed from tests/auto/declarative/qquickpathview/data/pathUpdate.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathUpdateOnStartChanged.qml (renamed from tests/auto/declarative/qquickpathview/data/pathUpdateOnStartChanged.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathline.qml (renamed from tests/auto/declarative/qquickpathview/data/pathline.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathtest.qml (renamed from tests/auto/declarative/qquickpathview/data/pathtest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathview0.qml (renamed from tests/auto/declarative/qquickpathview/data/pathview0.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathview1.qml (renamed from tests/auto/declarative/qquickpathview/data/pathview1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathview2.qml (renamed from tests/auto/declarative/qquickpathview/data/pathview2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathview3.qml (renamed from tests/auto/declarative/qquickpathview/data/pathview3.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/pathview_package.qml (renamed from tests/auto/declarative/qquickpathview/data/pathview_package.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/propertychanges.qml (renamed from tests/auto/declarative/qquickpathview/data/propertychanges.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/treemodel.qml (renamed from tests/auto/declarative/qquickpathview/data/treemodel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/undefinedpath.qml (renamed from tests/auto/declarative/qquickpathview/data/undefinedpath.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/data/vdm.qml (renamed from tests/auto/declarative/qquickpathview/data/vdm.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpathview/qquickpathview.pro12
-rw-r--r--tests/auto/qtquick2/qquickpathview/tst_qquickpathview.cpp1629
-rw-r--r--tests/auto/qtquick2/qquickpincharea/data/pinchproperties.qml (renamed from tests/auto/declarative/qquickpincharea/data/pinchproperties.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpincharea/qquickpincharea.pro13
-rw-r--r--tests/auto/qtquick2/qquickpincharea/tst_qquickpincharea.cpp395
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/allInvisible.qml (renamed from tests/auto/declarative/qquickpositioners/data/allInvisible.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/attachedproperties-column.qml (renamed from tests/auto/declarative/qquickpositioners/data/attachedproperties-column.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/attachedproperties-dynamic.qml (renamed from tests/auto/declarative/qquickpositioners/data/attachedproperties-dynamic.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/attachedproperties-flow.qml (renamed from tests/auto/declarative/qquickpositioners/data/attachedproperties-flow.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/attachedproperties-grid.qml (renamed from tests/auto/declarative/qquickpositioners/data/attachedproperties-grid.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/attachedproperties-row.qml (renamed from tests/auto/declarative/qquickpositioners/data/attachedproperties-row.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/flow-testimplicitsize.qml (renamed from tests/auto/declarative/qquickpositioners/data/flow-testimplicitsize.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/flowtest-toptobottom.qml (renamed from tests/auto/declarative/qquickpositioners/data/flowtest-toptobottom.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/flowtest.qml (renamed from tests/auto/declarative/qquickpositioners/data/flowtest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/grid-animated.qml (renamed from tests/auto/declarative/qquickpositioners/data/grid-animated.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/grid-row-column-spacing.qml (renamed from tests/auto/declarative/qquickpositioners/data/grid-row-column-spacing.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/grid-spacing.qml (renamed from tests/auto/declarative/qquickpositioners/data/grid-spacing.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/grid-toptobottom.qml (renamed from tests/auto/declarative/qquickpositioners/data/grid-toptobottom.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/gridtest.qml (renamed from tests/auto/declarative/qquickpositioners/data/gridtest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/gridzerocolumns.qml (renamed from tests/auto/declarative/qquickpositioners/data/gridzerocolumns.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/horizontal-animated-disabled.qml (renamed from tests/auto/declarative/qquickpositioners/data/horizontal-animated-disabled.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/horizontal-animated.qml (renamed from tests/auto/declarative/qquickpositioners/data/horizontal-animated.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/horizontal-spacing.qml (renamed from tests/auto/declarative/qquickpositioners/data/horizontal-spacing.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/horizontal.qml (renamed from tests/auto/declarative/qquickpositioners/data/horizontal.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/propertychangestest.qml (renamed from tests/auto/declarative/qquickpositioners/data/propertychangestest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/rectangleComponent.qml (renamed from tests/auto/declarative/qquickpositioners/data/rectangleComponent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/repeatertest.qml (renamed from tests/auto/declarative/qquickpositioners/data/repeatertest.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/vertical-animated.qml (renamed from tests/auto/declarative/qquickpositioners/data/vertical-animated.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/vertical-spacing.qml (renamed from tests/auto/declarative/qquickpositioners/data/vertical-spacing.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/data/vertical.qml (renamed from tests/auto/declarative/qquickpositioners/data/vertical.qml)0
-rw-r--r--tests/auto/qtquick2/qquickpositioners/qquickpositioners.pro11
-rw-r--r--tests/auto/qtquick2/qquickpositioners/tst_qquickpositioners.cpp1473
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/asyncloader.qml (renamed from tests/auto/declarative/qquickrepeater/data/asyncloader.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/initparent.qml (renamed from tests/auto/declarative/qquickrepeater/data/initparent.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/intmodel.qml (renamed from tests/auto/declarative/qquickrepeater/data/intmodel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/itemlist.qml (renamed from tests/auto/declarative/qquickrepeater/data/itemlist.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/modelChanged.qml (renamed from tests/auto/declarative/qquickrepeater/data/modelChanged.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/objlist.qml (renamed from tests/auto/declarative/qquickrepeater/data/objlist.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/properties.qml (renamed from tests/auto/declarative/qquickrepeater/data/properties.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/repeater1.qml (renamed from tests/auto/declarative/qquickrepeater/data/repeater1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/data/repeater2.qml (renamed from tests/auto/declarative/qquickrepeater/data/repeater2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickrepeater/qquickrepeater.pro12
-rw-r--r--tests/auto/qtquick2/qquickrepeater/tst_qquickrepeater.cpp764
-rw-r--r--tests/auto/qtquick2/qquickshadereffect/qquickshadereffect.pro8
-rw-r--r--tests/auto/qtquick2/qquickshadereffect/tst_qquickshadereffect.cpp (renamed from tests/auto/declarative/qquickshadereffect/tst_qquickshadereffect.cpp)0
-rw-r--r--tests/auto/qtquick2/qquickspriteimage/data/basic.qml (renamed from tests/auto/declarative/qquickspriteimage/data/basic.qml)0
-rw-r--r--tests/auto/qtquick2/qquickspriteimage/data/squarefacesprite.png (renamed from tests/auto/declarative/qquickspriteimage/data/squarefacesprite.png)bin496 -> 496 bytes
-rw-r--r--tests/auto/qtquick2/qquickspriteimage/qquickspriteimage.pro12
-rw-r--r--tests/auto/qtquick2/qquickspriteimage/tst_qquickspriteimage.cpp81
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments.qml (renamed from tests/auto/declarative/qquicktext/data/alignments.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_cb.png (renamed from tests/auto/declarative/qquicktext/data/alignments_cb.png)bin496 -> 496 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_cc.png (renamed from tests/auto/declarative/qquicktext/data/alignments_cc.png)bin556 -> 556 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_ct.png (renamed from tests/auto/declarative/qquicktext/data/alignments_ct.png)bin533 -> 533 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_lb.png (renamed from tests/auto/declarative/qquicktext/data/alignments_lb.png)bin496 -> 496 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_lc.png (renamed from tests/auto/declarative/qquicktext/data/alignments_lc.png)bin535 -> 535 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_lt.png (renamed from tests/auto/declarative/qquicktext/data/alignments_lt.png)bin514 -> 514 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_rb.png (renamed from tests/auto/declarative/qquicktext/data/alignments_rb.png)bin505 -> 505 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_rc.png (renamed from tests/auto/declarative/qquicktext/data/alignments_rc.png)bin559 -> 559 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/alignments_rt.png (renamed from tests/auto/declarative/qquicktext/data/alignments_rt.png)bin539 -> 539 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/embeddedImagesLocal.qml (renamed from tests/auto/declarative/qquicktext/data/embeddedImagesLocal.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/embeddedImagesLocalError.qml (renamed from tests/auto/declarative/qquicktext/data/embeddedImagesLocalError.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/embeddedImagesRemote.qml (renamed from tests/auto/declarative/qquicktext/data/embeddedImagesRemote.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/embeddedImagesRemoteError.qml (renamed from tests/auto/declarative/qquicktext/data/embeddedImagesRemoteError.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/horizontalAlignment_RightToLeft.qml (renamed from tests/auto/declarative/qquicktext/data/horizontalAlignment_RightToLeft.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/http/exists.png (renamed from tests/auto/declarative/qquicktext/data/http/exists.png)bin2738 -> 2738 bytes
-rw-r--r--tests/auto/qtquick2/qquicktext/data/lineCount.qml (renamed from tests/auto/declarative/qquicktext/data/lineCount.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/lineHeight.qml (renamed from tests/auto/declarative/qquicktext/data/lineHeight.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/lineLayout.qml (renamed from tests/auto/declarative/qquicktext/data/lineLayout.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/multilineelide.qml (renamed from tests/auto/declarative/qquicktext/data/multilineelide.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/qtbug_14734.qml (renamed from tests/auto/declarative/qquicktext/data/qtbug_14734.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/data/rotated.qml (renamed from tests/auto/declarative/qquicktext/data/rotated.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktext/qquicktext.pro17
-rw-r--r--tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp1460
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/CursorRect.qml (renamed from tests/auto/declarative/qquicktextedit/data/CursorRect.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments.qml (renamed from tests/auto/declarative/qquicktextedit/data/alignments.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_cb.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_cb.png)bin496 -> 496 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_cc.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_cc.png)bin556 -> 556 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_ct.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_ct.png)bin533 -> 533 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_lb.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_lb.png)bin496 -> 496 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_lc.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_lc.png)bin535 -> 535 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_lt.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_lt.png)bin514 -> 514 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_rb.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_rb.png)bin505 -> 505 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_rc.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_rc.png)bin559 -> 559 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/alignments_rt.png (renamed from tests/auto/declarative/qquicktextedit/data/alignments_rt.png)bin539 -> 539 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/cursorTest.qml (renamed from tests/auto/declarative/qquicktextedit/data/cursorTest.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/cursorVisible.qml (renamed from tests/auto/declarative/qquicktextedit/data/cursorVisible.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/geometrySignals.qml (renamed from tests/auto/declarative/qquicktextedit/data/geometrySignals.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/horizontalAlignment_RightToLeft.qml (renamed from tests/auto/declarative/qquicktextedit/data/horizontalAlignment_RightToLeft.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/ErrItem.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/ErrItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/NormItem.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/NormItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTest.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/cursorHttpTest.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail1.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail1.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail2.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail2.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestPass.qml (renamed from tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestPass.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/http/qmldir (renamed from tests/auto/declarative/qquicktextedit/data/http/qmldir)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/httpfail/FailItem.qml (renamed from tests/auto/declarative/qquicktextedit/data/httpfail/FailItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/httpslow/WaitItem.qml (renamed from tests/auto/declarative/qquicktextedit/data/httpslow/WaitItem.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/inputContext.qml (renamed from tests/auto/declarative/qquicktextedit/data/inputContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/inputMethodEvent.qml (renamed from tests/auto/declarative/qquicktextedit/data/inputMethodEvent.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/inputmethodhints.qml (renamed from tests/auto/declarative/qquicktextedit/data/inputmethodhints.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselection_default.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselection_default.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselection_false.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselection_false.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselection_false_words.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselection_false_words.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselection_true.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselection_true.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselection_true_words.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselection_true_words.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_characters.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselectionmode_characters.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_default.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselectionmode_default.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_words.qml (renamed from tests/auto/declarative/qquicktextedit/data/mouseselectionmode_words.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/navigation.qml (renamed from tests/auto/declarative/qquicktextedit/data/navigation.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/openInputPanel.qml (renamed from tests/auto/declarative/qquicktextedit/data/openInputPanel.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/positionAt.qml (renamed from tests/auto/declarative/qquicktextedit/data/positionAt.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/qtbug-22058.qml (renamed from tests/auto/declarative/qquicktextedit/data/qtbug-22058.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/data/readOnly.qml (renamed from tests/auto/declarative/qquicktextedit/data/readOnly.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextedit/qquicktextedit.pro12
-rw-r--r--tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp3555
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/cursorTest.qml (renamed from tests/auto/declarative/qquicktextinput/data/cursorTest.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/cursorVisible.qml (renamed from tests/auto/declarative/qquicktextinput/data/cursorVisible.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/echoMode.qml (renamed from tests/auto/declarative/qquicktextinput/data/echoMode.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/geometrySignals.qml (renamed from tests/auto/declarative/qquicktextinput/data/geometrySignals.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/halign_center.png (renamed from tests/auto/declarative/qquicktextinput/data/halign_center.png)bin293 -> 293 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/halign_left.png (renamed from tests/auto/declarative/qquicktextinput/data/halign_left.png)bin291 -> 291 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/halign_right.png (renamed from tests/auto/declarative/qquicktextinput/data/halign_right.png)bin292 -> 292 bytes
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment.qml (renamed from tests/auto/declarative/qquicktextinput/data/horizontalAlignment.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment_RightToLeft.qml (renamed from tests/auto/declarative/qquicktextinput/data/horizontalAlignment_RightToLeft.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/inputContext.qml (renamed from tests/auto/declarative/qquicktextinput/data/inputContext.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/inputMethodEvent.qml (renamed from tests/auto/declarative/qquicktextinput/data/inputMethodEvent.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/inputmethods.qml (renamed from tests/auto/declarative/qquicktextinput/data/inputmethods.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/masks.qml (renamed from tests/auto/declarative/qquicktextinput/data/masks.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/maxLength.qml (renamed from tests/auto/declarative/qquicktextinput/data/maxLength.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/mouseselection_true.qml (renamed from tests/auto/declarative/qquicktextinput/data/mouseselection_true.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_characters.qml (renamed from tests/auto/declarative/qquicktextinput/data/mouseselectionmode_characters.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_default.qml (renamed from tests/auto/declarative/qquicktextinput/data/mouseselectionmode_default.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_words.qml (renamed from tests/auto/declarative/qquicktextinput/data/mouseselectionmode_words.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/navigation.qml (renamed from tests/auto/declarative/qquicktextinput/data/navigation.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/openInputPanel.qml (renamed from tests/auto/declarative/qquicktextinput/data/openInputPanel.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/positionAt.qml (renamed from tests/auto/declarative/qquicktextinput/data/positionAt.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/preeditAutoScroll.qml (renamed from tests/auto/declarative/qquicktextinput/data/preeditAutoScroll.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/qtbug-19956double.qml (renamed from tests/auto/declarative/qquicktextinput/data/qtbug-19956double.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/qtbug-19956int.qml (renamed from tests/auto/declarative/qquicktextinput/data/qtbug-19956int.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/qtbug-19956regexp.qml (renamed from tests/auto/declarative/qquicktextinput/data/qtbug-19956regexp.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/readOnly.qml (renamed from tests/auto/declarative/qquicktextinput/data/readOnly.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/data/validators.qml (renamed from tests/auto/declarative/qquicktextinput/data/validators.qml)0
-rw-r--r--tests/auto/qtquick2/qquicktextinput/qquicktextinput.pro11
-rw-r--r--tests/auto/qtquick2/qquicktextinput/tst_qquicktextinput.cpp3310
-rw-r--r--tests/auto/qtquick2/qquickview/data/error1.qml (renamed from tests/auto/declarative/qquickview/data/error1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickview/data/resizemodeitem.qml (renamed from tests/auto/declarative/qquickview/data/resizemodeitem.qml)0
-rw-r--r--tests/auto/qtquick2/qquickview/qquickview.pro11
-rw-r--r--tests/auto/qtquick2/qquickview/tst_qquickview.cpp207
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/create.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/datalist-package.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/datalist-package.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/datalist.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/datalist.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/groups-invalid.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/groups-invalid.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/groups-package.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/groups-package.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/groups.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/groups.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_listView.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_package.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/modelproperties.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties2.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/modelproperties2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/objectlist.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/objectlist.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/onChanged.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/onChanged.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole1.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/singlerole1.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole2.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/singlerole2.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/data/visualdatamodel.qml (renamed from tests/auto/declarative/qquickvisualdatamodel/data/visualdatamodel.qml)0
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/qquickvisualdatamodel.pro13
-rw-r--r--tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp1865
-rw-r--r--tests/auto/qtquick2/qtquick2.pro63
-rw-r--r--tests/auto/shared/testhttpserver.cpp (renamed from tests/auto/declarative/shared/testhttpserver.cpp)0
-rw-r--r--tests/auto/shared/testhttpserver.h (renamed from tests/auto/declarative/shared/testhttpserver.h)0
-rw-r--r--tests/auto/shared/util.h (renamed from tests/auto/declarative/shared/util.h)0
-rw-r--r--tests/benchmarks/particles/affectors/affectors.pro2
-rw-r--r--tests/benchmarks/particles/emission/emission.pro2
-rw-r--r--tools/qmleasing/main.cpp4
-rw-r--r--tools/qmleasing/qmleasing.pro2
-rw-r--r--tools/qmlplugindump/main.cpp16
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro2
-rw-r--r--tools/qmlscene/main.cpp4
-rw-r--r--tools/qmlscene/qmlscene.pro2
1439 files changed, 107138 insertions, 106954 deletions
diff --git a/doc/src/quick/qtquick.qdoc b/doc/src/quick/qtquick.qdoc
new file mode 100644
index 0000000000..358e9f8433
--- /dev/null
+++ b/doc/src/quick/qtquick.qdoc
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \module QtQuick
+ \title Qt Quick Module
+ \ingroup modules
+
+ \brief The Qt Quick module provides classes for embedding Qt Quick
+ in Qt/C++ applications.
+
+ To include the definitions of the module's classes, use the
+ following directive:
+
+ \code
+ #include <QtQuick>
+ \endcode
+
+ To link against the module, add this line to your \l qmake \c
+ .pro file:
+
+ \code
+ QT += quick
+ \endcode
+
+ For more information on the Qt Quick module, see the
+ \l{Qt Quick} documentation.
+*/
diff --git a/examples/declarative/cppextensions/networkaccessmanagerfactory/main.cpp b/examples/declarative/cppextensions/networkaccessmanagerfactory/main.cpp
index e8ccdb7e36..4a13b7a597 100644
--- a/examples/declarative/cppextensions/networkaccessmanagerfactory/main.cpp
+++ b/examples/declarative/cppextensions/networkaccessmanagerfactory/main.cpp
@@ -44,7 +44,7 @@
#include <QDeclarativeEngine>
#include <QDeclarativeNetworkAccessManagerFactory>
-#include <QQuickView>
+#include <QtQuick/QQuickView>
/*
diff --git a/examples/declarative/cppextensions/networkaccessmanagerfactory/networkaccessmanagerfactory.pro b/examples/declarative/cppextensions/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
index 74d8db321d..18d7879900 100644
--- a/examples/declarative/cppextensions/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
+++ b/examples/declarative/cppextensions/networkaccessmanagerfactory/networkaccessmanagerfactory.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = networkaccessmanagerfactory
DEPENDPATH += .
INCLUDEPATH += .
-QT += declarative network
+QT += declarative quick network
# Input
SOURCES += main.cpp
diff --git a/examples/declarative/minehunt/main.cpp b/examples/declarative/minehunt/main.cpp
index 205835a9c0..5cc49af684 100644
--- a/examples/declarative/minehunt/main.cpp
+++ b/examples/declarative/minehunt/main.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <QtGui/QGuiApplication>
-#include <qquickview.h>
+#include <QtQuick/qquickview.h>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>
diff --git a/examples/declarative/minehunt/minehunt.pro b/examples/declarative/minehunt/minehunt.pro
index cf928ce333..82dfc0d5bc 100644
--- a/examples/declarative/minehunt/minehunt.pro
+++ b/examples/declarative/minehunt/minehunt.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET = minehunt
-QT += declarative
+QT += declarative quick
# Input
HEADERS += minehunt.h
diff --git a/examples/declarative/modelviews/abstractitemmodel/abstractitemmodel.pro b/examples/declarative/modelviews/abstractitemmodel/abstractitemmodel.pro
index 6c51eed9d2..eaf2b30c89 100644
--- a/examples/declarative/modelviews/abstractitemmodel/abstractitemmodel.pro
+++ b/examples/declarative/modelviews/abstractitemmodel/abstractitemmodel.pro
@@ -2,9 +2,9 @@ TEMPLATE = app
TARGET = abstractitemmodel
DEPENDPATH += .
INCLUDEPATH += .
-QT += declarative
+QT += declarative quick
HEADERS = model.h
SOURCES = main.cpp \
model.cpp
-RESOURCES += abstractitemmodel.qrc \ No newline at end of file
+RESOURCES += abstractitemmodel.qrc
diff --git a/examples/declarative/modelviews/abstractitemmodel/main.cpp b/examples/declarative/modelviews/abstractitemmodel/main.cpp
index 7924815879..d8c1abc939 100644
--- a/examples/declarative/modelviews/abstractitemmodel/main.cpp
+++ b/examples/declarative/modelviews/abstractitemmodel/main.cpp
@@ -43,8 +43,8 @@
#include <qdeclarativeengine.h>
#include <qdeclarativecontext.h>
#include <qdeclarative.h>
-#include <qquickitem.h>
-#include <qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
//![0]
int main(int argc, char ** argv)
diff --git a/examples/declarative/modelviews/objectlistmodel/main.cpp b/examples/declarative/modelviews/objectlistmodel/main.cpp
index 67ffb946c0..fc7252c864 100644
--- a/examples/declarative/modelviews/objectlistmodel/main.cpp
+++ b/examples/declarative/modelviews/objectlistmodel/main.cpp
@@ -43,8 +43,8 @@
#include <qdeclarativeengine.h>
#include <qdeclarativecontext.h>
#include <qdeclarative.h>
-#include <qquickitem.h>
-#include <qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
#include "dataobject.h"
diff --git a/examples/declarative/modelviews/objectlistmodel/objectlistmodel.pro b/examples/declarative/modelviews/objectlistmodel/objectlistmodel.pro
index 8cc293dbfa..434e6f080b 100644
--- a/examples/declarative/modelviews/objectlistmodel/objectlistmodel.pro
+++ b/examples/declarative/modelviews/objectlistmodel/objectlistmodel.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = objectlistmodel
DEPENDPATH += .
INCLUDEPATH += .
-QT += declarative
+QT += declarative quick
# Input
SOURCES += main.cpp \
diff --git a/examples/declarative/modelviews/stringlistmodel/main.cpp b/examples/declarative/modelviews/stringlistmodel/main.cpp
index ebd3c59307..d5ddbe8fb8 100644
--- a/examples/declarative/modelviews/stringlistmodel/main.cpp
+++ b/examples/declarative/modelviews/stringlistmodel/main.cpp
@@ -44,8 +44,8 @@
#include <qdeclarativeengine.h>
#include <qdeclarativecontext.h>
#include <qdeclarative.h>
-#include <qquickitem.h>
-#include <qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
/*
diff --git a/examples/declarative/modelviews/stringlistmodel/stringlistmodel.pro b/examples/declarative/modelviews/stringlistmodel/stringlistmodel.pro
index 23dc481f88..d34f7d0b56 100644
--- a/examples/declarative/modelviews/stringlistmodel/stringlistmodel.pro
+++ b/examples/declarative/modelviews/stringlistmodel/stringlistmodel.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = stringlistmodel
DEPENDPATH += .
INCLUDEPATH += .
-QT += declarative
+QT += declarative quick
# Input
SOURCES += main.cpp
diff --git a/examples/declarative/openglunderqml/main.cpp b/examples/declarative/openglunderqml/main.cpp
index 44984c5be3..cb65c3feac 100644
--- a/examples/declarative/openglunderqml/main.cpp
+++ b/examples/declarative/openglunderqml/main.cpp
@@ -41,7 +41,7 @@
#include <QGuiApplication>
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include "squircle.h"
diff --git a/examples/declarative/openglunderqml/openglunderqml.pro b/examples/declarative/openglunderqml/openglunderqml.pro
index 3cd167335b..c93ac791fe 100644
--- a/examples/declarative/openglunderqml/openglunderqml.pro
+++ b/examples/declarative/openglunderqml/openglunderqml.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
TEMPLATE = app
DEPENDPATH += .
diff --git a/examples/declarative/openglunderqml/squircle.cpp b/examples/declarative/openglunderqml/squircle.cpp
index c2d4c0ac97..55c1dd092c 100644
--- a/examples/declarative/openglunderqml/squircle.cpp
+++ b/examples/declarative/openglunderqml/squircle.cpp
@@ -41,8 +41,8 @@
#include "squircle.h"
-#include <qsgengine.h>
-#include <qquickcanvas.h>
+#include <QtQuick/qsgengine.h>
+#include <QtQuick/qquickcanvas.h>
#include <QOpenGLShaderProgram>
Squircle::Squircle()
diff --git a/examples/declarative/openglunderqml/squircle.h b/examples/declarative/openglunderqml/squircle.h
index c92c93e2db..ab33c6a25f 100644
--- a/examples/declarative/openglunderqml/squircle.h
+++ b/examples/declarative/openglunderqml/squircle.h
@@ -42,7 +42,7 @@
#ifndef SQUIRCLE_H
#define SQUIRCLE_H
-#include <QtDeclarative/QQuickItem>
+#include <QtQuick/QQuickItem>
#include <QtGui/QOpenGLShaderProgram>
class Squircle : public QQuickItem
diff --git a/examples/declarative/painteditem/smile/main.cpp b/examples/declarative/painteditem/smile/main.cpp
index dc76e71185..0f69f4c962 100644
--- a/examples/declarative/painteditem/smile/main.cpp
+++ b/examples/declarative/painteditem/smile/main.cpp
@@ -41,8 +41,8 @@
#include <QGuiApplication>
#include <QPainter>
#include <QtDeclarative/qdeclarative.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qquickpainteditem.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickpainteditem.h>
class MyPaintItem : public QQuickPaintedItem
{
Q_OBJECT
diff --git a/examples/declarative/painteditem/smile/smile.pro b/examples/declarative/painteditem/smile/smile.pro
index 3b9e4e0f62..780d351fe6 100644
--- a/examples/declarative/painteditem/smile/smile.pro
+++ b/examples/declarative/painteditem/smile/smile.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = painteditem
-QT += declarative
+QT += declarative quick
macx: CONFIG -= app_bundle
diff --git a/examples/declarative/painteditem/textballoons/textballoon.h b/examples/declarative/painteditem/textballoons/textballoon.h
index 064d20bd7e..e35107c1b2 100644
--- a/examples/declarative/painteditem/textballoons/textballoon.h
+++ b/examples/declarative/painteditem/textballoons/textballoon.h
@@ -42,7 +42,7 @@
#ifndef TEXTBALLOON_H
#define TEXTBALLOON_H
-#include <QtDeclarative>
+#include <QtQuick>
//! [0]
class TextBalloon : public QQuickPaintedItem
diff --git a/examples/declarative/painteditem/textballoons/textballoons.pro b/examples/declarative/painteditem/textballoons/textballoons.pro
index 3148fd20e6..453a00336d 100644
--- a/examples/declarative/painteditem/textballoons/textballoons.pro
+++ b/examples/declarative/painteditem/textballoons/textballoons.pro
@@ -1,6 +1,6 @@
TEMPLATE = lib
CONFIG += qt plugin
-QT += declarative
+QT += declarative quick
TARGET = qmltextballoonplugin
diff --git a/examples/declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro b/examples/declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro
index 0f0416718c..affc57ce1f 100644
--- a/examples/declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro
+++ b/examples/declarative/tutorials/extending/chapter1-basics/chapter1-basics.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
HEADERS += piechart.h
SOURCES += piechart.cpp \
diff --git a/examples/declarative/tutorials/extending/chapter1-basics/main.cpp b/examples/declarative/tutorials/extending/chapter1-basics/main.cpp
index 2670871e61..c507b2c30c 100644
--- a/examples/declarative/tutorials/extending/chapter1-basics/main.cpp
+++ b/examples/declarative/tutorials/extending/chapter1-basics/main.cpp
@@ -39,7 +39,7 @@
****************************************************************************/
//![0]
#include "piechart.h"
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
diff --git a/examples/declarative/tutorials/extending/chapter1-basics/piechart.h b/examples/declarative/tutorials/extending/chapter1-basics/piechart.h
index d1beb71545..1bd3019f7b 100644
--- a/examples/declarative/tutorials/extending/chapter1-basics/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter1-basics/piechart.h
@@ -41,7 +41,7 @@
#define PIECHART_H
//![0]
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
#include <QColor>
class PieChart : public QQuickPaintedItem
diff --git a/examples/declarative/tutorials/extending/chapter2-methods/chapter2-methods.pro b/examples/declarative/tutorials/extending/chapter2-methods/chapter2-methods.pro
index 0f0416718c..affc57ce1f 100644
--- a/examples/declarative/tutorials/extending/chapter2-methods/chapter2-methods.pro
+++ b/examples/declarative/tutorials/extending/chapter2-methods/chapter2-methods.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
HEADERS += piechart.h
SOURCES += piechart.cpp \
diff --git a/examples/declarative/tutorials/extending/chapter2-methods/main.cpp b/examples/declarative/tutorials/extending/chapter2-methods/main.cpp
index 2670871e61..c507b2c30c 100644
--- a/examples/declarative/tutorials/extending/chapter2-methods/main.cpp
+++ b/examples/declarative/tutorials/extending/chapter2-methods/main.cpp
@@ -39,7 +39,7 @@
****************************************************************************/
//![0]
#include "piechart.h"
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
diff --git a/examples/declarative/tutorials/extending/chapter2-methods/piechart.h b/examples/declarative/tutorials/extending/chapter2-methods/piechart.h
index 5205151a0a..4ed9e0665c 100644
--- a/examples/declarative/tutorials/extending/chapter2-methods/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter2-methods/piechart.h
@@ -40,7 +40,7 @@
#ifndef PIECHART_H
#define PIECHART_H
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
#include <QColor>
//![0]
diff --git a/examples/declarative/tutorials/extending/chapter3-bindings/chapter3-bindings.pro b/examples/declarative/tutorials/extending/chapter3-bindings/chapter3-bindings.pro
index 0f0416718c..affc57ce1f 100644
--- a/examples/declarative/tutorials/extending/chapter3-bindings/chapter3-bindings.pro
+++ b/examples/declarative/tutorials/extending/chapter3-bindings/chapter3-bindings.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
HEADERS += piechart.h
SOURCES += piechart.cpp \
diff --git a/examples/declarative/tutorials/extending/chapter3-bindings/main.cpp b/examples/declarative/tutorials/extending/chapter3-bindings/main.cpp
index 2670871e61..c507b2c30c 100644
--- a/examples/declarative/tutorials/extending/chapter3-bindings/main.cpp
+++ b/examples/declarative/tutorials/extending/chapter3-bindings/main.cpp
@@ -39,7 +39,7 @@
****************************************************************************/
//![0]
#include "piechart.h"
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
diff --git a/examples/declarative/tutorials/extending/chapter3-bindings/piechart.h b/examples/declarative/tutorials/extending/chapter3-bindings/piechart.h
index 55be2a493f..7c5fda2744 100644
--- a/examples/declarative/tutorials/extending/chapter3-bindings/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter3-bindings/piechart.h
@@ -41,7 +41,7 @@
#define PIECHART_H
#include <QColor>
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
//![0]
class PieChart : public QQuickPaintedItem
diff --git a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
index c3f5402aea..6724fa0375 100644
--- a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
+++ b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
HEADERS += piechart.h \
pieslice.h
diff --git a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp
index c9b9a0b5aa..5d1c4d6839 100644
--- a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp
+++ b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/main.cpp
@@ -40,7 +40,7 @@
#include "piechart.h"
#include "pieslice.h"
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QGuiApplication>
//![0]
diff --git a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h
index c1cdf30805..36a866dfc3 100644
--- a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/piechart.h
@@ -40,7 +40,7 @@
#ifndef PIECHART_H
#define PIECHART_H
-#include <QtDeclarative/QQuickItem>
+#include <QtQuick/QQuickItem>
class PieSlice;
diff --git a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h
index 59606486a4..23913adf84 100644
--- a/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h
+++ b/examples/declarative/tutorials/extending/chapter4-customPropertyTypes/pieslice.h
@@ -40,7 +40,7 @@
#ifndef PIESLICE_H
#define PIESLICE_H
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
#include <QColor>
//![0]
diff --git a/examples/declarative/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro b/examples/declarative/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
index c3f5402aea..6724fa0375 100644
--- a/examples/declarative/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
+++ b/examples/declarative/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
@@ -1,4 +1,4 @@
-QT += declarative
+QT += declarative quick
HEADERS += piechart.h \
pieslice.h
diff --git a/examples/declarative/tutorials/extending/chapter5-listproperties/main.cpp b/examples/declarative/tutorials/extending/chapter5-listproperties/main.cpp
index 78f6f25485..afd34455c8 100644
--- a/examples/declarative/tutorials/extending/chapter5-listproperties/main.cpp
+++ b/examples/declarative/tutorials/extending/chapter5-listproperties/main.cpp
@@ -40,7 +40,7 @@
#include "piechart.h"
#include "pieslice.h"
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
diff --git a/examples/declarative/tutorials/extending/chapter5-listproperties/piechart.h b/examples/declarative/tutorials/extending/chapter5-listproperties/piechart.h
index feea3d2789..5ba6b10b7a 100644
--- a/examples/declarative/tutorials/extending/chapter5-listproperties/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter5-listproperties/piechart.h
@@ -40,7 +40,7 @@
#ifndef PIECHART_H
#define PIECHART_H
-#include <QQuickItem>
+#include <QtQuick/QQuickItem>
class PieSlice;
diff --git a/examples/declarative/tutorials/extending/chapter5-listproperties/pieslice.h b/examples/declarative/tutorials/extending/chapter5-listproperties/pieslice.h
index 157e9cda77..a9174fbe0c 100644
--- a/examples/declarative/tutorials/extending/chapter5-listproperties/pieslice.h
+++ b/examples/declarative/tutorials/extending/chapter5-listproperties/pieslice.h
@@ -40,7 +40,7 @@
#ifndef PIESLICE_H
#define PIESLICE_H
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
#include <QColor>
//![0]
diff --git a/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro b/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
index 47fe0a2fde..c243ec4572 100644
--- a/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
+++ b/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
@@ -1,6 +1,6 @@
TEMPLATE = lib
CONFIG += qt plugin
-QT += declarative
+QT += declarative quick
DESTDIR = ChartsPlugin
TARGET = chartsplugin
diff --git a/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h
index 2d58360245..927dc25e5c 100644
--- a/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h
+++ b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h
@@ -40,7 +40,7 @@
#ifndef PIECHART_H
#define PIECHART_H
-#include <QQuickItem>
+#include <QtQuick/QQuickItem>
class PieSlice;
diff --git a/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h
index 4251e49396..c09b37d1c8 100644
--- a/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h
+++ b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h
@@ -40,7 +40,7 @@
#ifndef PIESLICE_H
#define PIESLICE_H
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
#include <QColor>
class PieSlice : public QQuickPaintedItem
diff --git a/modules/qt_quick.pri b/modules/qt_quick.pri
new file mode 100644
index 0000000000..0dc827b732
--- /dev/null
+++ b/modules/qt_quick.pri
@@ -0,0 +1,17 @@
+QT.quick.VERSION = 5.0.0
+QT.quick.MAJOR_VERSION = 5
+QT.quick.MINOR_VERSION = 0
+QT.quick.PATCH_VERSION = 0
+
+QT.quick.name = QtQuick
+QT.quick.bins = $$QT_MODULE_BIN_BASE
+QT.quick.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtQuick
+QT.quick.private_includes = $$QT_MODULE_INCLUDE_BASE/QtQuick/$$QT.quick.VERSION
+QT.quick.sources = $$QT_MODULE_BASE/src/quick
+QT.quick.libs = $$QT_MODULE_LIB_BASE
+QT.quick.plugins = $$QT_MODULE_PLUGIN_BASE
+QT.quick.imports = $$QT_MODULE_IMPORT_BASE
+QT.quick.depends = declarative
+QT.quick.DEFINES = QT_QUICK_LIB
+
+QT_CONFIG += quick
diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
index 7c74c63801..c2ee93b665 100644
--- a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
@@ -66,7 +66,7 @@ class QDeclarativeWatcher;
class QDataStream;
class QDeclarativeDebugStatesDelegate;
-class QDeclarativeEngineDebugService : public QDeclarativeDebugService
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeEngineDebugService : public QDeclarativeDebugService
{
Q_OBJECT
public:
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index 265e4eba33..ca81a4a3d3 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -31,10 +31,3 @@ HEADERS += qtdeclarativeversion.h
include(util/util.pri)
include(qml/qml.pri)
include(debugger/debugger.pri)
-include(scenegraph/scenegraph.pri)
-include(items/items.pri)
-include(particles/particles.pri)
-include(designer/designer.pri)
-
-HEADERS += qtquick2_p.h
-SOURCES += qtquick2.cpp
diff --git a/src/declarative/designer/designersupport.cpp b/src/declarative/designer/designersupport.cpp
deleted file mode 100644
index 9c565c138c..0000000000
--- a/src/declarative/designer/designersupport.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "designersupport.h"
-#include <private/qquickitem_p.h>
-
-#include <private/qquickshadereffectsource_p.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qdeclarativeengine_p.h>
-#include <private/qquickview_p.h>
-#include <private/qdeclarativestategroup_p.h>
-#include <QtGui/QImage>
-
-QT_BEGIN_NAMESPACE
-
-DesignerSupport::DesignerSupport()
-{
-}
-
-DesignerSupport::~DesignerSupport()
-{
- QHash<QQuickItem*, QQuickShaderEffectTexture*>::iterator iterator;
-
- for (iterator = m_itemTextureHash.begin(); iterator != m_itemTextureHash.end(); ++iterator) {
- QQuickShaderEffectTexture *texture = iterator.value();
- QQuickItem *item = iterator.key();
- QQuickItemPrivate::get(item)->derefFromEffectItem(true);
- delete texture;
- }
-}
-
-void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
-{
- if (referencedItem == 0)
- return;
-
- QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
- QQuickCanvasPrivate::get(referencedItem->canvas())->updateDirtyNode(referencedItem);
-
- Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode);
-
- if (!m_itemTextureHash.contains(referencedItem)) {
- QQuickShaderEffectTexture *texture = new QQuickShaderEffectTexture(referencedItem);
-
- texture->setLive(true);
- texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode);
- texture->setRect(referencedItem->boundingRect());
- texture->setSize(referencedItem->boundingRect().size().toSize());
- texture->setRecursive(true);
-#ifndef QT_OPENGL_ES
- texture->setFormat(GL_RGBA8);
-#else
- texture->setFormat(GL_RGBA);
-#endif
- texture->setHasMipmaps(false);
-
- m_itemTextureHash.insert(referencedItem, texture);
- }
-}
-
-void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
-{
- if (referencedItem == 0)
- return;
-
- delete m_itemTextureHash.take(referencedItem);
- QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
-}
-
-QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
-{
- if (referencedItem == 0 || referencedItem->parentItem() == 0) {
- qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
- return QImage();
- }
-
- QQuickShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
-
- Q_ASSERT(renderTexture);
- if (renderTexture == 0)
- return QImage();
- renderTexture->setRect(boundingRect);
- renderTexture->setSize(imageSize);
- renderTexture->updateTexture();
-
- QImage renderImage = renderTexture->toImage();
- renderImage = renderImage.mirrored(false, true);
-
- if (renderImage.size().isEmpty())
- qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
-
- return renderImage;
-}
-
-bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
-{
- if (referencedItem == 0)
- return false;
-
- return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
-}
-
-void DesignerSupport::resetDirty(QQuickItem *referencedItem)
-{
- if (referencedItem == 0)
- return;
-
- QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
- QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
-}
-
-QTransform DesignerSupport::canvasTransform(QQuickItem *referencedItem)
-{
- if (referencedItem == 0)
- return QTransform();
-
- return QQuickItemPrivate::get(referencedItem)->itemToCanvasTransform();
-}
-
-QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
-{
- if (referencedItem == 0)
- return QTransform();
-
- QTransform parentTransform;
-
- QQuickItemPrivate::get(referencedItem)->itemToParentTransform(parentTransform);
-
- return parentTransform;
-}
-
-QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
-{
- switch (anchorLine) {
- case QQuickAnchorLine::Left: return QLatin1String("left");
- case QQuickAnchorLine::Right: return QLatin1String("right");
- case QQuickAnchorLine::Top: return QLatin1String("top");
- case QQuickAnchorLine::Bottom: return QLatin1String("bottom");
- case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter");
- case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter");
- case QQuickAnchorLine::Baseline: return QLatin1String("baseline");
- case QQuickAnchorLine::Invalid:
- default: return QString();
- }
-}
-
-bool isValidAnchorName(const QString &name)
-{
- static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
- << QLatin1String("anchors.left")
- << QLatin1String("anchors.right")
- << QLatin1String("anchors.bottom")
- << QLatin1String("anchors.verticalCenter")
- << QLatin1String("anchors.horizontalCenter")
- << QLatin1String("anchors.fill")
- << QLatin1String("anchors.centerIn")
- << QLatin1String("anchors.baseline"));
-
- return anchorNameList.contains(name);
-}
-
-bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
-{
- Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
- QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
- QQuickAnchors *anchors = fromItemPrivate->anchors();
- return anchors->fill() == toItem
- || anchors->centerIn() == toItem
- || anchors->bottom().item == toItem
- || anchors->top().item == toItem
- || anchors->left().item == toItem
- || anchors->right().item == toItem
- || anchors->verticalCenter().item == toItem
- || anchors->horizontalCenter().item == toItem
- || anchors->baseline().item == toItem;
-}
-
-bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
-{
- foreach (QQuickItem *childItem, fromItem->childItems()) {
- if (childItem) {
- if (isAnchoredTo(childItem, toItem))
- return true;
-
- if (areChildrenAnchoredTo(childItem, toItem))
- return true;
- }
- }
-
- return false;
-}
-
-QQuickAnchors *anchors(QQuickItem *item)
-{
- QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
- return itemPrivate->anchors();
-}
-
-QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
-{
- if (name == QLatin1String("anchors.top"))
- return QQuickAnchors::TopAnchor;
-
- if (name == QLatin1String("anchors.left"))
- return QQuickAnchors::LeftAnchor;
-
- if (name == QLatin1String("anchors.bottom"))
- return QQuickAnchors::BottomAnchor;
-
- if (name == QLatin1String("anchors.right"))
- return QQuickAnchors::RightAnchor;
-
- if (name == QLatin1String("anchors.horizontalCenter"))
- return QQuickAnchors::HCenterAnchor;
-
- if (name == QLatin1String("anchors.verticalCenter"))
- return QQuickAnchors::VCenterAnchor;
-
- if (name == QLatin1String("anchors.baseline"))
- return QQuickAnchors::BaselineAnchor;
-
-
- Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
- return QQuickAnchors::LeftAnchor;
-}
-
-bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
-{
- if (!isValidAnchorName(name))
- return false;
-
- if (name == QLatin1String("anchors.fill"))
- return anchors(item)->fill() != 0;
-
- if (name == QLatin1String("anchors.centerIn"))
- return anchors(item)->centerIn() != 0;
-
- if (name == QLatin1String("anchors.right"))
- return anchors(item)->right().item != 0;
-
- if (name == QLatin1String("anchors.top"))
- return anchors(item)->top().item != 0;
-
- if (name == QLatin1String("anchors.left"))
- return anchors(item)->left().item != 0;
-
- if (name == QLatin1String("anchors.bottom"))
- return anchors(item)->bottom().item != 0;
-
- if (name == QLatin1String("anchors.horizontalCenter"))
- return anchors(item)->horizontalCenter().item != 0;
-
- if (name == QLatin1String("anchors.verticalCenter"))
- return anchors(item)->verticalCenter().item != 0;
-
- if (name == QLatin1String("anchors.baseline"))
- return anchors(item)->baseline().item != 0;
-
- return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
-}
-
-QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
-{
- return anchors(item)->fill();
-}
-
-QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
-{
- return anchors(item)->centerIn();
-}
-
-
-
-QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context)
-{
- QObject *targetObject = 0;
- QString targetName;
-
- if (name == QLatin1String("anchors.fill")) {
- targetObject = anchors(item)->fill();
- } else if (name == QLatin1String("anchors.centerIn")) {
- targetObject = anchors(item)->centerIn();
- } else {
- QDeclarativeProperty metaProperty(item, name, context);
- if (!metaProperty.isValid())
- return QPair<QString, QObject*>();
-
- QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
- if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
- targetObject = anchorLine.item;
- targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
- }
-
- }
-
- return QPair<QString, QObject*>(targetName, targetObject);
-}
-
-void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
-{
- if (name == QLatin1String("anchors.fill")) {
- anchors(item)->resetFill();
- } else if (name == QLatin1String("anchors.centerIn")) {
- anchors(item)->resetCenterIn();
- } else if (name == QLatin1String("anchors.top")) {
- anchors(item)->resetTop();
- } else if (name == QLatin1String("anchors.left")) {
- anchors(item)->resetLeft();
- } else if (name == QLatin1String("anchors.right")) {
- anchors(item)->resetRight();
- } else if (name == QLatin1String("anchors.bottom")) {
- anchors(item)->resetBottom();
- } else if (name == QLatin1String("anchors.horizontalCenter")) {
- anchors(item)->resetHorizontalCenter();
- } else if (name == QLatin1String("anchors.verticalCenter")) {
- anchors(item)->resetVerticalCenter();
- } else if (name == QLatin1String("anchors.baseline")) {
- anchors(item)->resetBaseline();
- }
-}
-
-QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
-{
- QList<QObject*> objectList;
- QList<QDeclarativeState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
- qCopy(stateList.begin(), stateList.end(), objectList.begin());
-
- return objectList;
-}
-
-bool DesignerSupport::isComponentComplete(QQuickItem *item)
-{
- return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
-}
-
-int DesignerSupport::borderWidth(QQuickItem *item)
-{
- QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
- if (rectangle)
- return rectangle->border()->width();
-
- return 0;
-}
-
-void DesignerSupport::refreshExpressions(QDeclarativeContext *context)
-{
- QDeclarativeContextPrivate::get(context)->data->refreshExpressions();
-}
-
-void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
-{
- QQuickViewPrivate::get(view)->setRootObject(item);
-}
-
-bool DesignerSupport::isValidWidth(QQuickItem *item)
-{
- return QQuickItemPrivate::get(item)->heightValid;
-}
-
-bool DesignerSupport::isValidHeight(QQuickItem *item)
-{
- return QQuickItemPrivate::get(item)->widthValid;
-}
-
-void DesignerSupport::updateDirtyNode(QQuickItem *item)
-{
- QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/designer/designersupport.h b/src/declarative/designer/designersupport.h
deleted file mode 100644
index 7654363276..0000000000
--- a/src/declarative/designer/designersupport.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DESIGNERSUPPORT_H
-#define DESIGNERSUPPORT_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/QtGlobal>
-#include <QtCore/QHash>
-#include <QtCore/QRectF>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QQuickShaderEffectTexture;
-class QImage;
-class QTransform;
-class QDeclarativeContext;
-class QQuickView;
-
-
-class Q_DECLARATIVE_EXPORT DesignerSupport
-{
-public:
- enum DirtyType {
- TransformOrigin = 0x00000001,
- Transform = 0x00000002,
- BasicTransform = 0x00000004,
- Position = 0x00000008,
- Size = 0x00000010,
-
- ZValue = 0x00000020,
- Content = 0x00000040,
- Smooth = 0x00000080,
- OpacityValue = 0x00000100,
- ChildrenChanged = 0x00000200,
- ChildrenStackingChanged = 0x00000400,
- ParentChanged = 0x00000800,
-
- Clip = 0x00001000,
- Canvas = 0x00002000,
-
- EffectReference = 0x00008000,
- Visible = 0x00010000,
- HideReference = 0x00020000,
-
- TransformUpdateMask = TransformOrigin | Transform | BasicTransform | Position | Size | Canvas,
- ComplexTransformUpdateMask = Transform | Canvas,
- ContentUpdateMask = Size | Content | Smooth | Canvas,
- ChildrenUpdateMask = ChildrenChanged | ChildrenStackingChanged | EffectReference | Canvas
- };
-
-
- DesignerSupport();
- ~DesignerSupport();
-
- void refFromEffectItem(QQuickItem *referencedItem, bool hide = true);
- void derefFromEffectItem(QQuickItem *referencedItem, bool unhide = true);
-
- QImage renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize);
-
- static bool isDirty(QQuickItem *referencedItem, DirtyType dirtyType);
- static void resetDirty(QQuickItem *referencedItem);
-
- static QTransform canvasTransform(QQuickItem *referencedItem);
- static QTransform parentTransform(QQuickItem *referencedItem);
-
- static bool isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem);
- static bool areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem);
- static bool hasAnchor(QQuickItem *item, const QString &name);
- static QQuickItem *anchorFillTargetItem(QQuickItem *item);
- static QQuickItem *anchorCenterInTargetItem(QQuickItem *item);
- static QPair<QString, QObject*> anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context);
- static void resetAnchor(QQuickItem *item, const QString &name);
-
-
- static QList<QObject*> statesForItem(QQuickItem *item);
-
- static bool isComponentComplete(QQuickItem *item);
-
- static int borderWidth(QQuickItem *item);
-
- static void refreshExpressions(QDeclarativeContext *context);
-
- static void setRootItem(QQuickView *view, QQuickItem *item);
-
- static bool isValidWidth(QQuickItem *item);
- static bool isValidHeight(QQuickItem *item);
-
- static void updateDirtyNode(QQuickItem *item);
-
-private:
- QHash<QQuickItem*, QQuickShaderEffectTexture*> m_itemTextureHash;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // DESIGNERSUPPORT_H
diff --git a/src/declarative/items/context2d/qquickcanvasitem.cpp b/src/declarative/items/context2d/qquickcanvasitem.cpp
deleted file mode 100644
index 81b7a49722..0000000000
--- a/src/declarative/items/context2d/qquickcanvasitem.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <private/qsgadaptationlayer_p.h>
-#include "qquickcanvasitem_p.h"
-#include <private/qquickitem_p.h>
-#include "qquickcontext2d_p.h"
-#include "qquickcontext2dnode_p.h"
-#include "qquickcontext2dtexture_p.h"
-#include <private/qdeclarativepixmapcache_p.h>
-
-#include <qdeclarativeinfo.h>
-#include <private/qdeclarativeengine_p.h>
-#include <QtCore/QBuffer>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickCanvasItemPrivate : public QQuickItemPrivate
-{
-public:
- QQuickCanvasItemPrivate();
- ~QQuickCanvasItemPrivate();
- QQuickContext2D* context;
- QQuickContext2DTexture* texture;
- QSizeF canvasSize;
- QSize tileSize;
- QRectF canvasWindow;
- QRectF dirtyRect;
- uint renderInThread : 1;
- uint hasCanvasSize :1;
- uint hasTileSize :1;
- uint hasCanvasWindow :1;
- uint componentCompleted :1;
- QQuickCanvasItem::RenderTarget renderTarget;
- QHash<QUrl, QDeclarativePixmap*> images;
- QUrl baseUrl;
-};
-
-QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
- : QQuickItemPrivate()
- , context(0)
- , texture(0)
- , canvasSize(1, 1)
- , tileSize(1, 1)
- , renderInThread(false)
- , hasCanvasSize(false)
- , hasTileSize(false)
- , hasCanvasWindow(false)
- , componentCompleted(false)
- , renderTarget(QQuickCanvasItem::FramebufferObject)
-{
-}
-
-QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
-{
- qDeleteAll(images);
-}
-
-/*!
- \qmlclass Canvas QQuickCanvasItem
- \inqmlmodule QtQuick 2
- \since QtQuick 2.0
- \brief The Canvas item provides a 2D canvas element which enables drawing via Javascript.
- \inherits Item
- \ingroup qml-basic-visual-elements
-
- The Canvas item allows drawing of straight and curved lines, simple and
- complex shapes, graphs, and referenced graphic images. It can also add text, colors,
- shadows, gradients, and patterns, and do low level pixel operations. The Canvas
- output may be saved as an image file or serialized to a url.
-
- To define a drawing area in the Canvas item set the \c width and \c height properties.
- For example, the following code creates a Canvas item which has a drawing area with a height of 100
- pixels and width of 200 pixels:
- \qml
- import QtQuick 2.0
- Canvas {
- id:mycanvas
- width:100
- height:200
- }
- \endqml
-
- Currently the Canvas item only supports the two-dimensional rendering context.
-
- \section1 Threaded Rendering and Render Target
-
- The Canvas item supports two render targets: \c Canvas.Image and \c Canvas.FramebufferObject.
-
- The \c Canvas.Image render target is a \a QImage object. This render target supports background
- thread rendering, allowing complex or long running painting to be executed without blocking the UI.
-
- The Canvas.FramebufferObject render target utilizes OpenGL hardware accelaration rather than rendering into
- system memory, which in many cases results in faster rendering.
-
- The default render target is Canvas.Image and the default renderInThread property is
- false.
-
- \section1 Tiled Canvas
- The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize
- and \l canvasWindow properties.
-
- Tiling allows efficient display of a very large virtual via a smaller canvas
- window. The actual memory consumption is in relatation to the canvas window size. The painting
- code can draw within the virtual canvas without handling coordinate system transformations.
-
- The tiles overlapping with the canvas window may be cached eliminating the need to redraw,
- which can lead to significantly improved performance in some situations.
-
- \section1 Pixel Operations
- All HTML5 2D context pixel operations are supported. In order to ensure improved
- pixel reading/writing performance the \a Canvas.Image render target should be chosen. The
- \a Canvas.FramebufferObject render target requires the pixel data to be exchanged between
- the system memory and the graphic card, which is significantly more expensive. Rendering
- may also be synchronized with the V-sync signal (to avoid {en.wikipedia.org/wiki/Screen_tearing}{screen tearing})
- which will futher impact pixel operations with \c Canvas.FrambufferObject render target.
-
- \section1 Tips for Porting Existing HTML5 Canvas applications
-
- Although the Canvas item is provides a HTML5 like API, HTML5 canvas applications
- need to be modified to run in the Canvas item:
- \list
- \o Replace all DOM API calls with QML property bindings or Canvas item methods.
- \o Replace all HTML event handlers with the \a MouseArea item.
- \o Change setInterval/setTimeout function calls with the \a Timer item.
- \o Place painting code into the \a QtQuick2::Canvas::onPaint handler and trigger
- painting by calling the \c markDirty or \c requestPaint methods.
- \o To draw images, load them by calling the Canvas's loadImage method and then request to paint
- them in the onImageLoaded handler.
- \endlist
-
- \sa QtQuick2::Context2D
-*/
-
-QQuickCanvasItem::QQuickCanvasItem(QQuickItem *parent)
- : QQuickItem(*(new QQuickCanvasItemPrivate), parent)
-{
- setFlag(ItemHasContents);
-}
-
-QQuickCanvasItem::~QQuickCanvasItem()
-{
- Q_D(QQuickCanvasItem);
- delete d->context;
-}
-
-/*!
- \qmlproperty size QtQuick2::Canvas::canvasSize
- Holds the logical canvas size that the context paints on.
-
- By default, the canvas size is the same size as the current canvas item size.
- By setting the canvasSize, tileSize and canvasWindow, the Canvas
- item can act as a large virtual canvas with many seperately rendered tile rectangles
- Only those tiles within the current canvas window are painted by
- the Canvas render engine.
-
- \sa QtQuick2::Canvas::tileSize QtQuick2::Canvas::canvasWindow
-*/
-QSizeF QQuickCanvasItem::canvasSize() const
-{
- Q_D(const QQuickCanvasItem);
- return d->canvasSize;
-}
-
-void QQuickCanvasItem::setCanvasSize(const QSizeF & size)
-{
- Q_D(QQuickCanvasItem);
- if (d->canvasSize != size) {
- d->hasCanvasSize = true;
- d->canvasSize = size;
- emit canvasSizeChanged();
- polish();
- update();
- }
-}
-
-/*!
- \qmlproperty size QtQuick2::Canvas::tileSize
- Holds the canvas rendering tile size.
-
- The Canvas item enters tiled mode by setting canvasSize, tileSize and
- the canvasWindow. This can improve rendering performance
- by rendering and caching tiles instead of rendering the whole canvas every time.
-
- Memory will be consumed only by those tiles within the current visible region.
-
- By default the tileSize is the same as the canvasSize.
-
- \sa QtQuick2::Canvas::canvaasSize QtQuick2::Canvas::canvasWindow
-*/
-QSize QQuickCanvasItem::tileSize() const
-{
- Q_D(const QQuickCanvasItem);
- return d->tileSize;
-}
-
-void QQuickCanvasItem::setTileSize(const QSize & size)
-{
- Q_D(QQuickCanvasItem);
- if (d->tileSize != size) {
- d->hasTileSize = true;
- d->tileSize = size;
-
- emit tileSizeChanged();
- polish();
- update();
- }
-}
-
-/*!
- \qmlproperty rect QtQuick2::Canvas::canvasWindow
- Holds the current canvas visible window.
-
- By default the canvasWindow size is the same as the Canvas item
- size with the topleft point as (0, 0).
-
- If the canvasSize is different to the Canvas item size, the Canvas
- item can display different visible areas by changing the canvas windowSize
- and/or position.
-
- \sa QtQuick2::Canvas::canvasSize QtQuick2::Canvas::tileSize
-*/
-QRectF QQuickCanvasItem::canvasWindow() const
-{
- Q_D(const QQuickCanvasItem);
- return d->canvasWindow;
-}
-
-void QQuickCanvasItem::setCanvasWindow(const QRectF& rect)
-{
- Q_D(QQuickCanvasItem);
- if (d->canvasWindow != rect) {
- d->canvasWindow = rect;
-
- d->hasCanvasWindow = true;
- emit canvasWindowChanged();
- polish();
- update();
- }
-}
-
-
-QQuickContext2D* QQuickCanvasItem::context() const
-{
- Q_D(const QQuickCanvasItem);
- return d->context;
-}
-/*!
- \qmlproperty bool QtQuick2::Canvas::renderInThread
- Holds the current canvas rendering mode.
-
- Set renderInThread to true to render complex and long
- running painting in a dedicated background
- thread, avoiding blocking the main UI.
-
- \note: Not all renderTargets support background rendering. If background rendering
- is not supported by the current renderTarget, the renderInThread
- property is ignored.
-
- The default value is false.
- \sa QtQuick2::Canvas::renderTarget
-*/
-bool QQuickCanvasItem::renderInThread() const
-{
- Q_D(const QQuickCanvasItem);
- return d->renderInThread;
-}
-/*!
- \qmlproperty bool QtQuick2::Canvas::renderTarget
- Holds the current canvas render target.
-
- \list
- \o Canvas.Image - render to an in memory image buffer, the render
- target supports background rendering.
- \o Canvas.FramebufferObject - render to an OpenGL frame buffer,
- this render target will ignore the
- renderInThread property. The actual
- rendering happens in the main QML rendering
- process, which may be in a seperate render thread
- or in the main GUI thread depending upon the platform.
- \endlist
-
- The default render target is \c Canvas.Image.
- \sa QtQuick2::Canvas::renderInThread
-*/
-QQuickCanvasItem::RenderTarget QQuickCanvasItem::renderTarget() const
-{
- Q_D(const QQuickCanvasItem);
- return d->renderTarget;
-}
-
-void QQuickCanvasItem::setRenderTarget(RenderTarget target)
-{
- Q_D(QQuickCanvasItem);
- if (d->renderTarget != target) {
- d->renderTarget = target;
-
- if (d->componentCompleted)
- createTexture();
- emit renderTargetChanged();
- }
-}
-
-void QQuickCanvasItem::_doPainting(const QRectF& region)
-{
- Q_D(QQuickCanvasItem);
- emit paint(QDeclarativeV8Handle::fromHandle(d->context->v8value())
- , QQuickContext2DTexture::tiledRect(region, d->tileSize));
- if (d->texture)
- d->texture->wake();
-}
-
-void QQuickCanvasItem::setRenderInThread(bool renderInThread)
-{
- Q_D(QQuickCanvasItem);
- if (d->renderInThread != renderInThread) {
- d->renderInThread = renderInThread;
-
- if (d->componentCompleted)
- createTexture();
-
- if (d->renderInThread)
- connect(this, SIGNAL(painted()), SLOT(update()));
- else
- disconnect(this, SIGNAL(painted()), this, SLOT(update()));
- emit renderInThreadChanged();
- polish();
- update();
- }
-}
-
-void QQuickCanvasItem::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
-{
- Q_D(QQuickCanvasItem);
- QQuickItem::geometryChanged(newGeometry, oldGeometry);
-
- const qreal w = newGeometry.width();
- const qreal h = newGeometry.height();
-
- if (!d->hasCanvasSize) {
- d->canvasSize = QSizeF(w, h);
- emit canvasSizeChanged();
- }
-
- if (!d->hasTileSize) {
- d->tileSize = d->canvasSize.toSize();
- emit tileSizeChanged();
- }
-
- if (!d->hasCanvasWindow) {
- d->canvasWindow = newGeometry;
- emit canvasWindowChanged();
- }
-
- polish();
- update();
-}
-
-void QQuickCanvasItem::componentComplete()
-{
- Q_D(QQuickCanvasItem);
- QQuickItem::componentComplete();
-
- if (!d->context)
- createContext();
- createTexture();
-
- d->baseUrl = qmlEngine(this)->contextForObject(this)->baseUrl();
- requestPaint();
- updatePolish(); //force update the canvas sizes to texture for the first time
- update();
- d->componentCompleted = true;
-}
-
-void QQuickCanvasItem::updatePolish()
-{
- Q_D(QQuickCanvasItem);
- QQuickItem::updatePolish();
- if (d->texture) {
- if (!d->renderInThread && d->dirtyRect.isValid())
- _doPainting(d->dirtyRect);
-
- d->texture->canvasChanged(d->canvasSize.toSize()
- , d->tileSize
- , d->canvasWindow.toAlignedRect()
- , d->dirtyRect.toAlignedRect()
- , d->smooth);
- d->dirtyRect = QRectF();
- }
-}
-
-QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- Q_D(QQuickCanvasItem);
- QQuickContext2DNode *node = static_cast<QQuickContext2DNode *>(oldNode);
- if (!node)
- node = new QQuickContext2DNode(this);
-
- node->setTexture(d->texture);
- node->setSize(d->canvasWindow.size());
- node->update();
- return node;
-}
-
-void QQuickCanvasItem::createTexture()
-{
- Q_D(QQuickCanvasItem);
-
- if (!d->texture
- || d->texture->threadRendering() != d->renderInThread
- || d->texture->renderTarget() != d->renderTarget) {
- if (d->texture) {
- d->texture->deleteLater();
- d->texture = 0;
- }
-
- if (d->renderTarget == QQuickCanvasItem::Image) {
- d->texture = new QQuickContext2DImageTexture(d->renderInThread);
- } else if (d->renderTarget == QQuickCanvasItem::FramebufferObject) {
- d->texture = new QQuickContext2DFBOTexture();
- }
-
- if (d->renderInThread && !d->texture->supportThreadRendering()) {
- qWarning("Canvas: render target does not support thread rendering, force to non-thread rendering mode.");
- d->renderInThread = false;
- emit renderInThreadChanged();
- }
-
- if (d->renderInThread)
- connect(d->texture, SIGNAL(textureChanged()), this, SLOT(update()));
-
- d->texture->setItem(this);
- }
-}
-
-void QQuickCanvasItem::createContext()
-{
- Q_D(QQuickCanvasItem);
-
- delete d->context;
-
- d->context = new QQuickContext2D(this);
-
- QV8Engine *e = QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this));
- d->context->setV8Engine(e);
-}
-
-/*!
- \qmlmethod object QtQuick2::Canvas::getContext(string contextId)
-
- Currently, the canvas item only supports the 2D context. If the \a contextId
- parameter isn't provided or is "2d", then the QtQuick2::Context2D object is
- returned, otherwise returns an invalid value.
- */
-QDeclarativeV8Handle QQuickCanvasItem::getContext(const QString &contextId)
-{
- Q_D(QQuickCanvasItem);
-
- if (contextId.toLower() != QLatin1String("2d"))
- return QDeclarativeV8Handle::fromHandle(v8::Undefined());
-
- if (!d->context)
- createContext();
- return QDeclarativeV8Handle::fromHandle(d->context->v8value());
-}
-
-/*!
- \qmlmethod void QtQuick2::Canvas::markDirty(rect region)
-
- Mark the given \a region as dirty, so that when this region is visible
- the canvas renderer will redraw it. This will trigger the "onPaint" signal
- handler function.
-
- \sa QtQuick2::Canvas::paint QtQuick2::Canvas::requestPaint
- */
-void QQuickCanvasItem::markDirty(const QRectF& region)
-{
- Q_D(QQuickCanvasItem);
- d->dirtyRect |= region;
- if (d->componentCompleted)
- polish();
- update();
-}
-
-
-/*!
- \qmlmethod bool QtQuick2::Canvas::save(string filename)
-
- Save the current canvas content into an image file \a filename.
- The saved image format is automatically decided by the \a filename's
- suffix.
-
- Note: calling this method will force painting the whole canvas, not just the
- current canvas visible window.
-
- \sa canvasWindow canvasSize toDataURL
- */
-bool QQuickCanvasItem::save(const QString &filename) const
-{
- Q_D(const QQuickCanvasItem);
- QUrl url = d->baseUrl.resolved(QUrl::fromLocalFile(filename));
- return toImage().save(url.toLocalFile());
-}
-
-QImage QQuickCanvasItem::loadedImage(const QUrl& url)
-{
- Q_D(QQuickCanvasItem);
- QUrl fullPathUrl = d->baseUrl.resolved(url);
- if (!d->images.contains(fullPathUrl)) {
- loadImage(url);
- }
- QDeclarativePixmap* pix = d->images.value(fullPathUrl);
- if (pix->isLoading() || pix->isError()) {
- return QImage();
- }
- return pix->image();
-}
-
-/*!
- \qmlmethod void QtQuick2::Canvas::loadImage(url image)
- Loads the given \c image asynchronously.
-
- When the image is ready, onImageLoaded will be emitted.
- The loaded image can be unloaded by the \a QtQuick2::Canvas::unloadImage method.
-
- Note: Only loaded images can be painted on the Canvas item.
- \sa QtQuick2::Canvas::unloadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded
- \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage
- */
-void QQuickCanvasItem::loadImage(const QUrl& url)
-{
- Q_D(QQuickCanvasItem);
- QUrl fullPathUrl = d->baseUrl.resolved(url);
- if (!d->images.contains(fullPathUrl)) {
- QDeclarativePixmap* pix = new QDeclarativePixmap();
- d->images.insert(fullPathUrl, pix);
-
- pix->load(qmlEngine(this)
- , fullPathUrl
- , QDeclarativePixmap::Cache | QDeclarativePixmap::Asynchronous);
- pix->connectFinished(this, SIGNAL(imageLoaded()));
- }
-}
-/*!
- \qmlmethod void QtQuick2::Canvas::unloadImage(url image)
- Unloads the \c image.
-
- Once an image is unloaded it cannot be painted by the canvas context
- unless it is loaded again.
-
- \sa QtQuick2::Canvas::loadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded
- \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage
- */
-void QQuickCanvasItem::unloadImage(const QUrl& url)
-{
- Q_D(QQuickCanvasItem);
- QUrl removeThis = d->baseUrl.resolved(url);
- if (d->images.contains(removeThis)) {
- delete d->images.value(removeThis);
- d->images.remove(removeThis);
- }
-}
-
-/*!
- \qmlmethod void QtQuick2::Canvas::isImageError(url image)
- Returns true if the \a image failed to load.
-
- \sa QtQuick2::Canvas::loadImage
- */
-bool QQuickCanvasItem::isImageError(const QUrl& url) const
-{
- Q_D(const QQuickCanvasItem);
- QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isError();
-}
-
-/*!
- \qmlmethod void QtQuick2::Canvas::isImageLoading(url image)
- Returns true if the \a image is currently loading.
-
- \sa QtQuick2::Canvas::loadImage
- */
-bool QQuickCanvasItem::isImageLoading(const QUrl& url) const
-{
- Q_D(const QQuickCanvasItem);
- QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isLoading();
-}
-/*!
- \qmlmethod void QtQuick2::Canvas::isImageLoaded(url image)
- Returns true if the \a image is sucessfully loaded and ready to use.
-
- \sa QtQuick2::Canvas::loadImage
- */
-bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const
-{
- Q_D(const QQuickCanvasItem);
- QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isReady();
-}
-
-QImage QQuickCanvasItem::toImage(const QRectF& region) const
-{
- Q_D(const QQuickCanvasItem);
- if (d->texture) {
- if (region.isEmpty())
- return d->texture->toImage(canvasWindow());
- else
- return d->texture->toImage(region);
- }
- return QImage();
-}
-
-/*!
- \qmlmethod string QtQuick2::Canvas::toDataURL(string mimeType)
-
- Returns a data URL for the image in the canvas.
-
- The default \a mimeType is "image/png".
-
- \sa QtQuick2::Canvas::save
- */
-QString QQuickCanvasItem::toDataURL(const QString& mimeType) const
-{
- QImage image = toImage();
-
- if (!image.isNull()) {
- QByteArray ba;
- QBuffer buffer(&ba);
- buffer.open(QIODevice::WriteOnly);
- QString mime = mimeType.toLower();
- QString type;
- if (mime == QLatin1Literal("image/png")) {
- type = QLatin1Literal("PNG");
- } else if (mime == QLatin1Literal("image/bmp"))
- type = QLatin1Literal("BMP");
- else if (mime == QLatin1Literal("image/jpeg"))
- type = QLatin1Literal("JPEG");
- else if (mime == QLatin1Literal("image/x-portable-pixmap"))
- type = QLatin1Literal("PPM");
- else if (mime == QLatin1Literal("image/tiff"))
- type = QLatin1Literal("TIFF");
- else if (mime == QLatin1Literal("image/xpm"))
- type = QLatin1Literal("XPM");
- else
- return QLatin1Literal("data:,");
-
- image.save(&buffer, type.toAscii());
- buffer.close();
- QString dataUrl = QLatin1Literal("data:%1;base64,%2");
- return dataUrl.arg(mime).arg(QLatin1String(ba.toBase64().constData()));
- }
- return QLatin1Literal("data:,");
-}
-
-/*!
- \qmlsignal QtQuick2::Canvas::onPaint(QtQuick2::Context2D context, rect region)
-
- This handler is called to render the \a region.
-
- This signal can be triggered by QtQuick2::Canvas::markdirty, QtQuick2::Canvas::requestPaint
- or by changing the current canvas window.
-*/
-
-/*!
- \qmlsignal QtQuick2::Canvas::onPainted()
-
- This handler is called after all context painting commands are executed and
- the Canvas has been rendered.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/context2d/qquickcanvasitem_p.h b/src/declarative/items/context2d/qquickcanvasitem_p.h
deleted file mode 100644
index 293434209a..0000000000
--- a/src/declarative/items/context2d/qquickcanvasitem_p.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCANVASITEM_P_H
-#define QQUICKCANVASITEM_P_H
-
-#include <qquickitem.h>
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class QQuickContext2D;
-class QQuickCanvasItemPrivate;
-class Q_DECLARATIVE_EXPORT QQuickCanvasItem : public QQuickItem
-{
- Q_OBJECT
- Q_ENUMS(RenderTarget)
- Q_ENUMS(ImageFilterMode)
-
- Q_PROPERTY(QSizeF canvasSize READ canvasSize WRITE setCanvasSize NOTIFY canvasSizeChanged)
- Q_PROPERTY(QSize tileSize READ tileSize WRITE setTileSize NOTIFY tileSizeChanged)
- Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
- Q_PROPERTY(bool renderInThread READ renderInThread WRITE setRenderInThread NOTIFY renderInThreadChanged)
- Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
-public:
- enum RenderTarget {
- Image,
- FramebufferObject
- };
-
- enum ImageFilterMode {
- Threshold,
- Mono,
- GrayScale,
- Brightness,
- Invert,
- Blur,
- Opaque,
- Convolute
- };
-
- QQuickCanvasItem(QQuickItem *parent = 0);
- ~QQuickCanvasItem();
-
- QSizeF canvasSize() const;
- void setCanvasSize(const QSizeF &);
-
- QSize tileSize() const;
- void setTileSize(const QSize &);
-
- QRectF canvasWindow() const;
- void setCanvasWindow(const QRectF& rect);
-
- bool renderInThread() const;
- void setRenderInThread(bool renderInThread);
-
- RenderTarget renderTarget() const;
- void setRenderTarget(RenderTarget target);
-
- QQuickContext2D* context() const;
- QImage toImage(const QRectF& region = QRectF()) const;
-
- QImage loadedImage(const QUrl& url);
-
-Q_SIGNALS:
- void paint(QDeclarativeV8Handle context, const QRect &region);
- void painted();
- void canvasSizeChanged();
- void tileSizeChanged();
- void renderInThreadChanged();
- void textureChanged();
- void canvasWindowChanged();
- void renderTargetChanged();
- void imageLoaded();
-public Q_SLOTS:
- QString toDataURL(const QString& type = QLatin1String("image/png")) const;
- QDeclarativeV8Handle getContext(const QString & = QLatin1String("2d"));
- void markDirty(const QRectF& region);
- void requestPaint() {markDirty(canvasWindow());}
- // Save current canvas to disk
- bool save(const QString& filename) const;
- void loadImage(const QUrl& url);
- void unloadImage(const QUrl& url);
- bool isImageLoaded(const QUrl& url) const;
- bool isImageLoading(const QUrl& url) const;
- bool isImageError(const QUrl& url) const;
-private Q_SLOTS:
- void _doPainting(const QRectF& region);
-protected:
- virtual void componentComplete();
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual void updatePolish();
-private:
- void createContext();
- void createTexture();
- Q_DECLARE_PRIVATE(QQuickCanvasItem)
- friend class QQuickContext2D;
- friend class QQuickContext2DTexture;
-};
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickCanvasItem)
-
-QT_END_HEADER
-
-#endif //QQUICKCANVASITEM_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2d.cpp b/src/declarative/items/context2d/qquickcontext2d.cpp
deleted file mode 100644
index 1f7a84baa6..0000000000
--- a/src/declarative/items/context2d/qquickcontext2d.cpp
+++ /dev/null
@@ -1,3540 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickcontext2d_p.h"
-#include "qquickcontext2dcommandbuffer_p.h"
-#include "qquickcanvasitem_p.h"
-#include <private/qquickitem_p.h>
-#include <private/qquickshadereffectsource_p.h>
-#include <QtGui/qopenglframebufferobject.h>
-
-#include <QtCore/qdebug.h>
-#include <private/qsgcontext_p.h>
-#include <private/qdeclarativesvgparser_p.h>
-#include <private/qdeclarativepath_p.h>
-
-#include <private/qquickimage_p_p.h>
-
-#include <QtGui/qguiapplication.h>
-#include <qdeclarativeinfo.h>
-#include <QtCore/qmath.h>
-#include <private/qv8engine_p.h>
-
-#include <qdeclarativeengine.h>
-#include <private/qv8domerrors_p.h>
-#include <QtCore/qnumeric.h>
-
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass Context2D QQuickContext2D
- \inqmlmodule QtQuick 2
- \since QtQuick 2.0
- \brief The Context2D API allows you to draw 2d graphic shapes on the \c Canvas item.
-
- The Context2D object can be created by \c Canvas item's \c getContext() method:
- \code
- Canvas {
- id:canvas
- onPaint:{
- var ctx = canvas.getContext('2d');
- //...
- }
- }
- \endcode
- The Context2D API implements the same \l {http://www.w3.org/TR/2dcontext}{W3C Canvas 2D Context API standard}
- with some enhanced features.
-
- The Context2D API provides the rendering \bold{context} which defines the methods and attributes needed to draw
- on the \c Canvas item. The following assigns the canvas rendering context to a \c{context}
- variable:
- \code
- var context = mycanvas.getContext("2d")
- \endcode
-
- The Context2D API renders the canvas as a coordinate system whose origin (0,0) is
- at the top left corner, as shown in the figure below. Coordinates increase along
- the \c{x} axis from left to right and along the \c{y} axis from top to bottom of
- the canvas.
- \image qml-item-canvas-context.gif
-*/
-
-Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-
-static const double Q_PI = 3.14159265358979323846; // pi
-
-#define DEGREES(t) ((t) * 180.0 / Q_PI)
-
-#define CHECK_CONTEXT(r) if (!r || !r->context || !r->context->buffer()) \
- V8THROW_ERROR("Not a Context2D object");
-
-#define CHECK_CONTEXT_SETTER(r) if (!r || !r->context || !r->context->buffer()) \
- V8THROW_ERROR_SETTER("Not a Context2D object");
-#define qClamp(val, min, max) qMin(qMax(val, min), max)
-#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
-QColor qt_color_from_string(v8::Local<v8::Value> name)
-{
- v8::String::AsciiValue str(name);
-
- char *p = *str;
- int len = str.length();
- //rgb/hsl color string has at least 7 characters
- if (!p || len > 255 || len <= 7)
- return QColor(p);
- else {
- bool isRgb(false), isHsl(false), hasAlpha(false);
- Q_UNUSED(isHsl)
-
- while (isspace(*p)) p++;
- if (strncmp(p, "rgb", 3) == 0)
- isRgb = true;
- else if (strncmp(p, "hsl", 3) == 0)
- isHsl = true;
- else
- return QColor(p);
-
- p+=3; //skip "rgb" or "hsl"
- hasAlpha = (*p == 'a') ? true : false;
-
- ++p; //skip "("
-
- if (hasAlpha) ++p; //skip "a"
-
- int rh, gs, bl, alpha = 255;
-
- //red
- while (isspace(*p)) p++;
- rh = strtol(p, &p, 10);
- if (*p == '%') {
- rh = qRound(rh/100.0 * 255);
- ++p;
- }
- if (*p++ != ',') return QColor();
-
- //green
- while (isspace(*p)) p++;
- gs = strtol(p, &p, 10);
- if (*p == '%') {
- gs = qRound(gs/100.0 * 255);
- ++p;
- }
- if (*p++ != ',') return QColor();
-
- //blue
- while (isspace(*p)) p++;
- bl = strtol(p, &p, 10);
- if (*p == '%') {
- bl = qRound(bl/100.0 * 255);
- ++p;
- }
-
- if (hasAlpha) {
- if (*p++!= ',') return QColor();
- while (isspace(*p)) p++;
- bool ok = false;
- alpha = qRound(qstrtod(p, const_cast<const char **>(&p), &ok) * 255);
- }
-
- if (*p != ')') return QColor();
- if (isRgb)
- return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
- else
- return QColor::fromHsl(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
- }
- return QColor();
-}
-
-QFont qt_font_from_string(const QString& fontString) {
- QFont font;
- // ### this is simplified and incomplete
- // ### TODO:get code from Qt webkit
- QStringList tokens = fontString.split(QLatin1String(" "));
- foreach (const QString &token, tokens) {
- if (token == QLatin1String("italic"))
- font.setItalic(true);
- else if (token == QLatin1String("bold"))
- font.setBold(true);
- else if (token.endsWith(QLatin1String("px"))) {
- QString number = token;
- number.remove(QLatin1String("px"));
- //font.setPointSizeF(number.trimmed().toFloat());
- font.setPixelSize(number.trimmed().toInt());
- } else
- font.setFamily(token);
- }
-
- return font;
-}
-
-
-
-class QQuickContext2DEngineData : public QV8Engine::Deletable
-{
-public:
- QQuickContext2DEngineData(QV8Engine *engine);
- ~QQuickContext2DEngineData();
-
- v8::Persistent<v8::Function> constructorContext;
- v8::Persistent<v8::Function> constructorGradient;
- v8::Persistent<v8::Function> constructorPattern;
- v8::Persistent<v8::Function> constructorPixelArray;
- v8::Persistent<v8::Function> constructorImageData;
-};
-
-V8_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
-
-class QV8Context2DResource : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(Context2DType)
-public:
- QV8Context2DResource(QV8Engine *e) : QV8ObjectResource(e) {}
- QQuickContext2D* context;
-};
-
-class QV8Context2DStyleResource : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(Context2DStyleType)
-public:
- QV8Context2DStyleResource(QV8Engine *e)
- : QV8ObjectResource(e)
- , patternRepeatX(false)
- , patternRepeatY(false)
- {}
- QBrush brush;
- bool patternRepeatX:1;
- bool patternRepeatY:1;
-};
-
-class QV8Context2DPixelArrayResource : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(Context2DPixelArrayType)
-public:
- QV8Context2DPixelArrayResource(QV8Engine *e) : QV8ObjectResource(e) {}
-
- QImage image;
-};
-
-QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
-{
- int sides = radius ? radius : qRound(qSqrt(weights.size()));
- int half = qFloor(sides/2);
-
- QImage dst = QImage(src.size(), src.format());
- int w = src.width();
- int h = src.height();
- for (int y = 0; y < dst.height(); ++y) {
- QRgb *dr = (QRgb*)dst.scanLine(y);
- for (int x = 0; x < dst.width(); ++x) {
- unsigned char* dRgb = ((unsigned char*)&dr[x]);
- unsigned char red=0, green=0, blue=0, alpha=0;
- int sy = y;
- int sx = x;
-
- for (int cy=0; cy<sides; cy++) {
- for (int cx=0; cx<sides; cx++) {
- int scy = sy + cy - half;
- int scx = sx + cx - half;
- if (scy >= 0 && scy < w && scx >= 0 && scx < h) {
- const QRgb *sr = (const QRgb*)(src.constScanLine(scy));
- const unsigned char* sRgb = ((const unsigned char*)&sr[scx]);
- qreal wt = radius ? weights[0] : weights[cy*sides+cx];
- red += sRgb[0] * wt;
- green += sRgb[1] * wt;
- blue += sRgb[2] * wt;
- alpha += sRgb[3] * wt;
- }
- }
- }
- dRgb[0] = red;
- dRgb[1] = green;
- dRgb[2] = blue;
- dRgb[3] = alpha;
- }
- }
- return dst;
-}
-
-void qt_image_boxblur(QImage& image, int radius, bool quality)
-{
- int passes = quality? 3: 1;
- for (int i=0; i < passes; i++) {
- image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0/(radius * radius * 1.0), radius);
- }
-}
-
-static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
-{
- if (compositeOperator == QLatin1String("source-over")) {
- return QPainter::CompositionMode_SourceOver;
- } else if (compositeOperator == QLatin1String("source-out")) {
- return QPainter::CompositionMode_SourceOut;
- } else if (compositeOperator == QLatin1String("source-in")) {
- return QPainter::CompositionMode_SourceIn;
- } else if (compositeOperator == QLatin1String("source-atop")) {
- return QPainter::CompositionMode_SourceAtop;
- } else if (compositeOperator == QLatin1String("destination-atop")) {
- return QPainter::CompositionMode_DestinationAtop;
- } else if (compositeOperator == QLatin1String("destination-in")) {
- return QPainter::CompositionMode_DestinationIn;
- } else if (compositeOperator == QLatin1String("destination-out")) {
- return QPainter::CompositionMode_DestinationOut;
- } else if (compositeOperator == QLatin1String("destination-over")) {
- return QPainter::CompositionMode_DestinationOver;
- } else if (compositeOperator == QLatin1String("lighter")) {
- return QPainter::CompositionMode_Lighten;
- } else if (compositeOperator == QLatin1String("copy")) {
- return QPainter::CompositionMode_Source;
- } else if (compositeOperator == QLatin1String("xor")) {
- return QPainter::CompositionMode_Xor;
- } else if (compositeOperator == QLatin1String("qt-clear")) {
- return QPainter::CompositionMode_Clear;
- } else if (compositeOperator == QLatin1String("qt-destination")) {
- return QPainter::CompositionMode_Destination;
- } else if (compositeOperator == QLatin1String("qt-multiply")) {
- return QPainter::CompositionMode_Multiply;
- } else if (compositeOperator == QLatin1String("qt-screen")) {
- return QPainter::CompositionMode_Screen;
- } else if (compositeOperator == QLatin1String("qt-overlay")) {
- return QPainter::CompositionMode_Overlay;
- } else if (compositeOperator == QLatin1String("qt-darken")) {
- return QPainter::CompositionMode_Darken;
- } else if (compositeOperator == QLatin1String("qt-lighten")) {
- return QPainter::CompositionMode_Lighten;
- } else if (compositeOperator == QLatin1String("qt-color-dodge")) {
- return QPainter::CompositionMode_ColorDodge;
- } else if (compositeOperator == QLatin1String("qt-color-burn")) {
- return QPainter::CompositionMode_ColorBurn;
- } else if (compositeOperator == QLatin1String("qt-hard-light")) {
- return QPainter::CompositionMode_HardLight;
- } else if (compositeOperator == QLatin1String("qt-soft-light")) {
- return QPainter::CompositionMode_SoftLight;
- } else if (compositeOperator == QLatin1String("qt-difference")) {
- return QPainter::CompositionMode_Difference;
- } else if (compositeOperator == QLatin1String("qt-exclusion")) {
- return QPainter::CompositionMode_Exclusion;
- }
- return QPainter::CompositionMode_SourceOver;
-}
-
-static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
-{
- switch (op) {
- case QPainter::CompositionMode_SourceOver:
- return QLatin1String("source-over");
- case QPainter::CompositionMode_DestinationOver:
- return QLatin1String("destination-over");
- case QPainter::CompositionMode_Clear:
- return QLatin1String("qt-clear");
- case QPainter::CompositionMode_Source:
- return QLatin1String("copy");
- case QPainter::CompositionMode_Destination:
- return QLatin1String("qt-destination");
- case QPainter::CompositionMode_SourceIn:
- return QLatin1String("source-in");
- case QPainter::CompositionMode_DestinationIn:
- return QLatin1String("destination-in");
- case QPainter::CompositionMode_SourceOut:
- return QLatin1String("source-out");
- case QPainter::CompositionMode_DestinationOut:
- return QLatin1String("destination-out");
- case QPainter::CompositionMode_SourceAtop:
- return QLatin1String("source-atop");
- case QPainter::CompositionMode_DestinationAtop:
- return QLatin1String("destination-atop");
- case QPainter::CompositionMode_Xor:
- return QLatin1String("xor");
- case QPainter::CompositionMode_Plus:
- return QLatin1String("plus");
- case QPainter::CompositionMode_Multiply:
- return QLatin1String("qt-multiply");
- case QPainter::CompositionMode_Screen:
- return QLatin1String("qt-screen");
- case QPainter::CompositionMode_Overlay:
- return QLatin1String("qt-overlay");
- case QPainter::CompositionMode_Darken:
- return QLatin1String("qt-darken");
- case QPainter::CompositionMode_Lighten:
- return QLatin1String("lighter");
- case QPainter::CompositionMode_ColorDodge:
- return QLatin1String("qt-color-dodge");
- case QPainter::CompositionMode_ColorBurn:
- return QLatin1String("qt-color-burn");
- case QPainter::CompositionMode_HardLight:
- return QLatin1String("qt-hard-light");
- case QPainter::CompositionMode_SoftLight:
- return QLatin1String("qt-soft-light");
- case QPainter::CompositionMode_Difference:
- return QLatin1String("qt-difference");
- case QPainter::CompositionMode_Exclusion:
- return QLatin1String("qt-exclusion");
- default:
- break;
- }
- return QString();
-}
-
-
-static v8::Local<v8::Object> qt_create_image_data(qreal w, qreal h, QV8Engine* engine, const QImage& image)
-{
- QQuickContext2DEngineData *ed = engineData(engine);
- v8::Local<v8::Object> imageData = ed->constructorImageData->NewInstance();
- QV8Context2DPixelArrayResource *r = new QV8Context2DPixelArrayResource(engine);
- if (image.isNull()) {
- r->image = QImage(w, h, QImage::Format_ARGB32);
- r->image.fill(0x00000000);
- } else {
- Q_ASSERT(image.width() == w && image.height() == h);
- r->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
- }
- v8::Local<v8::Object> pixelData = ed->constructorPixelArray->NewInstance();
- pixelData->SetExternalResource(r);
-
- imageData->SetInternalField(0, pixelData);
- return imageData;
-}
-
-//static script functions
-
-/*!
- \qmlproperty QtQuick2::Canvas QtQuick2::Context2D::canvas
- Holds the canvas item that the context paints on.
-
- This property is read only.
-*/
-static v8::Handle<v8::Value> ctx2d_canvas(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- return engine->newQObject(r->context->canvas());
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::restore()
- Pops the top state on the stack, restoring the context to that state.
-
- \sa QtQuick2::Context2D::save()
-*/
-static v8::Handle<v8::Value> ctx2d_restore(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- r->context->popState();
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::reset()
- Resets the context state and properties to the default values.
-*/
-static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- r->context->reset();
- r->context->m_path = QPainterPath();
- r->context->m_path.setFillRule(Qt::WindingFill);
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::save()
- Pushes the current state onto the state stack.
-
- Before changing any state attributes, you should save the current state
- for future reference. The context maintains a stack of drawing states.
- Each state consists of the current transformation matrix, clipping region,
- and values of the following attributes:
- \list
- \o\a QtQuick2::Context2D::strokeStyle
- \o\a QtQuick2::Context2D::fillStyle
- \o\a QtQuick2::Context2D::fillRule
- \o\a QtQuick2::Context2D::globalAlpha
- \o\a QtQuick2::Context2D::lineWidth
- \o\a QtQuick2::Context2D::lineCap
- \o\a QtQuick2::Context2D::lineJoin
- \o\a QtQuick2::Context2D::miterLimit
- \o\a QtQuick2::Context2D::shadowOffsetX
- \o\a QtQuick2::Context2D::shadowOffsetY
- \o\a QtQuick2::Context2D::shadowBlur
- \o\a QtQuick2::Context2D::shadowColor
- \o\a QtQuick2::Context2D::globalCompositeOperation
- \o\a QtQuick2::Context2D::font
- \o\a QtQuick2::Context2D::textAlign
- \o\a QtQuick2::Context2D::textBaseline
- \endlist
-
- The current path is NOT part of the drawing state. The path can be reset by
- invoking the \a QtQuick2::Context2D::beginPath() method.
-*/
-static v8::Handle<v8::Value> ctx2d_save(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- r->context->pushState();
-
- return args.This();
-}
-
-// transformations
-/*!
- \qmlmethod object QtQuick2::Context2D::rotate(real angle)
- Rotate the canvas around the current origin by \c angle in radians and clockwise direction.
- \code
- ctx.rotate(Math.PI/2);
- \endcode
- \image qml-item-canvas-rotate.png
-
- The rotation transformation matrix is as follows:
-
- \image qml-item-canvas-math-rotate.png
-
- where the \c angle of rotation is in radians.
-
-*/
-static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 1) {
- qreal angle = args[0]->NumberValue();
- if (!qIsFinite(angle))
- return args.This();
-
- r->context->state.matrix.rotate(DEGREES(angle));
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::scale(real x, real y)
- Increases or decreases the size of each unit in the canvas grid by multiplying the scale factors
- to the current tranform matrix.
- Where \c x is the scale factor in the horizontal direction and \c y is the scale factor in the
- vertical direction.
- The following code doubles the horizontal size of an object drawn on the canvas and half its
- vertical size:
- \code
- ctx.scale(2.0, 0.5);
- \endcode
- \image qml-item-canvas-scale.png
-
-*/
-static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 2) {
- qreal x, y;
- x = args[0]->NumberValue();
- y = args[1]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->state.matrix.scale(x, y);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::setTransform(real a, real b, real c, real d, real e, real f)
- Changes the transformation matrix to the matrix given by the arguments as described below.
-
- Modifying the transformation matrix directly enables you to perform scaling,
- rotating, and translating transformations in a single step.
-
- Each point on the canvas is multiplied by the matrix before anything is
- drawn. The \l{HTML5 Canvas API} defines the transformation matrix as:
-
- \image qml-item-canvas-math.png
- where:
- \list
- \o \c{a} is the scale factor in the horizontal (x) direction
- \image qml-item-canvas-scalex.png
- \o \c{c} is the skew factor in the x direction
- \image qml-item-canvas-canvas-skewx.png
- \o \c{e} is the translation in the x direction
- \image qml-item-canvas-canvas-translate.png
- \o \c{b} is the skew factor in the y (vertical) direction
- \image qml-item-canvas-canvas-skewy.png
- \o \c{d} is the scale factor in the y direction
- \image qml-item-canvas-canvas-scaley.png
- \o \c{f} is the translation in the y direction
- \image qml-item-canvas-canvas-translatey.png
- \o the last row remains constant
- \endlist
- The scale factors and skew factors are multiples; \c{e} and \c{f} are
- coordinate space units, just like the units in the \a QtQuick2::Context2D::translate(x,y)
- method.
-
- \sa QtQuick2::Context2D::transform()
-*/
-static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 6) {
- qreal a = args[0]->NumberValue();
- qreal b = args[1]->NumberValue();
- qreal c = args[2]->NumberValue();
- qreal d = args[3]->NumberValue();
- qreal e = args[4]->NumberValue();
- qreal f = args[5]->NumberValue();
-
- if (!qIsFinite(a)
- || !qIsFinite(b)
- || !qIsFinite(c)
- || !qIsFinite(d)
- || !qIsFinite(e)
- || !qIsFinite(f))
- return args.This();
-
- r->context->state.matrix = QTransform(a, b, c, d, e, f);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::transform(real a, real b, real c, real d, real e, real f)
- This method is very similar to \a QtQuick2::Context2D::setTransform(), but instead of replacing the old
- tranform matrix, this method applies the given tranform matrix to the current matrix by mulitplying to it.
-
- The \a setTransform(a, b, c, d, e, f) method actually resets the current transform to the identity matrix,
- and then invokes the transform(a, b, c, d, e, f) method with the same arguments.
-
- \sa QtQuick2::Context2D::setTransform()
-*/
-static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 6) {
- qreal a = args[0]->NumberValue();
- qreal b = args[1]->NumberValue();
- qreal c = args[2]->NumberValue();
- qreal d = args[3]->NumberValue();
- qreal e = args[4]->NumberValue();
- qreal f = args[5]->NumberValue();
-
- if (!qIsFinite(a)
- || !qIsFinite(b)
- || !qIsFinite(c)
- || !qIsFinite(d)
- || !qIsFinite(e)
- || !qIsFinite(f))
- return args.This();
-
- r->context->state.matrix *= QTransform(a, b, c, d, e, f);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::translate(real x, real y)
- Translates the origin of the canvas to point (\c x, \c y).
-
- \c x is the horizontal distance that the origin is translated, in coordinate space units,
- \c y is the vertical distance that the origin is translated, in coordinate space units.
- Translating the origin enables you to draw patterns of different objects on the canvas
- without having to measure the coordinates manually for each shape.
-*/
-static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->state.matrix.translate(x, y);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
- return args.This();
-}
-
-
-/*!
- \qmlmethod object QtQuick2::Context2D::resetTransform()
- Reset the transformation matrix to default value.
-
- \sa QtQuick2::Context2D::transform(), QtQuick2::Context2D::setTransform(), QtQuick2::Context2D::reset()
-*/
-static v8::Handle<v8::Value> ctx2d_resetTransform(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- r->context->state.matrix = QTransform();
- r->context->buffer()->updateMatrix(r->context->state.matrix);
-
- return args.This();
-}
-
-
-/*!
- \qmlmethod object QtQuick2::Context2D::shear(real sh, real sv )
- Shear the transformation matrix with \a sh in horizontal direction and \a sv in vertical direction.
-*/
-static v8::Handle<v8::Value> ctx2d_shear(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 2) {
- qreal sh = args[0]->NumberValue();
- qreal sv = args[1]->NumberValue();
-
- if (!qIsFinite(sh) || !qIsFinite(sv))
- return args.This();
-
- r->context->state.matrix.shear(sh, sv);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
- return args.This();
-}
-// compositing
-
-/*!
- \qmlproperty real QtQuick2::Context2D::globalAlpha
- Holds the the current alpha value applied to rendering operations.
- The value must be in the range from 0.0 (fully transparent) to 1.0 (fully opque).
- The default value is 1.0.
-*/
-static v8::Handle<v8::Value> ctx2d_globalAlpha(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
- return v8::Number::New(r->context->state.globalAlpha);
-}
-
-static void ctx2d_globalAlpha_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- qreal globalAlpha = value->NumberValue();
-
- if (!qIsFinite(globalAlpha))
- return;
-
- if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->context->state.globalAlpha != globalAlpha) {
- r->context->state.globalAlpha = globalAlpha;
- r->context->buffer()->setGlobalAlpha(r->context->state.globalAlpha);
- }
-}
-
-/*!
- \qmlproperty string QtQuick2::Context2D::globalCompositeOperation
- Holds the the current the current composition operation, from the list below:
- \list
- \o source-atop - A atop B. Display the source image wherever both images are opaque.
- Display the destination image wherever the destination image is opaque but the source image is transparent.
- Display transparency elsewhere.
- \o source-in - A in B. Display the source image wherever both the source image and destination image are opaque.
- Display transparency elsewhere.
- \o source-out - A out B. Display the source image wherever the source image is opaque and the destination image is transparent.
- Display transparency elsewhere.
- \o source-over - (default) A over B. Display the source image wherever the source image is opaque.
- Display the destination image elsewhere.
- \o destination-atop - B atop A. Same as source-atop but using the destination image instead of the source image and vice versa.
- \o destination-in - B in A. Same as source-in but using the destination image instead of the source image and vice versa.
- \o destination-out - B out A. Same as source-out but using the destination image instead of the source image and vice versa.
- \o destination-over - B over A. Same as source-over but using the destination image instead of the source image and vice versa.
- \o lighter - A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit.
- \o copy - A (B is ignored). Display the source image instead of the destination image.
- \o xor - A xor B. Exclusive OR of the source image and destination image.
- \endlist
-
- Additionally, this property also accepts the compositon modes listed in \a {QPainter::CompositionMode}. According to the W3C standard, these
- extension composition modes are provided as "vendorName-operationName" syntax, for example: \c {QPainter::CompositionMode_Exclusion} is porvided as
- "qt-exclusion".
-*/
-static v8::Handle<v8::Value> ctx2d_globalCompositeOperation(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- return engine->toString(qt_composite_mode_to_string(r->context->state.globalCompositeOperation));
-}
-
-static void ctx2d_globalCompositeOperation_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
-
- QString mode = engine->toString(value);
- QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
- if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over"))
- return;
-
- if (cm != r->context->state.globalCompositeOperation) {
- r->context->state.globalCompositeOperation = cm;
- r->context->buffer()->setGlobalCompositeOperation(cm);
- }
-}
-
-// colors and styles
-/*!
- \qmlproperty variant QtQuick2::Context2D::fillStyle
- Holds the current style used for filling shapes.
- The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object. Invalid values are ignored.
- This property accepts several color syntaxes:
- \list
- \o 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)'
- \o 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)'
- \o 'hsl(hue, saturation, lightness)'
- \o 'hsla(hue, saturation, lightness, alpha)'
- \o '#RRGGBB' - for example: '#00FFCC'
- \o Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0)
- \endlist
- If the \a fillStyle or \a strokeStyle is assigned many times in a loop, the last Qt.rgba() syntax should be chosen, as it has the
- best performance, because it's already a valid QColor value, does not need to be parsed everytime.
-
- The default value is '#000000'.
- \sa QtQuick2::Context2D::createLinearGradient
- \sa QtQuick2::Context2D::createRadialGradient
- \sa QtQuick2::Context2D::createPattern
- \sa QtQuick2::Context2D::strokeStyle
- */
-static v8::Handle<v8::Value> ctx2d_fillStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- QColor color = r->context->state.fillStyle.color();
- if (color.isValid()) {
- if (color.alpha() == 255)
- return engine->toString(color.name());
- QString alphaString = QString::number(color.alphaF(), 'f');
- while (alphaString.endsWith(QLatin1Char('0')))
- alphaString.chop(1);
- if (alphaString.endsWith(QLatin1Char('.')))
- alphaString += QLatin1Char('0');
- return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
- }
- return r->context->m_fillStyle;
-}
-
-static void ctx2d_fillStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- if (value->IsObject()) {
- QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
- if (color.isValid()) {
- r->context->state.fillStyle = color;
- r->context->buffer()->setFillStyle(color);
- r->context->m_fillStyle = value;
- } else {
- QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
- if (style && style->brush != r->context->state.fillStyle) {
- r->context->state.fillStyle = style->brush;
- r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
- r->context->m_fillStyle = value;
- r->context->state.fillPatternRepeatX = style->patternRepeatX;
- r->context->state.fillPatternRepeatY = style->patternRepeatY;
- }
- }
- } else if (value->IsString()) {
- QColor color = qt_color_from_string(value);
- if (color.isValid() && r->context->state.fillStyle != QBrush(color)) {
- r->context->state.fillStyle = QBrush(color);
- r->context->buffer()->setFillStyle(r->context->state.fillStyle);
- r->context->m_fillStyle = value;
- }
- }
-}
-/*!
- \qmlproperty enumeration QtQuick2::Context2D::fillRule
- Holds the current fill rule used for filling shapes. The following fill rules supported:
- \list
- \o Qt.OddEvenFill
- \o Qt.WindingFill
- \endlist
- Note: Unlike the \a QPainterPath, the Canvas API uses the winding fill as the default fill rule.
- The fillRule property is part of the context rendering state.
-
- \sa QtQuick2::Context2D::fillStyle
- */
-static v8::Handle<v8::Value> ctx2d_fillRule(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- return engine->fromVariant(r->context->state.fillRule);
-}
-
-static void ctx2d_fillRule_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- if ((value->IsString() && engine->toString(value) == QStringLiteral("WindingFill"))
- ||(value->IsNumber() && value->NumberValue() == Qt::WindingFill)) {
- r->context->state.fillRule = Qt::WindingFill;
- } else if ((value->IsString() && engine->toString(value) == QStringLiteral("OddEvenFill"))
- ||(value->IsNumber() && value->NumberValue() == Qt::OddEvenFill)) {
- r->context->state.fillRule = Qt::OddEvenFill;
- } else {
- //error
- }
- r->context->m_path.setFillRule(r->context->state.fillRule);
-}
-/*!
- \qmlproperty variant QtQuick2::Context2D::strokeStyle
- Holds the current color or style to use for the lines around shapes,
- The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object.
- Invalid values are ignored.
-
- The default value is '#000000'.
-
- \sa QtQuick2::Context2D::createLinearGradient
- \sa QtQuick2::Context2D::createRadialGradient
- \sa QtQuick2::Context2D::createPattern
- \sa QtQuick2::Context2D::fillStyle
- */
-v8::Handle<v8::Value> ctx2d_strokeStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- QColor color = r->context->state.strokeStyle.color();
- if (color.isValid()) {
- if (color.alpha() == 255)
- return engine->toString(color.name());
- QString alphaString = QString::number(color.alphaF(), 'f');
- while (alphaString.endsWith(QLatin1Char('0')))
- alphaString.chop(1);
- if (alphaString.endsWith(QLatin1Char('.')))
- alphaString += QLatin1Char('0');
- return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
- }
- return r->context->m_strokeStyle;
-}
-
-static void ctx2d_strokeStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- if (value->IsObject()) {
- QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
- if (color.isValid()) {
- r->context->state.fillStyle = color;
- r->context->buffer()->setStrokeStyle(color);
- r->context->m_strokeStyle = value;
- } else {
- QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
- if (style && style->brush != r->context->state.strokeStyle) {
- r->context->state.strokeStyle = style->brush;
- r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
- r->context->m_strokeStyle = value;
- r->context->state.strokePatternRepeatX = style->patternRepeatX;
- r->context->state.strokePatternRepeatY = style->patternRepeatY;
-
- }
- }
- } else if (value->IsString()) {
- QColor color = qt_color_from_string(value);
- if (color.isValid() && r->context->state.strokeStyle != QBrush(color)) {
- r->context->state.strokeStyle = QBrush(color);
- r->context->buffer()->setStrokeStyle(r->context->state.strokeStyle);
- r->context->m_strokeStyle = value;
- }
- }
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::createLinearGradient(real x0, real y0, real x1, real y1)
- Returns a CanvasGradient object that represents a linear gradient that transitions the color along a line between
- the start point (\a x0, \a y0) and the end point (\a x1, \a y1).
-
- A gradient is a smooth transition between colors. There are two types of gradients: linear and radial.
- Gradients must have two or more color stops, representing color shifts positioned from 0 to 1 between
- to the gradient's starting and end points or circles.
-
- \sa QtQuick2::Context2D::CanvasGradient::addColorStop
- \sa QtQuick2::Context2D::createRadialGradient
- \sa QtQuick2::Context2D::ctx2d_createConicalGradient
- \sa QtQuick2::Context2D::createPattern
- \sa QtQuick2::Context2D::fillStyle
- \sa QtQuick2::Context2D::strokeStyle
- */
-
-static v8::Handle<v8::Value> ctx2d_createLinearGradient(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 4) {
- QQuickContext2DEngineData *ed = engineData(engine);
- v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
- QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
- qreal x0 = args[0]->NumberValue();
- qreal y0 = args[1]->NumberValue();
- qreal x1 = args[2]->NumberValue();
- qreal y1 = args[3]->NumberValue();
-
- if (!qIsFinite(x0)
- || !qIsFinite(y0)
- || !qIsFinite(x1)
- || !qIsFinite(y1))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
-
- r->brush = QLinearGradient(x0, y0, x1, y1);
- gradient->SetExternalResource(r);
- return gradient;
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::createRadialGradient(real x0, real y0, real r0, real x1, real y1, real r1)
- Returns a CanvasGradient object that represents a radial gradient that paints along the cone given by the start circle with
- origin (x0, y0) and radius r0, and the end circle with origin (x1, y1) and radius r1.
-
- \sa QtQuick2::Context2D::CanvasGradient::addColorStop
- \sa QtQuick2::Context2D::createLinearGradient
- \sa QtQuick2::Context2D::ctx2d_createConicalGradient
- \sa QtQuick2::Context2D::createPattern
- \sa QtQuick2::Context2D::fillStyle
- \sa QtQuick2::Context2D::strokeStyle
- */
-
-static v8::Handle<v8::Value> ctx2d_createRadialGradient(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 6) {
- QQuickContext2DEngineData *ed = engineData(engine);
- v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
- QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
-
- qreal x0 = args[0]->NumberValue();
- qreal y0 = args[1]->NumberValue();
- qreal r0 = args[2]->NumberValue();
- qreal x1 = args[3]->NumberValue();
- qreal y1 = args[4]->NumberValue();
- qreal r1 = args[5]->NumberValue();
-
- if (!qIsFinite(x0)
- || !qIsFinite(y0)
- || !qIsFinite(x1)
- || !qIsFinite(r0)
- || !qIsFinite(r1)
- || !qIsFinite(y1))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
-
- if (r0 < 0 || r1 < 0)
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
-
-
- r->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
- gradient->SetExternalResource(r);
- return gradient;
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::createConicalGradient(real x, real y, real angle)
- Returns a CanvasGradient object that represents a conical gradient that interpolate colors counter-clockwise around a center point (\c x, \c y)
- with start angle \c angle in units of radians.
-
- \sa QtQuick2::Context2D::CanvasGradient::addColorStop
- \sa QtQuick2::Context2D::createLinearGradient
- \sa QtQuick2::Context2D::ctx2d_createRadialGradient
- \sa QtQuick2::Context2D::createPattern
- \sa QtQuick2::Context2D::fillStyle
- \sa QtQuick2::Context2D::strokeStyle
- */
-
-static v8::Handle<v8::Value> ctx2d_createConicalGradient(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 6) {
- QQuickContext2DEngineData *ed = engineData(engine);
- v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
- QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
-
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal angle = DEGREES(args[2]->NumberValue());
- if (!qIsFinite(x) || !qIsFinite(y))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
-
- if (!qIsFinite(angle))
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
-
- r->brush = QConicalGradient(x, y, angle);
- gradient->SetExternalResource(r);
- return gradient;
- }
-
- return args.This();
-}
-/*!
- \qmlmethod variant createPattern(Color color, enumeration patternMode)
- This is a overload function.
- Returns a CanvasPattern object that uses the given \c color and \c patternMode.
- The valid pattern modes are:
- \list
- \o Qt.SolidPattern
- \o Qt.Dense1Pattern
- \o Qt.Dense2Pattern
- \o Qt.Dense3Pattern
- \o Qt.Dense4Pattern
- \o Qt.Dense5Pattern
- \o Qt.Dense6Pattern
- \o Qt.Dense7Pattern
- \o Qt.HorPattern
- \o Qt.VerPattern
- \o Qt.CrossPattern
- \o Qt.BDiagPattern
- \o Qt.FDiagPattern
- \o Qt.DiagCrossPattern
-\endlist
- \sa Qt::BrushStyle
- */
-/*!
- \qmlmethod variant createPattern(Image image, string repetition)
- Returns a CanvasPattern object that uses the given image and repeats in the direction(s) given by the repetition argument.
-
- The \a image parameter must be a valid Image item, a valid \a QtQuick2::CanvasImageData object or loaded image url, if there is no image data, throws an INVALID_STATE_ERR exception.
-
- The allowed values for \a repetition are:
-
- \list
- \o "repeat" - both directions
- \o "repeat-x - horizontal only
- \o "repeat-y" - vertical only
- \o "no-repeat" - neither
- \endlist
-
- If the repetition argument is empty or null, the value "repeat" is used.
-
- \sa QtQuick2::Context2D::strokeStyle
- \sa QtQuick2::Context2D::fillStyle
- */
-static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 2) {
- QQuickContext2DEngineData *ed = engineData(engine);
- QV8Context2DStyleResource *styleResouce = new QV8Context2DStyleResource(engine);
-
- QColor color = engine->toVariant(args[0], qMetaTypeId<QColor>()).value<QColor>();
- if (color.isValid()) {
- int patternMode = args[1]->IntegerValue();
- Qt::BrushStyle style = Qt::SolidPattern;
- if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) {
- style = static_cast<Qt::BrushStyle>(patternMode);
- }
- styleResouce->brush = QBrush(color, style);
- } else {
- QImage patternTexture;
-
- if (args[0]->IsObject()) {
- QV8Context2DPixelArrayResource *pixelData = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->Get(v8::String::New("data"))->ToObject());
- if (pixelData) {
- patternTexture = pixelData->image;
- }
- } else {
- patternTexture = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
- }
-
- if (!patternTexture.isNull()) {
- styleResouce->brush.setTextureImage(patternTexture);
-
- QString repetition = engine->toString(args[1]);
- if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) {
- styleResouce->patternRepeatX = true;
- styleResouce->patternRepeatY = true;
- } else if (repetition == QStringLiteral("repeat-x")) {
- styleResouce->patternRepeatX = true;
- } else if (repetition == QStringLiteral("repeat-y")) {
- styleResouce->patternRepeatY = true;
- } else if (repetition == QStringLiteral("no-repeat")) {
- styleResouce->patternRepeatY = false;
- styleResouce->patternRepeatY = false;
- } else {
- //TODO: exception: SYNTAX_ERR
- }
-
- }
- }
-
- v8::Local<v8::Object> pattern = ed->constructorPattern->NewInstance();
- pattern->SetExternalResource(styleResouce);
- return pattern;
-
- }
- return v8::Undefined();
-}
-
-// line styles
-/*!
- \qmlproperty string QtQuick2::Context2D::lineCap
- Holds the the current line cap style.
- The possible line cap styles are:
- \list
- \o butt - the end of each line has a flat edge perpendicular to the direction of the line, this is the default line cap value.
- \o round - a semi-circle with the diameter equal to the width of the line must then be added on to the end of the line.
- \o square - a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line.
- \endlist
- Other values are ignored.
-*/
-v8::Handle<v8::Value> ctx2d_lineCap(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- switch (r->context->state.lineCap) {
- case Qt::RoundCap:
- return engine->toString(QLatin1String("round"));
- case Qt::FlatCap:
- return engine->toString(QLatin1String("butt"));
- case Qt::SquareCap:
- return engine->toString(QLatin1String("square"));
- default:
- break;
- }
- return engine->toString(QLatin1String("butt"));;
-}
-
-static void ctx2d_lineCap_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- QString lineCap = engine->toString(value);
- Qt::PenCapStyle cap;
- if (lineCap == QLatin1String("round"))
- cap = Qt::RoundCap;
- else if (lineCap == QLatin1String("butt"))
- cap = Qt::FlatCap;
- else if (lineCap == QLatin1String("square"))
- cap = Qt::SquareCap;
- else
- return;
-
- if (cap != r->context->state.lineCap) {
- r->context->state.lineCap = cap;
- r->context->buffer()->setLineCap(cap);
- }
-}
-
-/*!
- \qmlproperty string QtQuick2::Context2D::lineJoin
- Holds the the current line join style. A join exists at any point in a subpath
- shared by two consecutive lines. When a subpath is closed, then a join also exists
- at its first point (equivalent to its last point) connecting the first and last lines in the subpath.
-
- The possible line join styles are:
- \list
- \o bevel - this is all that is rendered at joins.
- \o round - a filled arc connecting the two aforementioned corners of the join, abutting (and not overlapping) the aforementioned triangle, with the diameter equal to the line width and the origin at the point of the join, must be rendered at joins.
- \o miter - a second filled triangle must (if it can given the miter length) be rendered at the join, this is the default line join style.
- \endlist
- Other values are ignored.
-*/
-v8::Handle<v8::Value> ctx2d_lineJoin(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- switch (r->context->state.lineJoin) {
- case Qt::RoundJoin:
- return engine->toString(QLatin1String("round"));
- case Qt::BevelJoin:
- return engine->toString(QLatin1String("bevel"));
- case Qt::MiterJoin:
- return engine->toString(QLatin1String("miter"));
- default:
- break;
- }
- return engine->toString(QLatin1String("miter"));
-}
-
-static void ctx2d_lineJoin_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- QString lineJoin = engine->toString(value);
- Qt::PenJoinStyle join;
- if (lineJoin == QLatin1String("round"))
- join = Qt::RoundJoin;
- else if (lineJoin == QLatin1String("bevel"))
- join = Qt::BevelJoin;
- else if (lineJoin == QLatin1String("miter"))
- join = Qt::MiterJoin;
- else
- return;
-
- if (join != r->context->state.lineJoin) {
- r->context->state.lineJoin = join;
- r->context->buffer()->setLineJoin(join);
- }
-}
-
-/*!
- \qmlproperty real QtQuick2::Context2D::lineWidth
- Holds the the current line width. Values that are not finite values greater than zero are ignored.
- */
-v8::Handle<v8::Value> ctx2d_lineWidth(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- return v8::Number::New(r->context->state.lineWidth);
-}
-
-static void ctx2d_lineWidth_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- qreal w = value->NumberValue();
-
- if (w > 0 && qIsFinite(w) && w != r->context->state.lineWidth) {
- r->context->state.lineWidth = w;
- r->context->buffer()->setLineWidth(w);
- }
-}
-
-/*!
- \qmlproperty real QtQuick2::Context2D::miterLimit
- Holds the current miter limit ratio.
- The default miter limit value is 10.0.
- */
-v8::Handle<v8::Value> ctx2d_miterLimit(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- return v8::Number::New(r->context->state.miterLimit);
-}
-
-static void ctx2d_miterLimit_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- qreal ml = value->NumberValue();
-
- if (ml > 0 && qIsFinite(ml) && ml != r->context->state.miterLimit) {
- r->context->state.miterLimit = ml;
- r->context->buffer()->setMiterLimit(ml);
- }
-}
-
-// shadows
-/*!
- \qmlproperty real QtQuick2::Context2D::shadowBlur
- Holds the current level of blur applied to shadows
- */
-v8::Handle<v8::Value> ctx2d_shadowBlur(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- return v8::Number::New(r->context->state.shadowBlur);
-}
-
-static void ctx2d_shadowBlur_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
- qreal blur = value->NumberValue();
-
- if (blur > 0 && qIsFinite(blur) && blur != r->context->state.shadowBlur) {
- r->context->state.shadowBlur = blur;
- r->context->buffer()->setShadowBlur(blur);
- }
-}
-
-/*!
- \qmlproperty string QtQuick2::Context2D::shadowColor
- Holds the current shadow color.
- */
-v8::Handle<v8::Value> ctx2d_shadowColor(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- return engine->toString(r->context->state.shadowColor.name());
-}
-
-static void ctx2d_shadowColor_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QColor color = qt_color_from_string(value);
-
- if (color.isValid() && color != r->context->state.shadowColor) {
- r->context->state.shadowColor = color;
- r->context->buffer()->setShadowColor(color);
- }
-}
-
-
-/*!
- \qmlproperty qreal QtQuick2::Context2D::shadowOffsetX
- Holds the current shadow offset in the positive horizontal distance.
-
- \sa QtQuick2::Context2D::shadowOffsetY
- */
-v8::Handle<v8::Value> ctx2d_shadowOffsetX(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- return v8::Number::New(r->context->state.shadowOffsetX);
-}
-
-static void ctx2d_shadowOffsetX_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- qreal offsetX = value->NumberValue();
- if (qIsFinite(offsetX) && offsetX != r->context->state.shadowOffsetX) {
- r->context->state.shadowOffsetX = offsetX;
- r->context->buffer()->setShadowOffsetX(offsetX);
- }
-}
-/*!
- \qmlproperty qreal QtQuick2::Context2D::shadowOffsetY
- Holds the current shadow offset in the positive vertical distance.
-
- \sa QtQuick2::Context2D::shadowOffsetX
- */
-v8::Handle<v8::Value> ctx2d_shadowOffsetY(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
-
- return v8::Number::New(r->context->state.shadowOffsetY);
-}
-
-static void ctx2d_shadowOffsetY_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- qreal offsetY = value->NumberValue();
- if (qIsFinite(offsetY) && offsetY != r->context->state.shadowOffsetY) {
- r->context->state.shadowOffsetY = offsetY;
- r->context->buffer()->setShadowOffsetY(offsetY);
- }
-}
-
-v8::Handle<v8::Value> ctx2d_path(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
- return r->context->m_v8path;
-}
-
-static void ctx2d_path_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- r->context->beginPath();
- if (value->IsObject()) {
- QDeclarativePath* path = qobject_cast<QDeclarativePath*>(engine->toQObject(value));
- if (path)
- r->context->m_path = path->path();
- } else {
- QString path = engine->toString(value->ToString());
- QDeclarativeSvgParser::parsePathDataFast(path, r->context->m_path);
- }
- r->context->m_v8path = value;
-}
-
-//rects
-/*!
- \qmlmethod object QtQuick2::Context2D::clearRect(real x, real y, real w, real h)
- Clears all pixels on the canvas in the given rectangle to transparent black.
- */
-static v8::Handle<v8::Value> ctx2d_clearRect(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->clearRect(x, y, w, h);
- }
-
- return args.This();
-}
-/*!
- \qmlmethod object QtQuick2::Context2D::fillRect(real x, real y, real w, real h)
- Paint the specified rectangular area using the fillStyle.
-
- \sa QtQuick2::Context2D::fillStyle
- */
-static v8::Handle<v8::Value> ctx2d_fillRect(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->fillRect(x, y, w, h);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::fillRect(real x, real y, real w, real h)
- Stroke the specified rectangle's path using the strokeStyle, lineWidth, lineJoin,
- and (if appropriate) miterLimit attributes.
-
- \sa QtQuick2::Context2D::strokeStyle
- \sa QtQuick2::Context2D::lineWidth
- \sa QtQuick2::Context2D::lineJoin
- \sa QtQuick2::Context2D::miterLimit
- */
-static v8::Handle<v8::Value> ctx2d_strokeRect(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->strokeRect(x, y, w, h);
- }
-
- return args.This();
-}
-
-// Complex shapes (paths) API
-/*!
- \qmlmethod object QtQuick2::Context2D::arc(real x, real y, real radius, real startAngle, real endAngle, bool anticlockwise)
- Adds an arc to the current subpath that lies on the circumference of the circle whose center is at the point (\c x,\cy) and whose radius is \c radius.
- \image qml-item-canvas-arcTo2.png
- \sa QtQuick2::Context2D::arcTo
- See {http://www.w3.org/TR/2dcontext/#dom-context-2d-arc}{W3C 2d context standard for arc}
- */
-static v8::Handle<v8::Value> ctx2d_arc(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() >= 5) {
- bool antiClockwise = false;
-
- if (args.Length() == 6)
- antiClockwise = args[5]->BooleanValue();
-
- qreal radius = args[2]->NumberValue();
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal sa = args[3]->NumberValue();
- qreal ea = args[4]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(sa) || !qIsFinite(ea))
- return args.This();
-
- if (radius < 0)
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
-
- r->context->arc(args[0]->NumberValue(),
- args[1]->NumberValue(),
- radius,
- args[3]->NumberValue(),
- args[4]->NumberValue(),
- antiClockwise);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::arcTo(real x1, real y1, real x2, real y2, real radius)
-
- Adds an arc with the given control points and radius to the current subpath, connected to the previous point by a straight line.
- To draw an arc, you begin with the same steps your followed to create a line:
- \list
- \o Call the context.beginPath() method to set a new path.
- \o Call the context.moveTo(\c x, \c y) method to set your starting position on the canvas at the point (\c x,\c y).
- \o To draw an arc or circle, call the context.arcTo(\c x1, \c y1, \c x2, \c y2,\c radius) method.
- This adds an arc with starting point (\c x1,\c y1), ending point (\c x2, \c y2), and radius \c radius to the current subpath and connects
- it to the previous subpath by a straight line.
- \endlist
- \image qml-item-canvas-arcTo.png
- Both startAngle and endAngle are measured from the x axis in units of radians.
-
- \image qml-item-canvas-startAngle.png
- The anticlockwise has the value TRUE for each arc in the figure above because they are all drawn in the counterclockwise direction.
- \sa QtQuick2::Context2D::arc
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto}{W3C 2d context standard for arcTo}
- */
-static v8::Handle<v8::Value> ctx2d_arcTo(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
-
- if (args.Length() == 5) {
- qreal x1 = args[0]->NumberValue();
- qreal y1 = args[1]->NumberValue();
- qreal x2 = args[2]->NumberValue();
- qreal y2 = args[3]->NumberValue();
-
- if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2))
- return args.This();
-
- qreal radius = args[4]->NumberValue();
- if (radius < 0)
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
- r->context->arcTo(args[0]->NumberValue(),
- args[1]->NumberValue(),
- args[2]->NumberValue(),
- args[3]->NumberValue(),
- args[4]->NumberValue());
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::beginPath()
-
- Resets the current path to a new path.
- */
-static v8::Handle<v8::Value> ctx2d_beginPath(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- r->context->beginPath();
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::bezierCurveTo(real cp1x, real cp1y, real cp2x, real cp2y, real x, real y)
-
- Adds a cubic Bezier curve between the current position and the given endPoint using the control points specified by (\c cp1x, cp1y),
- and (\c cp2x, \c cp2y).
- After the curve is added, the current position is updated to be at the end point (\c x, \c y) of the curve.
- The following code produces the path shown below:
- \code
- ctx.strokeStyle = Qt.rgba(0, 0, 0, 1);
- ctx.lineWidth = 1;
- ctx.beginPath();
- ctx.moveTo(20, 0);//start point
- ctx.bezierCurveTo(-10, 90, 210, 90, 180, 0);
- ctx.stroke();
- \endcode
- \image qml-item-canvas-bezierCurveTo.png
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto}{W3C 2d context standard for bezierCurveTo}
- \sa {http://www.openrise.com/lab/FlowerPower/}{The beautiful flower demo by using bezierCurveTo}
- */
-static v8::Handle<v8::Value> ctx2d_bezierCurveTo(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 6) {
- qreal cp1x = args[0]->NumberValue();
- qreal cp1y = args[1]->NumberValue();
- qreal cp2x = args[2]->NumberValue();
- qreal cp2y = args[3]->NumberValue();
- qreal x = args[4]->NumberValue();
- qreal y = args[5]->NumberValue();
-
- if (!qIsFinite(cp1x) || !qIsFinite(cp1y) || !qIsFinite(cp2x) || !qIsFinite(cp2y) || !qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::clip()
-
- Creates the clipping region from the current path.
- Any parts of the shape outside the clipping path are not displayed.
- To create a complex shape using the \a clip() method:
-
- \list 1
- \o Call the \c{context.beginPath()} method to set the clipping path.
- \o Define the clipping path by calling any combination of the \c{lineTo},
- \c{arcTo}, \c{arc}, \c{moveTo}, etc and \c{closePath} methods.
- \o Call the \c{context.clip()} method.
- \endlist
-
- The new shape displays. The following shows how a clipping path can
- modify how an image displays:
-
- \image qml-canvas-clip-complex.png
- \sa QtQuick2::Context2D::beginPath()
- \sa QtQuick2::Context2D::closePath()
- \sa QtQuick2::Context2D::stroke()
- \sa QtQuick2::Context2D::fill()
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-clip}{W3C 2d context standard for clip}
- */
-static v8::Handle<v8::Value> ctx2d_clip(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QPainterPath clipPath = r->context->m_path;
- clipPath.closeSubpath();
- if (!r->context->state.clipPath.isEmpty())
- r->context->state.clipPath = clipPath.intersected(r->context->state.clipPath);
- else
- r->context->state.clipPath = clipPath;
- r->context->buffer()->clip(r->context->state.clipPath);
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::closePath()
- Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting a new path.
- The current point of the new path is the previous subpath's first point.
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-closepath}{W3C 2d context standard for closePath}
- */
-static v8::Handle<v8::Value> ctx2d_closePath(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- r->context->closePath();
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::fill()
-
- Fills the subpaths with the current fill style.
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-fill}{W3C 2d context standard for fill}
-
- \sa QtQuick2::Context2D::fillStyle
- */
-static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r);
-
- r->context->buffer()->fill(r->context->m_path);
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::lineTo(real x, real y)
-
- Draws a line from the current position to the point (x, y).
- */
-static v8::Handle<v8::Value> ctx2d_lineTo(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->lineTo(x, y);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::moveTo(real x, real y)
-
- Creates a new subpath with the given point.
- */
-static v8::Handle<v8::Value> ctx2d_moveTo(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
- r->context->moveTo(x, y);
- }
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::quadraticCurveTo(real cpx, real cpy, real x, real y)
-
- Adds a quadratic Bezier curve between the current point and the endpoint (\c x, \c y) with the control point specified by (\c cpx, \c cpy).
-
- See {http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for for quadraticCurveTo}
- */
-static v8::Handle<v8::Value> ctx2d_quadraticCurveTo(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 4) {
- qreal cpx = args[0]->NumberValue();
- qreal cpy = args[1]->NumberValue();
- qreal x = args[2]->NumberValue();
- qreal y = args[3]->NumberValue();
-
- if (!qIsFinite(cpx) || !qIsFinite(cpy) || !qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->quadraticCurveTo(cpx, cpy, x, y);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::rect(real x, real y, real w, real h)
-
- Adds a rectangle at position (\c x, \c y), with the given width \c w and height \c h, as a closed subpath.
- */
-static v8::Handle<v8::Value> ctx2d_rect(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->rect(x, y, w, h);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::roundedRect(real x, real y, real w, real h, real xRadius, real yRadius)
-
- Adds the given rectangle rect with rounded corners to the path. The \c xRadius and \c yRadius arguments specify the radius of the
- ellipses defining the corners of the rounded rectangle.
- */
-static v8::Handle<v8::Value> ctx2d_roundedRect(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- if (args.Length() == 6) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
- qreal xr = args[4]->NumberValue();
- qreal yr = args[5]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- if (!qIsFinite(xr) || !qIsFinite(yr))
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "roundedRect(): Invalid arguments");
-
- r->context->roundedRect(x, y, w, h, xr, yr);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::ellipse(real x, real y, real w, real h)
-
- Creates an ellipse within the bounding rectangle defined by its top-left corner at (\a x, \ y), width \a w and height \a h,
- and adds it to the path as a closed subpath.
-
- The ellipse is composed of a clockwise curve, starting and finishing at zero degrees (the 3 o'clock position).
- */
-static v8::Handle<v8::Value> ctx2d_ellipse(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
-
- r->context->ellipse(x, y, w, h);
- }
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::text(string text, real x, real y)
-
- Adds the given \c text to the path as a set of closed subpaths created from the current context font supplied.
- The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\c x, \c y).
- */
-static v8::Handle<v8::Value> ctx2d_text(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
- if (args.Length() == 3) {
- qreal x = args[1]->NumberValue();
- qreal y = args[2]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
- r->context->text(engine->toString(args[0]), x, y);
- }
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::stroke()
-
- Strokes the subpaths with the current stroke style.
-
- See {http://www.w3.org/TR/2dcontext/#dom-context-2d-stroke}{W3C 2d context standard for stroke}
-
- \sa QtQuick2::Context2D::strokeStyle
- */
-static v8::Handle<v8::Value> ctx2d_stroke(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
-
- r->context->buffer()->stroke(r->context->m_path);
-
- return args.This();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::isPointInPath(real x, real y)
-
- Returns true if the given point is in the current path.
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath}{W3C 2d context standard for isPointInPath}
- */
-static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- bool pointInPath = false;
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return v8::Boolean::New(false);
- pointInPath = r->context->isPointInPath(x, y);
- }
- return v8::Boolean::New(pointInPath);
-}
-
-static v8::Handle<v8::Value> ctx2d_drawFocusRing(const v8::Arguments &args)
-{
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
- return args.This();
-}
-
-static v8::Handle<v8::Value> ctx2d_setCaretSelectionRect(const v8::Arguments &args)
-{
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
- return args.This();
-}
-
-static v8::Handle<v8::Value> ctx2d_caretBlinkRate(const v8::Arguments &args)
-{
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
- return args.This();
-}
-// text
-/*!
- \qmlproperty string QtQuick2::Context2D::font
- Holds the current font settings.
-
- The default font value is "10px sans-serif".
- See {http://www.w3.org/TR/2dcontext/#dom-context-2d-font}{w3C 2d context standard for font}
- */
-v8::Handle<v8::Value> ctx2d_font(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- return engine->toString(r->context->state.font.toString());
-}
-
-static void ctx2d_font_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- QString fs = engine->toString(value);
- QFont font = qt_font_from_string(fs);
- if (font != r->context->state.font) {
- r->context->state.font = font;
- }
-}
-
-/*!
- \qmlproperty string QtQuick2::Context2D::textAlign
-
- Holds the current text alignment settings.
- The possible values are:
- \list
- \o start
- \o end
- \o left
- \o right
- \o center
- \endlist
- Other values are ignored. The default value is "start".
- */
-v8::Handle<v8::Value> ctx2d_textAlign(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- switch (r->context->state.textAlign) {
- case QQuickContext2D::Start:
- return engine->toString(QLatin1String("start"));
- case QQuickContext2D::End:
- return engine->toString(QLatin1String("end"));
- case QQuickContext2D::Left:
- return engine->toString(QLatin1String("left"));
- case QQuickContext2D::Right:
- return engine->toString(QLatin1String("right"));
- case QQuickContext2D::Center:
- return engine->toString(QLatin1String("center"));
- default:
- break;
- }
- return engine->toString(QLatin1String("start"));
-}
-
-static void ctx2d_textAlign_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
- QV8Engine *engine = V8ENGINE_ACCESSOR();
-
- QString textAlign = engine->toString(value);
-
- QQuickContext2D::TextAlignType ta;
- if (textAlign == QLatin1String("start"))
- ta = QQuickContext2D::Start;
- else if (textAlign == QLatin1String("end"))
- ta = QQuickContext2D::End;
- else if (textAlign == QLatin1String("left"))
- ta = QQuickContext2D::Left;
- else if (textAlign == QLatin1String("right"))
- ta = QQuickContext2D::Right;
- else if (textAlign == QLatin1String("center"))
- ta = QQuickContext2D::Center;
- else
- return;
-
- if (ta != r->context->state.textAlign) {
- r->context->state.textAlign = ta;
- }
-}
-
-/*!
- \qmlproperty string QtQuick2::Context2D::textBaseline
-
- Holds the current baseline alignment settings.
- The possible values are:
- \list
- \o top
- \o hanging
- \o middle
- \o alphabetic
- \o ideographic
- \o bottom
- \endlist
- Other values are ignored. The default value is "alphabetic".
- */
-v8::Handle<v8::Value> ctx2d_textBaseline(v8::Local<v8::String>, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- switch (r->context->state.textBaseline) {
- case QQuickContext2D::Alphabetic:
- return engine->toString(QLatin1String("alphabetic"));
- case QQuickContext2D::Hanging:
- return engine->toString(QLatin1String("hanging"));
- case QQuickContext2D::Top:
- return engine->toString(QLatin1String("top"));
- case QQuickContext2D::Bottom:
- return engine->toString(QLatin1String("bottom"));
- case QQuickContext2D::Middle:
- return engine->toString(QLatin1String("middle"));
- default:
- break;
- }
- return engine->toString(QLatin1String("alphabetic"));
-}
-
-static void ctx2d_textBaseline_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
- CHECK_CONTEXT_SETTER(r)
- QV8Engine *engine = V8ENGINE_ACCESSOR();
- QString textBaseline = engine->toString(value);
-
- QQuickContext2D::TextBaseLineType tb;
- if (textBaseline == QLatin1String("alphabetic"))
- tb = QQuickContext2D::Alphabetic;
- else if (textBaseline == QLatin1String("hanging"))
- tb = QQuickContext2D::Hanging;
- else if (textBaseline == QLatin1String("top"))
- tb = QQuickContext2D::Top;
- else if (textBaseline == QLatin1String("bottom"))
- tb = QQuickContext2D::Bottom;
- else if (textBaseline == QLatin1String("middle"))
- tb = QQuickContext2D::Middle;
- else
- return;
-
- if (tb != r->context->state.textBaseline) {
- r->context->state.textBaseline = tb;
- }
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::fillText(text, x, y)
- Fills the given text at the given position.
- \sa QtQuick2::Context2D::font
- \sa QtQuick2::Context2D::textAlign
- \sa QtQuick2::Context2D::textBaseline
- \sa QtQuick2::Context2D::strokeText
- */
-static v8::Handle<v8::Value> ctx2d_fillText(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
- if (args.Length() == 3) {
- qreal x = args[1]->NumberValue();
- qreal y = args[2]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
- QPainterPath textPath = r->context->createTextGlyphs(x, y, engine->toString(args[0]));
- r->context->buffer()->fill(textPath);
- }
- return args.This();
-}
-/*!
- \qmlmethod object QtQuick2::Context2D::strokeText(text, x, y)
- Strokes the given text at the given position.
- \sa QtQuick2::Context2D::font
- \sa QtQuick2::Context2D::textAlign
- \sa QtQuick2::Context2D::textBaseline
- \sa QtQuick2::Context2D::fillText
- */
-static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
- if (args.Length() == 3) {
- qreal x = args[1]->NumberValue();
- qreal y = args[2]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
- QPainterPath textPath = r->context->createTextGlyphs(x, y, engine->toString(args[0]));
- r->context->buffer()->stroke(textPath);
- }
- return args.This();
-}
-/*!
- \qmlclass QtQuick2::TextMetrics
- \inqmlmodule QtQuick 2
- \since QtQuick 2.0
- \brief The Context2D TextMetrics interface.
- The TextMetrics object can be created by QtQuick2::Context2D::measureText method.
- See {http://www.w3.org/TR/2dcontext/#textmetrics}{W3C 2d context TexMetrics} for more details.
-
- \sa QtQuick2::Context2D::measureText
- \sa QtQuick2::TextMetrics::width
- */
-
-/*!
- \qmlproperty int QtQuick2::TextMetrics::width
- Holds the advance width of the text that was passed to the QtQuick2::Context2D::measureText() method.
- This property is read only.
- */
-
-/*!
- \qmlmethod variant QtQuick2::Context2D::measureText(text)
- Returns a TextMetrics object with the metrics of the given text in the current font.
- */
-static v8::Handle<v8::Value> ctx2d_measureText(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 1) {
- QFontMetrics fm(r->context->state.font);
- uint width = fm.width(engine->toString(args[0]));
- v8::Local<v8::Object> tm = v8::Object::New();
- tm->Set(v8::String::New("width"), v8::Number::New(width));
- return tm;
- }
- return v8::Undefined();
-}
-
-// drawing images
-/*!
- \qmlmethod QtQuick2::Context2D::drawImage(variant image, real dx, real dy)
- Draws the given \a image on the canvas at position (\a dx, \a dy).
- Note:
- The \a image type can be an Image item, an image url or a \a {QtQuick2::CanvasImageData} object.
- When given as Image item, if the image isn't fully loaded, this method draws nothing.
- When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
- This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
-
- \sa QtQuick2::CanvasImageData
- \sa QtQuick2::Image
- \sa QtQuick2::Canvas::loadImage
- \sa QtQuick2::Canvas::isImageLoaded
- \sa QtQuick2::Canvas::imageLoaded
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
- */
-/*!
- \qmlmethod QtQuick2::Context2D::drawImage(variant image, real dx, real dy, real dw, real dh)
- This is an overloaded function.
- Draws the given item as \a image onto the canvas at point (\a dx, \a dy) and with width \a dw,
- height \a dh.
-
- Note:
- The \a image type can be an Image item, an image url or a \a {QtQuick2::CanvasImageData} object.
- When given as Image item, if the image isn't fully loaded, this method draws nothing.
- When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
- This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
-
- \sa QtQuick2::CanvasImageData
- \sa QtQuick2::Image
- \sa QtQuick2::Canvas::loadImage
- \sa QtQuick2::Canvas::isImageLoaded
- \sa QtQuick2::Canvas::imageLoaded
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
- */
-/*!
- \qmlmethod QtQuick2::Context2D::drawImage(variant image, real sx, real sy, real sw, sh, real dx, real dy, real dw, dh)
- This is an overloaded function.
- Draws the given item as \a image from source point (\a sx, \a sy) and source width \sw, source height \sh
- onto the canvas at point (\a dx, \a dy) and with width \a dw, height \a dh.
-
-
- Note:
- The \a image type can be an Image or Canvas item, an image url or a \a {QtQuick2::CanvasImageData} object.
- When given as Image item, if the image isn't fully loaded, this method draws nothing.
- When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
- This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
-
- \sa QtQuick2::CanvasImageData
- \sa QtQuick2::Image
- \sa QtQuick2::Canvas::loadImage
- \sa QtQuick2::Canvas::isImageLoaded
- \sa QtQuick2::Canvas::imageLoaded
-
- \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
-*/
-static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
- qreal sx, sy, sw, sh, dx, dy, dw, dh;
-
- if (!args.Length())
- return args.This();
-
- QImage image;
- if (args[0]->IsString()) {
- QUrl url(engine->toString(args[0]->ToString()));
- if (!url.isValid())
- V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
-
- image = r->context->createImage(url);
- } else if (args[0]->IsObject()) {
- QQuickImage *imageItem = qobject_cast<QQuickImage*>(engine->toQObject(args[0]->ToObject()));
- QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(engine->toQObject(args[0]->ToObject()));
-
- QV8Context2DPixelArrayResource *pix = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->GetInternalField(0)->ToObject());
- if (pix) {
- image = pix->image;
- } else if (imageItem) {
- image = imageItem->image();
- } else if (canvas) {
- image = canvas->toImage();
- } else {
- V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
- }
- } else {
- V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
- }
- if (args.Length() == 3) {
- dx = args[1]->NumberValue();
- dy = args[2]->NumberValue();
- sx = 0;
- sy = 0;
- sw = image.width();
- sh = image.height();
- dw = sw;
- dh = sh;
- } else if (args.Length() == 5) {
- sx = 0;
- sy = 0;
- sw = image.width();
- sh = image.height();
- dx = args[1]->NumberValue();
- dy = args[2]->NumberValue();
- dw = args[3]->NumberValue();
- dh = args[4]->NumberValue();
- } else if (args.Length() == 9) {
- sx = args[1]->NumberValue();
- sy = args[2]->NumberValue();
- sw = args[3]->NumberValue();
- sh = args[4]->NumberValue();
- dx = args[5]->NumberValue();
- dy = args[6]->NumberValue();
- dw = args[7]->NumberValue();
- dh = args[8]->NumberValue();
- } else {
- return args.This();
- }
-
- if (!qIsFinite(sx)
- || !qIsFinite(sy)
- || !qIsFinite(sw)
- || !qIsFinite(sh)
- || !qIsFinite(dx)
- || !qIsFinite(dy)
- || !qIsFinite(dw)
- || !qIsFinite(dh))
- return args.This();
-
- if (!image.isNull()) {
- if (sx < 0 || sy < 0 || sw == 0 || sh == 0
- || sx + sw > image.width() || sy + sh > image.height()
- || sx + sw < 0 || sy + sh < 0) {
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
- }
-
- r->context->buffer()->drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
- }
-
- return args.This();
-}
-
-// pixel manipulation
-/*!
- \qmlclass QtQuick2::CanvasImageData
- The \a QtQuick2::CanvasImageData object holds the image pixel data.
-
- The \a QtQuick2::CanvasImageData object has the actual dimensions of the data stored in
- this object and holds the one-dimensional array containing the data in RGBA order,
- as integers in the range 0 to 255.
-
- \sa QtQuick2::CanvasImageData::width
- \sa QtQuick2::CanvasImageData::height
- \sa QtQuick2::CanvasImageData::data
- \sa QtQuick2::Context2D::createImageData
- \sa QtQuick2::Context2D::getImageData
- \sa QtQuick2::Context2D::putImageData
- */
-/*!
- \qmlproperty QtQuick2::CanvasImageData::width
- Holds the actual width dimension of the data in the ImageData object, in device pixels.
- */
-v8::Handle<v8::Value> ctx2d_imageData_width(v8::Local<v8::String>, const v8::AccessorInfo &args)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
- if (!r)
- return v8::Integer::New(0);
- return v8::Integer::New(r->image.width());
-}
-
-/*!
- \qmlproperty QtQuick2::CanvasImageData::height
- Holds the actual height dimension of the data in the ImageData object, in device pixels.
- */
-v8::Handle<v8::Value> ctx2d_imageData_height(v8::Local<v8::String>, const v8::AccessorInfo &args)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
- if (!r)
- return v8::Integer::New(0);
-
- return v8::Integer::New(r->image.height());
-}
-
-/*!
- \qmlproperty QtQuick2::CanvasImageData::data
- Holds the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255.
- */
-v8::Handle<v8::Value> ctx2d_imageData_data(v8::Local<v8::String>, const v8::AccessorInfo &args)
-{
- return args.This()->GetInternalField(0);
-}
-
-/*!
- \qmlmethod void QtQuick2::CanvasImageData::mirrr( bool horizontal = false, bool vertical = true)
- Mirrors the image data in place in the \c horizontal and/or the \c vertical direction depending on
- whether horizontal and vertical are set to true or false.
- The default \c horizontal value is false, the default \c vertical value is true.
-*/
-static v8::Handle<v8::Value> ctx2d_imageData_mirror(const v8::Arguments &args)
-{
- bool horizontal = false, vertical = true;
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
-
- if (!r) {
- //error
- return v8::Undefined();
- }
-
- if (args.Length() > 2) {
- //error
- return v8::Undefined();
- }
-
- if (args.Length() == 1) {
- horizontal = args[0]->BooleanValue();
- } else if (args.Length() == 2) {
- horizontal = args[0]->BooleanValue();
- vertical = args[1]->BooleanValue();
- }
- r->image = r->image.mirrored(horizontal, vertical);
- return args.This();
-}
-
-/*!
- \qmlmethod void QtQuick2::CanvasImageData::filter(enumeration mode, args)
- Filters the image data as defined by one of the following modes:
- \list
- \o Canvas.Threshold - converts the image to black and white pixels depending
- if they are above or below the threshold defined by the level parameter.
- The level must be between 0.0 (black) and 1.0(white).
- If no level is specified, 0.5 is used.
- \o Canvas.Mono - converts the image to the 1-bit per pixel format.
- \o Canvas.GrayScale - converts any colors in the image to grayscale equivalents.
- \o Canvas.Brightness -increase/decrease a fixed \c adjustment value to each pixel's RGB channel value.
- \o Canvas.Invert - sets each pixel to its inverse value.
- \o Canvas.Blur - executes a box blur with the pixel \c radius parameter specifying the range of the blurring for each pixel.
- the default blur \c radius is 3. This filter also accepts another \c quality parameter, if true, the filter will
- execute 3-passes box blur to simulate the Guassian blur. The default \c quality value is false.
- \o Canvas.Opaque - sets the alpha channel to entirely opaque.
- \o Canvas.Convolute - executes a generic {http://en.wikipedia.org/wiki/Convolution}{Convolution} filter, the second
- parameter contains the convoluton matrix data as a number array.
- \endlist
-
-*/
-static v8::Handle<v8::Value> ctx2d_imageData_filter(const v8::Arguments &args)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
-
- if (!r) {
- //error
- return v8::Undefined();
- }
-
- if (args.Length() >= 1) {
- int filterFlag = args[0]->IntegerValue();
- switch (filterFlag) {
- case QQuickCanvasItem::Mono :
- {
- r->image = r->image.convertToFormat(QImage::Format_Mono).convertToFormat(QImage::Format_ARGB32_Premultiplied);
- }
- break;
- case QQuickCanvasItem::GrayScale :
- {
- for (int y = 0; y < r->image.height(); ++y) {
- QRgb *row = (QRgb*)r->image.scanLine(y);
- for (int x = 0; x < r->image.width(); ++x) {
- unsigned char* rgb = ((unsigned char*)&row[x]);
- rgb[0] = rgb[1] = rgb[2] = qGray(rgb[0], rgb[1], rgb[2]);
- }
- }
- }
- break;
- case QQuickCanvasItem::Threshold :
- {
- qreal threshold = 0.5;
- if (args.Length() > 1)
- threshold = args[1]->NumberValue();
-
- for (int y = 0; y < r->image.height(); ++y) {
- QRgb *row = (QRgb*)r->image.scanLine(y);
- for (int x = 0; x < r->image.width(); ++x) {
- unsigned char* rgb = ((unsigned char*)&row[x]);
- unsigned char v = qGray(rgb[0], rgb[1], rgb[2]) >= threshold*255 ? 255 : 0;
- rgb[0] = rgb[1] = rgb[2] = v;
- }
- }
- }
- break;
- case QQuickCanvasItem::Brightness :
- {
- int adjustment = 1;
- if (args.Length() > 1)
- adjustment = args[1]->IntegerValue();
-
- for (int y = 0; y < r->image.height(); ++y) {
- QRgb *row = (QRgb*)r->image.scanLine(y);
- for (int x = 0; x < r->image.width(); ++x) {
- ((unsigned char*)&row[x])[0] += adjustment;
- ((unsigned char*)&row[x])[1] += adjustment;
- ((unsigned char*)&row[x])[2] += adjustment;
- }
- }
- }
- break;
- case QQuickCanvasItem::Invert :
- {
- r->image.invertPixels();
- }
- break;
- case QQuickCanvasItem::Blur :
- {
- int radius = 3;
- bool quality = false;
-
- if (args.Length() > 1)
- radius = args[1]->IntegerValue() / 2;
- if (args.Length() > 2)
- quality = args[2]->BooleanValue();
-
- qt_image_boxblur(r->image, radius, quality);
- }
- break;
- case QQuickCanvasItem::Opaque :
- {
- for (int y = 0; y < r->image.height(); ++y) {
- QRgb *row = (QRgb*)r->image.scanLine(y);
- for (int x = 0; x < r->image.width(); ++x) {
- ((unsigned char*)&row[x])[3] = 255;
- }
- }
- }
- break;
- case QQuickCanvasItem::Convolute :
- {
- if (args.Length() > 1 && args[1]->IsArray()) {
- v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]);
- QVector<qreal> weights;
- for (uint32_t i = 0; i < array->Length(); ++i)
- weights.append(array->Get(i)->NumberValue());
- r->image = qt_image_convolute_filter(r->image, weights);
- } else {
- //error
- }
- }
- break;
- default:
- break;
- }
- }
-
- return args.This();
-}
-/*!
- \qmlclass QtQuick2::CanvasPixelArray
- The CanvasPixelArray object provides ordered, indexed access to the color components of each pixel of the image data.
- The CanvasPixelArray can be accessed as normal Javascript array.
- \sa QtQuick2::CanvasImageData
- \sa {http://www.w3.org/TR/2dcontext/#canvaspixelarray}{W3C 2d context standard for PixelArray}
- */
-
-/*!
- \qmlproperty QtQuick2::CanvasPixelArray::length
- The CanvasPixelArray object represents h×w×4 integers which w and h comes from CanvasImageData.
- The length attribute of a CanvasPixelArray object must return this h×w×4 number value.
- This property is read only.
-*/
-v8::Handle<v8::Value> ctx2d_pixelArray_length(v8::Local<v8::String>, const v8::AccessorInfo &args)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This());
- if (!r || r->image.isNull()) return v8::Undefined();
-
- return v8::Integer::New(r->image.width() * r->image.height() * 4);
-}
-
-v8::Handle<v8::Value> ctx2d_pixelArray_indexed(uint32_t index, const v8::AccessorInfo& args)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This());
-
- if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4)) {
- const quint32 w = r->image.width();
- const quint32 row = (index / 4) / w;
- const quint32 col = (index / 4) % w;
- const QRgb* pixel = reinterpret_cast<const QRgb*>(r->image.constScanLine(row));
- pixel += col;
- switch (index % 4) {
- case 0:
- return v8::Integer::New(qRed(*pixel));
- case 1:
- return v8::Integer::New(qGreen(*pixel));
- case 2:
- return v8::Integer::New(qBlue(*pixel));
- case 3:
- return v8::Integer::New(qAlpha(*pixel));
- }
- }
- return v8::Undefined();
-}
-
-v8::Handle<v8::Value> ctx2d_pixelArray_indexed_set(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
-{
- QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(info.This());
-
- const int v = value->Uint32Value();
- if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4) && v > 0 && v <= 255) {
- const quint32 w = r->image.width();
- const quint32 row = (index / 4) / w;
- const quint32 col = (index / 4) % w;
-
- QRgb* pixel = reinterpret_cast<QRgb*>(r->image.scanLine(row));
- pixel += col;
- switch (index % 4) {
- case 0:
- *pixel = qRgba(v, qGreen(*pixel), qBlue(*pixel), qAlpha(*pixel));
- break;
- case 1:
- *pixel = qRgba(qRed(*pixel), v, qBlue(*pixel), qAlpha(*pixel));
- break;
- case 2:
- *pixel = qRgba(qRed(*pixel), qGreen(*pixel), v, qAlpha(*pixel));
- break;
- case 3:
- *pixel = qRgba(qRed(*pixel), qGreen(*pixel), qBlue(*pixel), v);
- break;
- }
- }
- return v8::Undefined();
-}
-/*!
- \qmlmethod QtQuick2::CanvasImageData createImageData(real sw, real sh)
- Creates a CanvasImageData object with the given dimensions(\a sw, \a sh).
- */
-/*!
- \qmlmethod QtQuick2::CanvasImageData createImageData(QtQuick2::CanvasImageData imageData)
- Creates a CanvasImageData object with the same dimensions as the argument.
- */
-/*!
- \qmlmethod QtQuick2::CanvasImageData createImageData(Url imageUrl)
- Creates a CanvasImageData object with the given image loaded from \a imageUrl.
- Note:The \a imageUrl must be already loaded before this function call, if not, an empty
- CanvasImageData obect will be returned.
-
- \sa QtQuick2::Canvas::loadImage, QtQuick2::Canvas::unloadImage, QtQuick2::Canvas::isImageLoaded
- */
-static v8::Handle<v8::Value> ctx2d_createImageData(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 1) {
- if (args[0]->IsObject()) {
- v8::Local<v8::Object> imgData = args[0]->ToObject();
- QV8Context2DPixelArrayResource *pa = v8_resource_cast<QV8Context2DPixelArrayResource>(imgData->GetInternalField(0)->ToObject());
- if (pa) {
- qreal w = imgData->Get(v8::String::New("width"))->NumberValue();
- qreal h = imgData->Get(v8::String::New("height"))->NumberValue();
- return qt_create_image_data(w, h, engine, QImage());
- }
- } else if (args[0]->IsString()) {
- QImage image = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
- return qt_create_image_data(image.width(), image.height(), engine, image);
- }
- } else if (args.Length() == 2) {
- qreal w = args[0]->NumberValue();
- qreal h = args[1]->NumberValue();
-
- if (!qIsFinite(w) || !qIsFinite(h))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
-
- if (w > 0 && h > 0)
- return qt_create_image_data(w, h, engine, QImage());
- else
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments");
- }
- return v8::Undefined();
-}
-
-/*!
- \qmlmethod QtQuick2::CanvasImageData getImageData(real sx, real sy, real sw, real sh)
- Returns an CanvasImageData object containing the image data for the given rectangle of the canvas.
- */
-static v8::Handle<v8::Value> ctx2d_getImageData(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
-
- QV8Engine *engine = V8ENGINE();
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(w))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
-
- if (w <= 0 || h <= 0)
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments");
-
- QImage image = r->context->canvas()->toImage(QRectF(x, y, w, h));
- v8::Local<v8::Object> imageData = qt_create_image_data(w, h, engine, image);
-
- return imageData;
- }
- return v8::Null();
-}
-
-/*!
- \qmlmethod object QtQuick2::Context2D::putImageData(QtQuick2::CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight)
- Paints the data from the given ImageData object onto the canvas. If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight) is provided, only the pixels from that rectangle are painted.
- */
-static v8::Handle<v8::Value> ctx2d_putImageData(const v8::Arguments &args)
-{
- QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
- if (args.Length() != 3 && args.Length() != 7)
- return v8::Undefined();
-
- if (args[0]->IsNull() || !args[0]->IsObject()) {
- V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch");
- }
- qreal dx = args[1]->NumberValue();
- qreal dy = args[2]->NumberValue();
- qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
-
- if (!qIsFinite(dx) || !qIsFinite(dy))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
-
- v8::Local<v8::Object> imageData = args[0]->ToObject();
- QV8Context2DPixelArrayResource *pixelArray = v8_resource_cast<QV8Context2DPixelArrayResource>(imageData->Get(v8::String::New("data"))->ToObject());
- if (pixelArray) {
- w = imageData->Get(v8::String::New("width"))->NumberValue();
- h = imageData->Get(v8::String::New("height"))->NumberValue();
-
- if (args.Length() == 7) {
- dirtyX = args[3]->NumberValue();
- dirtyY = args[4]->NumberValue();
- dirtyWidth = args[5]->NumberValue();
- dirtyHeight = args[6]->NumberValue();
-
- if (!qIsFinite(dirtyX) || !qIsFinite(dirtyY) || !qIsFinite(dirtyWidth) || !qIsFinite(dirtyHeight))
- V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
-
-
- if (dirtyWidth < 0) {
- dirtyX = dirtyX+dirtyWidth;
- dirtyWidth = -dirtyWidth;
- }
-
- if (dirtyHeight < 0) {
- dirtyY = dirtyY+dirtyHeight;
- dirtyHeight = -dirtyHeight;
- }
-
- if (dirtyX < 0) {
- dirtyWidth = dirtyWidth+dirtyX;
- dirtyX = 0;
- }
-
- if (dirtyY < 0) {
- dirtyHeight = dirtyHeight+dirtyY;
- dirtyY = 0;
- }
-
- if (dirtyX+dirtyWidth > w) {
- dirtyWidth = w - dirtyX;
- }
-
- if (dirtyY+dirtyHeight > h) {
- dirtyHeight = h - dirtyY;
- }
-
- if (dirtyWidth <=0 || dirtyHeight <= 0)
- return args.This();
- } else {
- dirtyX = 0;
- dirtyY = 0;
- dirtyWidth = w;
- dirtyHeight = h;
- }
-
- QImage image = pixelArray->image.copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
- r->context->buffer()->drawImage(image, dirtyX, dirtyY, dirtyWidth, dirtyHeight, dx, dy, dirtyWidth, dirtyHeight);
- }
- return args.This();
-}
-
-/*!
- \qmlclass QtQuick2::CanvasGradient
- \inqmlmodule QtQuick 2
- \since QtQuick 2.0
- \brief The Context2D opaque CanvasGradient interface.
- */
-
-/*!
- \qmlmethod QtQuick2::CanvasGradient QtQuick2::CanvasGradient::addColorStop(real offsetof, string color)
- Adds a color stop with the given color to the gradient at the given offset.
- 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end.
-
- For example:
- \code
- var gradient = ctx.createLinearGradient(0, 0, 100, 100);
- gradient.addColorStop(0.3, Qt.rgba(1, 0, 0, 1));
- gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1');
- \endcode
- */
-static v8::Handle<v8::Value> ctx2d_gradient_addColorStop(const v8::Arguments &args)
-{
- QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(args.This());
- if (!style)
- V8THROW_ERROR("Not a CanvasGradient object");
-
- QV8Engine *engine = V8ENGINE();
-
- if (args.Length() == 2) {
-
- if (!style->brush.gradient())
- V8THROW_ERROR("Not a valid CanvasGradient object, can't get the gradient information");
- QGradient gradient = *(style->brush.gradient());
- qreal pos = args[0]->NumberValue();
- QColor color;
-
- if (args[1]->IsObject()) {
- color = engine->toVariant(args[1], qMetaTypeId<QColor>()).value<QColor>();
- } else {
- color = qt_color_from_string(args[1]);
- }
- if (pos < 0.0 || pos > 1.0 || !qIsFinite(pos)) {
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
- }
-
- if (color.isValid()) {
- gradient.setColorAt(pos, color);
- } else {
- V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string");
- }
- style->brush = gradient;
- }
-
- return args.This();
-}
-
-
-void QQuickContext2D::beginPath()
-{
- m_path = QPainterPath();
- m_path.setFillRule(state.fillRule);
-}
-
-void QQuickContext2D::closePath()
-{
- if (m_path.isEmpty())
- return;
-
- QRectF boundRect = m_path.boundingRect();
- if (boundRect.width() || boundRect.height())
- m_path.closeSubpath();
- //FIXME:QPainterPath set the current point to (0,0) after close subpath
- //should be the first point of the previous subpath
-}
-
-void QQuickContext2D::moveTo( qreal x, qreal y)
-{
- //FIXME: moveTo should not close the previous subpath
- m_path.moveTo(state.matrix.map(QPointF(x, y)));
-}
-
-void QQuickContext2D::lineTo( qreal x, qreal y)
-{
- m_path.lineTo(state.matrix.map(QPointF(x, y)));
-}
-
-void QQuickContext2D::quadraticCurveTo(qreal cpx, qreal cpy,
- qreal x, qreal y)
-{
- m_path.quadTo(state.matrix.map(QPointF(cpx, cpy)),
- state.matrix.map(QPointF(x, y)));
-}
-
-void QQuickContext2D::bezierCurveTo(qreal cp1x, qreal cp1y,
- qreal cp2x, qreal cp2y,
- qreal x, qreal y)
-{
- m_path.cubicTo(state.matrix.map(QPointF(cp1x, cp1y)),
- state.matrix.map(QPointF(cp2x, cp2y)),
- state.matrix.map(QPointF(x, y)));
-}
-
-void QQuickContext2D::addArcTo(const QPointF& p1, const QPointF& p2, float radius)
-{
- QPointF p0(m_path.currentPosition());
-
- QPointF p1p0((p0.x() - p1.x()), (p0.y() - p1.y()));
- QPointF p1p2((p2.x() - p1.x()), (p2.y() - p1.y()));
- float p1p0_length = qSqrt(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y());
- float p1p2_length = qSqrt(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y());
-
- double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length);
-
- // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8)
- // We could have used areCollinear() here, but since we're reusing
- // the variables computed above later on we keep this logic.
- if (qFuzzyCompare(qAbs(cos_phi), 1.0)) {
- m_path.lineTo(p1);
- return;
- }
-
- float tangent = radius / tan(acos(cos_phi) / 2);
- float factor_p1p0 = tangent / p1p0_length;
- QPointF t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));
-
- QPointF orth_p1p0(p1p0.y(), -p1p0.x());
- float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y());
- float factor_ra = radius / orth_p1p0_length;
-
- // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
- double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length);
- if (cos_alpha < 0.f)
- orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
-
- QPointF p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));
-
- // calculate angles for addArc
- orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
- float sa = acos(orth_p1p0.x() / orth_p1p0_length);
- if (orth_p1p0.y() < 0.f)
- sa = 2 * Q_PI - sa;
-
- // anticlockwise logic
- bool anticlockwise = false;
-
- float factor_p1p2 = tangent / p1p2_length;
- QPointF t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
- QPointF orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y()));
- float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y());
- float ea = acos(orth_p1p2.x() / orth_p1p2_length);
- if (orth_p1p2.y() < 0)
- ea = 2 * Q_PI - ea;
- if ((sa > ea) && ((sa - ea) < Q_PI))
- anticlockwise = true;
- if ((sa < ea) && ((ea - sa) > Q_PI))
- anticlockwise = true;
-
- arc(p.x(), p.y(), radius, sa, ea, anticlockwise, false);
-}
-
-void QQuickContext2D::arcTo(qreal x1, qreal y1,
- qreal x2, qreal y2,
- qreal radius)
-{
- QPointF st = state.matrix.map(QPointF(x1, y1));
- QPointF end = state.matrix.map(QPointF(x2, y2));
-
- if (!m_path.elementCount()) {
- m_path.moveTo(st);
- } else if (st == m_path.currentPosition() || st == end || !radius) {
- m_path.lineTo(st);
- } else {
- addArcTo(st, end, radius);
- }
-}
-
-void QQuickContext2D::rect(qreal x, qreal y,
- qreal w, qreal h)
-{
- m_path.addPolygon(state.matrix.map(QRectF(x, y, w, h)));
-}
-
-void QQuickContext2D::roundedRect(qreal x, qreal y,
- qreal w, qreal h,
- qreal xr, qreal yr)
-{
- QPainterPath path;
- path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
- m_path.addPath(state.matrix.map(path));
-}
-
-void QQuickContext2D::ellipse(qreal x, qreal y,
- qreal w, qreal h)
-{
- QPainterPath path;
- path.addEllipse(x, y, w, h);
- m_path.addPath(state.matrix.map(path));
-}
-
-void QQuickContext2D::text(const QString& str, qreal x, qreal y)
-{
- QPainterPath path;
- path.addText(x, y, state.font, str);
- m_path.addPath(state.matrix.map(path));
-}
-
-void QQuickContext2D::arc(qreal xc,
- qreal yc,
- qreal radius,
- qreal sar,
- qreal ear,
- bool antiClockWise,
- bool transform)
-{
-
- if (transform) {
- QPointF point = state.matrix.map(QPointF(xc, yc));
- xc = point.x();
- yc = point.y();
- }
- //### HACK
-
- // In Qt we don't switch the coordinate system for degrees
- // and still use the 0,0 as bottom left for degrees so we need
- // to switch
- sar = -sar;
- ear = -ear;
- antiClockWise = !antiClockWise;
- //end hack
-
- float sa = DEGREES(sar);
- float ea = DEGREES(ear);
-
- double span = 0;
-
- double xs = xc - radius;
- double ys = yc - radius;
- double width = radius*2;
- double height = radius*2;
- if ((!antiClockWise && (ea - sa >= 360)) || (antiClockWise && (sa - ea >= 360)))
- // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
- // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
- // circumference of this circle.
- span = 360;
- else {
- if (!antiClockWise && (ea < sa)) {
- span += 360;
- } else if (antiClockWise && (sa < ea)) {
- span -= 360;
- }
- //### this is also due to switched coordinate system
- // we would end up with a 0 span instead of 360
- if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
- qFuzzyCompare(qAbs(span), 360))) {
- span += ea - sa;
- }
- if (!m_path.elementCount())
- m_path.moveTo(xs, ys);
- }
-
-
- if (transform) {
- QPointF currentPos = m_path.currentPosition();
- QPointF startPos = QPointF(xc + radius * qCos(sar),
- yc - radius * qSin(sar));
- if (currentPos != startPos)
- m_path.lineTo(startPos);
- }
-
- m_path.arcTo(xs, ys, width, height, sa, span);
-}
-
-int baseLineOffset(QQuickContext2D::TextBaseLineType value, const QFontMetrics &metrics)
-{
- int offset = 0;
- switch (value) {
- case QQuickContext2D::Top:
- break;
- case QQuickContext2D::Alphabetic:
- case QQuickContext2D::Middle:
- case QQuickContext2D::Hanging:
- offset = metrics.ascent();
- break;
- case QQuickContext2D::Bottom:
- offset = metrics.height();
- break;
- }
- return offset;
-}
-
-static int textAlignOffset(QQuickContext2D::TextAlignType value, const QFontMetrics &metrics, const QString &text)
-{
- int offset = 0;
- if (value == QQuickContext2D::Start)
- value = QGuiApplication::layoutDirection() == Qt::LeftToRight ? QQuickContext2D::Left : QQuickContext2D::Right;
- else if (value == QQuickContext2D::End)
- value = QGuiApplication::layoutDirection() == Qt::LeftToRight ? QQuickContext2D::Right: QQuickContext2D::Left;
- switch (value) {
- case QQuickContext2D::Center:
- offset = metrics.width(text)/2;
- break;
- case QQuickContext2D::Right:
- offset = metrics.width(text);
- case QQuickContext2D::Left:
- default:
- break;
- }
- return offset;
-}
-
-
-QImage QQuickContext2D::createImage(const QUrl& url)
-{
- return m_canvas->loadedImage(url);
-}
-
-QPainterPath QQuickContext2D::createTextGlyphs(qreal x, qreal y, const QString& text)
-{
- const QFontMetrics metrics(state.font);
- int yoffset = baseLineOffset(static_cast<QQuickContext2D::TextBaseLineType>(state.textBaseline), metrics);
- int xoffset = textAlignOffset(static_cast<QQuickContext2D::TextAlignType>(state.textAlign), metrics, text);
-
- QPainterPath textPath;
-
- textPath.addText(x - xoffset, y - yoffset+metrics.ascent(), state.font, text);
- textPath = state.matrix.map(textPath);
- return textPath;
-}
-
-
-bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
-{
- return m_path.contains(QPointF(x, y));
-}
-
-QQuickContext2D::QQuickContext2D(QQuickCanvasItem* item)
- : m_canvas(item)
- , m_buffer(new QQuickContext2DCommandBuffer)
- , m_v8engine(0)
-{
- reset();
-}
-
-QQuickContext2D::~QQuickContext2D()
-{
- delete m_buffer;
-}
-
-v8::Handle<v8::Object> QQuickContext2D::v8value() const
-{
- return m_v8value;
-}
-
-QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
-{
- v8::HandleScope handle_scope;
- v8::Context::Scope scope(engine->context());
-
- v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
- ft->InstanceTemplate()->SetHasExternalResource(true);
- ft->PrototypeTemplate()->SetAccessor(v8::String::New("canvas"), ctx2d_canvas, 0, v8::External::Wrap(engine));
- ft->PrototypeTemplate()->Set(v8::String::New("restore"), V8FUNCTION(ctx2d_restore, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("reset"), V8FUNCTION(ctx2d_reset, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("save"), V8FUNCTION(ctx2d_save, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("rotate"), V8FUNCTION(ctx2d_rotate, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("scale"), V8FUNCTION(ctx2d_scale, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("resetTransform"), V8FUNCTION(ctx2d_resetTransform, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("setTransform"), V8FUNCTION(ctx2d_setTransform, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("transform"), V8FUNCTION(ctx2d_transform, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("translate"), V8FUNCTION(ctx2d_translate, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("shear"), V8FUNCTION(ctx2d_shear, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("globalAlpha"), ctx2d_globalAlpha, ctx2d_globalAlpha_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("globalCompositeOperation"), ctx2d_globalCompositeOperation, ctx2d_globalCompositeOperation_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("fillRule"), ctx2d_fillRule, ctx2d_fillRule_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("fillStyle"), ctx2d_fillStyle, ctx2d_fillStyle_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("strokeStyle"), ctx2d_strokeStyle, ctx2d_strokeStyle_set, v8::External::Wrap(engine));
- ft->PrototypeTemplate()->Set(v8::String::New("createLinearGradient"), V8FUNCTION(ctx2d_createLinearGradient, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("createRadialGradient"), V8FUNCTION(ctx2d_createRadialGradient, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("createConicalGradient"), V8FUNCTION(ctx2d_createConicalGradient, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("createPattern"), V8FUNCTION(ctx2d_createPattern, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineCap"), ctx2d_lineCap, ctx2d_lineCap_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineJoin"), ctx2d_lineJoin, ctx2d_lineJoin_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("lineWidth"), ctx2d_lineWidth, ctx2d_lineWidth_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("miterLimit"), ctx2d_miterLimit, ctx2d_miterLimit_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowBlur"), ctx2d_shadowBlur, ctx2d_shadowBlur_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowColor"), ctx2d_shadowColor, ctx2d_shadowColor_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetX"), ctx2d_shadowOffsetX, ctx2d_shadowOffsetX_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetY"), ctx2d_shadowOffsetY, ctx2d_shadowOffsetY_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("path"), ctx2d_path, ctx2d_path_set, v8::External::Wrap(engine));
- ft->PrototypeTemplate()->Set(v8::String::New("clearRect"), V8FUNCTION(ctx2d_clearRect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("fillRect"), V8FUNCTION(ctx2d_fillRect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("strokeRect"), V8FUNCTION(ctx2d_strokeRect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("arc"), V8FUNCTION(ctx2d_arc, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("arcTo"), V8FUNCTION(ctx2d_arcTo, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("beginPath"), V8FUNCTION(ctx2d_beginPath, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("bezierCurveTo"), V8FUNCTION(ctx2d_bezierCurveTo, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("clip"), V8FUNCTION(ctx2d_clip, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("closePath"), V8FUNCTION(ctx2d_closePath, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("fill"), V8FUNCTION(ctx2d_fill, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("lineTo"), V8FUNCTION(ctx2d_lineTo, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("moveTo"), V8FUNCTION(ctx2d_moveTo, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("quadraticCurveTo"), V8FUNCTION(ctx2d_quadraticCurveTo, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("rect"), V8FUNCTION(ctx2d_rect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("roundedRect"), V8FUNCTION(ctx2d_roundedRect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("text"), V8FUNCTION(ctx2d_text, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("ellipse"), V8FUNCTION(ctx2d_ellipse, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("stroke"), V8FUNCTION(ctx2d_stroke, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("isPointInPath"), V8FUNCTION(ctx2d_isPointInPath, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("drawFocusRing"), V8FUNCTION(ctx2d_drawFocusRing, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("caretBlinkRate"), V8FUNCTION(ctx2d_caretBlinkRate, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("setCaretSelectionRect"), V8FUNCTION(ctx2d_setCaretSelectionRect, engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("font"), ctx2d_font, ctx2d_font_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("textAlign"), ctx2d_textAlign, ctx2d_textAlign_set, v8::External::Wrap(engine));
- ft->InstanceTemplate()->SetAccessor(v8::String::New("textBaseline"), ctx2d_textBaseline, ctx2d_textBaseline_set, v8::External::Wrap(engine));
- ft->PrototypeTemplate()->Set(v8::String::New("fillText"), V8FUNCTION(ctx2d_fillText, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("measureText"), V8FUNCTION(ctx2d_measureText, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("strokeText"), V8FUNCTION(ctx2d_strokeText, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("drawImage"), V8FUNCTION(ctx2d_drawImage, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("createImageData"), V8FUNCTION(ctx2d_createImageData, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("getImageData"), V8FUNCTION(ctx2d_getImageData, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("putImageData"), V8FUNCTION(ctx2d_putImageData, engine));
-
- constructorContext = qPersistentNew(ft->GetFunction());
-
- v8::Local<v8::FunctionTemplate> ftGradient = v8::FunctionTemplate::New();
- ftGradient->InstanceTemplate()->SetHasExternalResource(true);
- ftGradient->PrototypeTemplate()->Set(v8::String::New("addColorStop"), V8FUNCTION(ctx2d_gradient_addColorStop, engine));
- constructorGradient = qPersistentNew(ftGradient->GetFunction());
-
- v8::Local<v8::FunctionTemplate> ftPattern = v8::FunctionTemplate::New();
- ftPattern->InstanceTemplate()->SetHasExternalResource(true);
- constructorPattern = qPersistentNew(ftPattern->GetFunction());
-
- v8::Local<v8::FunctionTemplate> ftPixelArray = v8::FunctionTemplate::New();
- ftPixelArray->InstanceTemplate()->SetHasExternalResource(true);
- ftPixelArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), ctx2d_pixelArray_length, 0, v8::External::Wrap(engine));
- ftPixelArray->InstanceTemplate()->SetIndexedPropertyHandler(ctx2d_pixelArray_indexed, ctx2d_pixelArray_indexed_set, 0, 0, 0, v8::External::Wrap(engine));
- constructorPixelArray = qPersistentNew(ftPixelArray->GetFunction());
-
- v8::Local<v8::FunctionTemplate> ftImageData = v8::FunctionTemplate::New();
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("width"), ctx2d_imageData_width, 0, v8::External::Wrap(engine));
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("height"), ctx2d_imageData_height, 0, v8::External::Wrap(engine));
- ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("data"), ctx2d_imageData_data, 0, v8::External::Wrap(engine));
- ftImageData->PrototypeTemplate()->Set(v8::String::New("mirror"), V8FUNCTION(ctx2d_imageData_mirror, engine));
- ftImageData->PrototypeTemplate()->Set(v8::String::New("filter"), V8FUNCTION(ctx2d_imageData_filter, engine));
- ftImageData->InstanceTemplate()->SetInternalFieldCount(1);
- constructorImageData = qPersistentNew(ftImageData->GetFunction());
-}
-
-QQuickContext2DEngineData::~QQuickContext2DEngineData()
-{
- qPersistentDispose(constructorContext);
- qPersistentDispose(constructorGradient);
- qPersistentDispose(constructorPattern);
- qPersistentDispose(constructorImageData);
- qPersistentDispose(constructorPixelArray);
-}
-
-void QQuickContext2D::popState()
-{
- if (m_stateStack.isEmpty())
- return;
-
- QQuickContext2D::State newState = m_stateStack.pop();
-
- if (state.matrix != newState.matrix)
- buffer()->updateMatrix(newState.matrix);
-
- if (newState.globalAlpha != state.globalAlpha)
- buffer()->setGlobalAlpha(newState.globalAlpha);
-
- if (newState.globalCompositeOperation != state.globalCompositeOperation)
- buffer()->setGlobalCompositeOperation(newState.globalCompositeOperation);
-
- if (newState.fillStyle != state.fillStyle)
- buffer()->setFillStyle(newState.fillStyle);
-
- if (newState.strokeStyle != state.strokeStyle)
- buffer()->setStrokeStyle(newState.strokeStyle);
-
- if (newState.lineWidth != state.lineWidth)
- buffer()->setLineWidth(newState.lineWidth);
-
- if (newState.lineCap != state.lineCap)
- buffer()->setLineCap(newState.lineCap);
-
- if (newState.lineJoin != state.lineJoin)
- buffer()->setLineJoin(newState.lineJoin);
-
- if (newState.miterLimit != state.miterLimit)
- buffer()->setMiterLimit(newState.miterLimit);
-
- if (newState.clipPath != state.clipPath) {
- buffer()->clip(newState.clipPath);
- }
-
- if (newState.shadowBlur != state.shadowBlur)
- buffer()->setShadowBlur(newState.shadowBlur);
-
- if (newState.shadowColor != state.shadowColor)
- buffer()->setShadowColor(newState.shadowColor);
-
- if (newState.shadowOffsetX != state.shadowOffsetX)
- buffer()->setShadowOffsetX(newState.shadowOffsetX);
-
- if (newState.shadowOffsetY != state.shadowOffsetY)
- buffer()->setShadowOffsetY(newState.shadowOffsetY);
- state = newState;
-}
-void QQuickContext2D::pushState()
-{
- m_stateStack.push(state);
-}
-
-void QQuickContext2D::reset()
-{
- QQuickContext2D::State newState;
- newState.matrix = QTransform();
-
- QPainterPath defaultClipPath;
-
- QRect r(0, 0, m_canvas->canvasSize().width(), m_canvas->canvasSize().height());
- r = r.united(m_canvas->canvasWindow().toRect());
- defaultClipPath.addRect(r);
- newState.clipPath = defaultClipPath;
- newState.clipPath.setFillRule(Qt::WindingFill);
-
- newState.strokeStyle = QColor("#000000");
- newState.fillStyle = QColor("#000000");
- newState.fillPatternRepeatX = false;
- newState.fillPatternRepeatY = false;
- newState.strokePatternRepeatX = false;
- newState.strokePatternRepeatY = false;
- newState.fillRule = Qt::WindingFill;
- newState.globalAlpha = 1.0;
- newState.lineWidth = 1;
- newState.lineCap = Qt::FlatCap;
- newState.lineJoin = Qt::MiterJoin;
- newState.miterLimit = 10;
- newState.shadowOffsetX = 0;
- newState.shadowOffsetY = 0;
- newState.shadowBlur = 0;
- newState.shadowColor = qRgba(0, 0, 0, 0);
- newState.globalCompositeOperation = QPainter::CompositionMode_SourceOver;
- newState.font = QFont(QLatin1String("sans-serif"), 10);
- newState.textAlign = QQuickContext2D::Start;
- newState.textBaseline = QQuickContext2D::Alphabetic;
-
- m_stateStack.clear();
- m_stateStack.push(newState);
- popState();
- m_buffer->clearRect(0, 0, m_canvas->width(), m_canvas->height());
-}
-
-void QQuickContext2D::setV8Engine(QV8Engine *engine)
-{
- v8::HandleScope handle_scope;
- v8::Context::Scope scope(engine->context());
-
- if (m_v8engine != engine) {
- m_v8engine = engine;
-
- qPersistentDispose(m_v8value);
-
- if (m_v8engine == 0)
- return;
-
- QQuickContext2DEngineData *ed = engineData(engine);
- m_v8value = qPersistentNew(ed->constructorContext->NewInstance());
- QV8Context2DResource *r = new QV8Context2DResource(engine);
- r->context = this;
- m_v8value->SetExternalResource(r);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/context2d/qquickcontext2d_p.h b/src/declarative/items/context2d/qquickcontext2d_p.h
deleted file mode 100644
index c5634d2b18..0000000000
--- a/src/declarative/items/context2d/qquickcontext2d_p.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCONTEXT2D_P_H
-#define QQUICKCONTEXT2D_P_H
-
-#include <QtDeclarative/qdeclarative.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-
-#include <QtGui/qpainter.h>
-#include <QtGui/qpainterpath.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qstack.h>
-#include <private/qv8engine_p.h>
-
-
-
-#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
-
-#ifdef QQUICKCONTEXT2D_DEBUG
-#include <QElapsedTimer>
-#endif
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickCanvasItem;
-class QQuickContext2DCommandBuffer;
-class QDeclarativePixmap;
-
-class Q_DECLARATIVE_EXPORT QQuickContext2D
-{
-public:
- enum TextBaseLineType { Alphabetic=0, Top, Middle, Bottom, Hanging};
- enum TextAlignType { Start=0, End, Left, Right, Center};
- enum PaintCommand {
- Invalid = 0,
- UpdateMatrix,
- ClearRect,
- FillRect,
- StrokeRect,
- Fill,
- Stroke,
- Clip,
- UpdateBrush,
- GlobalAlpha,
- GlobalCompositeOperation,
- StrokeStyle,
- FillStyle,
- LineWidth,
- LineCap,
- LineJoin,
- MiterLimit,
- ShadowOffsetX,
- ShadowOffsetY,
- ShadowBlur,
- ShadowColor,
- Font,
- TextBaseline,
- TextAlign,
- FillText,
- StrokeText,
- DrawImage,
- GetImageData
- };
-
-
- struct State {
- State()
- : strokeStyle(QColor("#000000"))
- , fillStyle(QColor("#000000"))
- , fillPatternRepeatX(false)
- , fillPatternRepeatY(false)
- , strokePatternRepeatX(false)
- , strokePatternRepeatY(false)
- , fillRule(Qt::WindingFill)
- , globalAlpha(1.0)
- , lineWidth(1)
- , lineCap(Qt::FlatCap)
- , lineJoin(Qt::MiterJoin)
- , miterLimit(10)
- , shadowOffsetX(0)
- , shadowOffsetY(0)
- , shadowBlur(0)
- , shadowColor(qRgba(0, 0, 0, 0))
- , globalCompositeOperation(QPainter::CompositionMode_SourceOver)
- , font(QFont(QLatin1String("sans-serif"), 10))
- , textAlign(QQuickContext2D::Start)
- , textBaseline(QQuickContext2D::Alphabetic)
- {
- }
-
- QTransform matrix;
- QPainterPath clipPath;
- QBrush strokeStyle;
- QBrush fillStyle;
- bool fillPatternRepeatX:1;
- bool fillPatternRepeatY:1;
- bool strokePatternRepeatX:1;
- bool strokePatternRepeatY:1;
- Qt::FillRule fillRule;
- qreal globalAlpha;
- qreal lineWidth;
- Qt::PenCapStyle lineCap;
- Qt::PenJoinStyle lineJoin;
- qreal miterLimit;
- qreal shadowOffsetX;
- qreal shadowOffsetY;
- qreal shadowBlur;
- QColor shadowColor;
- QPainter::CompositionMode globalCompositeOperation;
- QFont font;
- QQuickContext2D::TextAlignType textAlign;
- QQuickContext2D::TextBaseLineType textBaseline;
- };
-
- QQuickContext2D(QQuickCanvasItem* item);
- ~QQuickContext2D();
-
- inline QQuickCanvasItem* canvas() const {return m_canvas;}
- inline QQuickContext2DCommandBuffer* buffer() const {return m_buffer;}
-
- v8::Handle<v8::Object> v8value() const;
- void setV8Engine(QV8Engine *eng);
- void popState();
- void pushState();
- void reset();
-
- // path API
- void beginPath();
- void closePath();
- void moveTo(qreal x, qreal y);
- void lineTo(qreal x, qreal y);
- void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y);
- void bezierCurveTo(qreal cp1x, qreal cp1y,
- qreal cp2x, qreal cp2y, qreal x, qreal y);
- void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius);
- void rect(qreal x, qreal y, qreal w, qreal h);
- void roundedRect(qreal x, qreal y,qreal w, qreal h, qreal xr, qreal yr);
- void ellipse(qreal x, qreal y,qreal w, qreal h);
- void text(const QString& str, qreal x, qreal y);
- void arc(qreal x, qreal y, qreal radius,
- qreal startAngle, qreal endAngle,
- bool anticlockwise, bool transform=true);
- void addArcTo(const QPointF& p1, const QPointF& p2, float radius);
-
- bool isPointInPath(qreal x, qreal y) const;
-
- QPainterPath createTextGlyphs(qreal x, qreal y, const QString& text);
- QImage createImage(const QUrl& url);
-
- State state;
- QStack<QQuickContext2D::State> m_stateStack;
- QQuickCanvasItem* m_canvas;
- QQuickContext2DCommandBuffer* m_buffer;
- QPainterPath m_path;
- v8::Local<v8::Value> m_fillStyle;
- v8::Local<v8::Value> m_strokeStyle;
- v8::Handle<v8::Value> m_v8path;
- QV8Engine *m_v8engine;
- v8::Persistent<v8::Object> m_v8value;
-};
-
-
-QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickContext2D)
-
-QT_END_HEADER
-
-#endif // QQUICKCONTEXT2D_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/declarative/items/context2d/qquickcontext2dcommandbuffer_p.h
deleted file mode 100644
index 7deb2fbd6e..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCONTEXT2DCOMMANDBUFFER_P_H
-#define QQUICKCONTEXT2DCOMMANDBUFFER_P_H
-
-#include "qquickcontext2d_p.h"
-#include <private/qdeclarativepixmapcache_p.h>
-
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickCanvasItem;
-class QMutex;
-
-class QQuickContext2DCommandBuffer
-{
-public:
- QQuickContext2DCommandBuffer();
- ~QQuickContext2DCommandBuffer();
- void reset();
- void clear();
- inline int size() {return commands.size();}
- inline bool isEmpty() const {return commands.isEmpty(); }
- inline bool hasNext() const {return cmdIdx < commands.size(); }
- inline QQuickContext2D::PaintCommand takeNextCommand() { return commands[cmdIdx++]; }
-
- inline qreal takeGlobalAlpha() { return takeReal(); }
- inline QPainter::CompositionMode takeGlobalCompositeOperation(){ return static_cast<QPainter::CompositionMode>(takeInt()); }
- inline QBrush takeStrokeStyle() { return takeBrush(); }
- inline QBrush takeFillStyle() { return takeBrush(); }
-
- inline qreal takeLineWidth() { return takeReal(); }
- inline Qt::PenCapStyle takeLineCap() { return static_cast<Qt::PenCapStyle>(takeInt());}
- inline Qt::PenJoinStyle takeLineJoin(){ return static_cast<Qt::PenJoinStyle>(takeInt());}
- inline qreal takeMiterLimit() { return takeReal(); }
-
- inline void setGlobalAlpha( qreal alpha)
- {
- commands << QQuickContext2D::GlobalAlpha;
- reals << alpha;
- }
-
- inline void setGlobalCompositeOperation(QPainter::CompositionMode cm)
- {
- commands << QQuickContext2D::GlobalCompositeOperation;
- ints << cm;
- }
-
- inline void setStrokeStyle(const QBrush &style, bool repeatX = false, bool repeatY = false)
- {
- commands << QQuickContext2D::StrokeStyle;
- brushes << style;
- bools << repeatX << repeatY;
- }
-
- inline void drawImage(const QImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh)
- {
- commands << QQuickContext2D::DrawImage;
- images << image;
- reals << sx << sy << sw << sh << dx << dy << dw << dh;
- }
-
- inline qreal takeShadowOffsetX() { return takeReal(); }
- inline qreal takeShadowOffsetY() { return takeReal(); }
- inline qreal takeShadowBlur() { return takeReal(); }
- inline QColor takeShadowColor() { return takeColor(); }
-
-
- inline void updateMatrix(const QTransform& matrix)
- {
- commands << QQuickContext2D::UpdateMatrix;
- matrixes << matrix;
- }
-
- inline void clearRect(qreal x, qreal y, qreal w, qreal h)
- {
- commands << QQuickContext2D::ClearRect;
- reals << x << y << w << h;
- }
-
- inline void fillRect(qreal x, qreal y, qreal w, qreal h)
- {
- commands << QQuickContext2D::FillRect;
- reals << x << y << w << h;
- }
-
- inline void strokeRect(qreal x, qreal y, qreal w, qreal h)
- {
- QPainterPath p;
- p.addRect(x, y, w, h);
-
- commands << QQuickContext2D::Stroke;
- pathes << p;
- }
-
-
- inline void fill(const QPainterPath& path)
- {
- commands << QQuickContext2D::Fill;
- pathes << path;
-
- }
-
- inline void stroke(const QPainterPath& path)
- {
- commands << QQuickContext2D::Stroke;
- pathes << path;
- }
-
- inline void clip(const QPainterPath& path)
- {
- commands << QQuickContext2D::Clip;
- pathes << path;
- }
-
-
-
- inline void setFillStyle(const QBrush &style, bool repeatX = false, bool repeatY = false)
- {
- commands << QQuickContext2D::FillStyle;
- brushes << style;
- bools << repeatX << repeatY;
- }
-
-
- inline void setLineWidth( qreal w)
- {
- commands << QQuickContext2D::LineWidth;
- reals << w;
- }
-
- inline void setLineCap(Qt::PenCapStyle cap)
- {
- commands << QQuickContext2D::LineCap;
- ints << cap;
- }
-
- inline void setLineJoin(Qt::PenJoinStyle join)
- {
- commands << QQuickContext2D::LineJoin;
- ints << join;
- }
-
- inline void setMiterLimit( qreal limit)
- {
- commands << QQuickContext2D::MiterLimit;
- reals << limit;
- }
-
- inline void setShadowOffsetX( qreal x)
- {
- commands << QQuickContext2D::ShadowOffsetX;
- reals << x;
- }
-
- inline void setShadowOffsetY( qreal y)
- {
- commands << QQuickContext2D::ShadowOffsetY;
- reals << y;
- }
-
- inline void setShadowBlur( qreal b)
- {
- commands << QQuickContext2D::ShadowBlur;
- reals << b;
- }
-
- inline void setShadowColor(const QColor &color)
- {
- commands << QQuickContext2D::ShadowColor;
- colors << color;
- }
-
- inline QTransform takeMatrix() { return matrixes[matrixIdx++]; }
-
- // rects
- inline QRectF takeRect() {
- qreal x, y, w, h;
- x = takeReal();
- y = takeReal();
- w = takeReal();
- h = takeReal();
- return QRectF(x, y, w ,h);
- }
-
- inline QPainterPath takePath() { return pathes[pathIdx++]; }
-
- inline const QImage& takeImage() { return images[imageIdx++]; }
-
- inline int takeInt() { return ints[intIdx++]; }
- inline bool takeBool() {return bools[boolIdx++]; }
- inline qreal takeReal() { return reals[realIdx++]; }
- inline QColor takeColor() { return colors[colorIdx++]; }
- inline QBrush takeBrush() { return brushes[brushIdx++]; }
-
- void replay(QPainter* painter, QQuickContext2D::State& state);
-private:
- QPen makePen(const QQuickContext2D::State& state);
- void setPainterState(QPainter* painter, const QQuickContext2D::State& state, const QPen& pen);
- int cmdIdx;
- int intIdx;
- int boolIdx;
- int realIdx;
- int colorIdx;
- int matrixIdx;
- int brushIdx;
- int pathIdx;
- int imageIdx;
- QVector<QQuickContext2D::PaintCommand> commands;
-
- QVector<int> ints;
- QVector<bool> bools;
- QVector<qreal> reals;
- QVector<QColor> colors;
- QVector<QTransform> matrixes;
- QVector<QBrush> brushes;
- QVector<QPainterPath> pathes;
- QVector<QImage> images;
-};
-
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // QQUICKCONTEXT2DCOMMANDBUFFER_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dnode.cpp b/src/declarative/items/context2d/qquickcontext2dnode.cpp
deleted file mode 100644
index 76b50d9747..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dnode.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickcontext2dnode_p.h"
-
-#include <private/qsgcontext_p.h>
-#include <QtCore/qmath.h>
-
-QT_BEGIN_NAMESPACE
-
-
-QQuickContext2DNode::QQuickContext2DNode(QQuickCanvasItem* item)
- : QSGGeometryNode()
- , m_item(item)
- , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- , m_texture(0)
- , m_size(1, 1)
- , m_dirtyGeometry(false)
- , m_dirtyTexture(false)
-{
- setMaterial(&m_materialO);
- setOpaqueMaterial(&m_material);
- setGeometry(&m_geometry);
- setFlag(UsePreprocess, true);
-}
-
-QQuickContext2DNode::~QQuickContext2DNode()
-{
- delete m_texture;
-}
-
-void QQuickContext2DNode::setSize(const QSizeF& size)
-{
- if (m_size != size) {
- m_dirtyGeometry = true;
- m_size = size;
- }
-}
-
-void QQuickContext2DNode::preprocess()
-{
- bool doDirty = false;
- QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
- if (t) {
- doDirty = t->updateTexture();
- }
- if (doDirty) {
- m_dirtyTexture = true;
- markDirty(DirtyMaterial);
- }
-}
-void QQuickContext2DNode::setTexture(QQuickContext2DTexture* texture)
-{
- if (texture != m_texture) {
- m_dirtyTexture = true;
- m_texture = texture;
- }
-}
-
-void QQuickContext2DNode::update()
-{
- if (m_dirtyGeometry)
- updateGeometry();
- if (m_dirtyTexture)
- updateTexture();
-
- m_dirtyGeometry = false;
- m_dirtyTexture = false;
-}
-
-void QQuickContext2DNode::updateTexture()
-{
- m_material.setTexture(m_texture);
- m_materialO.setTexture(m_texture);
- markDirty(DirtyMaterial);
-}
-
-void QQuickContext2DNode::updateGeometry()
-{
- QRectF source = m_texture->textureSubRect();
- QSGGeometry::updateTexturedRectGeometry(&m_geometry,
- QRectF(0, 0, m_size.width(), m_size.height()),
- source);
- markDirty(DirtyGeometry);
-}
-QT_END_NAMESPACE
diff --git a/src/declarative/items/context2d/qquickcontext2dnode_p.h b/src/declarative/items/context2d/qquickcontext2dnode_p.h
deleted file mode 100644
index 7403acaf07..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dnode_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCONTEXT2DNODE_P_H
-#define QQUICKCONTEXT2DNODE_P_H
-
-#include <qsgnode.h>
-#include <qsgtexturematerial.h>
-
-#include "qquickcanvasitem_p.h"
-#include "qquickcontext2dtexture_p.h"
-#include "qquickcontext2d_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickContext2DNode : public QSGGeometryNode
-{
-public:
- QQuickContext2DNode(QQuickCanvasItem* item);
- virtual ~QQuickContext2DNode();
- void setTexture(QQuickContext2DTexture* texture);
- void update();
- void preprocess();
- void setSize(const QSizeF& size);
-private:
- void updateTexture();
- void updateGeometry();
-
- QQuickCanvasItem* m_item;
- QSGOpaqueTextureMaterial m_material;
- QSGTextureMaterial m_materialO;
- QSGGeometry m_geometry;
- QQuickContext2DTexture* m_texture;
- QSizeF m_size;
-
- bool m_dirtyGeometry;
- bool m_dirtyTexture;
-};
-
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // QQUICKCONTEXT2DNODE_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dtexture.cpp b/src/declarative/items/context2d/qquickcontext2dtexture.cpp
deleted file mode 100644
index 1128fa224f..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dtexture.cpp
+++ /dev/null
@@ -1,778 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickcontext2dtexture_p.h"
-#include "qquickcontext2dtile_p.h"
-#include "qquickcanvasitem_p.h"
-#include <private/qquickitem_p.h>
-#include <private/qsgtexture_p.h>
-#include "qquickcontext2dcommandbuffer_p.h"
-#include <QOpenGLPaintDevice>
-
-#include <QOpenGLFramebufferObject>
-#include <QOpenGLFramebufferObjectFormat>
-#include <QtCore/QThread>
-
-#define QT_MINIMUM_FBO_SIZE 64
-
-static inline int qt_next_power_of_two(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
-
-Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance)
-
-
-QQuickContext2DTexture::QQuickContext2DTexture()
- : QSGDynamicTexture()
- , m_context(0)
- , m_item(0)
- , m_canvasSize(QSize(1, 1))
- , m_tileSize(QSize(1, 1))
- , m_canvasWindow(QRect(0, 0, 1, 1))
- , m_dirtyCanvas(false)
- , m_dirtyTexture(false)
- , m_threadRendering(false)
- , m_smooth(false)
- , m_tiledCanvas(false)
- , m_doGrabImage(false)
- , m_painting(false)
-{
-}
-
-QQuickContext2DTexture::~QQuickContext2DTexture()
-{
- clearTiles();
-}
-
-QSize QQuickContext2DTexture::textureSize() const
-{
- return m_canvasWindow.size();
-}
-
-void QQuickContext2DTexture::markDirtyTexture()
-{
- lock();
- m_dirtyTexture = true;
- unlock();
- emit textureChanged();
-}
-
-bool QQuickContext2DTexture::setCanvasSize(const QSize &size)
-{
- if (m_canvasSize != size) {
- m_canvasSize = size;
- m_dirtyCanvas = true;
- return true;
- }
- return false;
-}
-
-bool QQuickContext2DTexture::setTileSize(const QSize &size)
-{
- if (m_tileSize != size) {
- m_tileSize = size;
- m_dirtyCanvas = true;
- return true;
- }
- return false;
-}
-
-void QQuickContext2DTexture::setSmooth(bool smooth)
-{
- m_smooth = smooth;
-}
-
-void QQuickContext2DTexture::setItem(QQuickCanvasItem* item)
-{
- if (!item) {
- lock();
- m_item = 0;
- m_context = 0;
- unlock();
- wake();
- } else if (m_item != item) {
- lock();
- m_item = item;
- m_context = item->context();
- m_state = m_context->state;
- unlock();
- connect(this, SIGNAL(textureChanged()), m_item, SIGNAL(painted()));
- }
-}
-
-bool QQuickContext2DTexture::setCanvasWindow(const QRect& r)
-{
- if (m_canvasWindow != r) {
- m_canvasWindow = r;
- return true;
- }
- return false;
-}
-
-bool QQuickContext2DTexture::setDirtyRect(const QRect &r)
-{
- bool doDirty = false;
- if (m_tiledCanvas) {
- foreach (QQuickContext2DTile* t, m_tiles) {
- bool dirty = t->rect().intersected(r).isValid();
- t->markDirty(dirty);
- if (dirty)
- doDirty = true;
- }
- } else {
- doDirty = m_canvasWindow.intersected(r).isValid();
- }
- return doDirty;
-}
-
-void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth)
-{
- lock();
-
- QSize ts = tileSize;
- if (ts.width() > canvasSize.width())
- ts.setWidth(canvasSize.width());
-
- if (ts.height() > canvasSize.height())
- ts.setHeight(canvasSize.height());
-
- setCanvasSize(canvasSize);
- setTileSize(ts);
-
- if (canvasSize == canvasWindow.size()) {
- m_tiledCanvas = false;
- m_dirtyCanvas = false;
- } else {
- m_tiledCanvas = true;
- }
-
- bool doDirty = false;
- if (dirtyRect.isValid())
- doDirty = setDirtyRect(dirtyRect);
-
- bool windowChanged = setCanvasWindow(canvasWindow);
- if (windowChanged || doDirty) {
- if (m_threadRendering)
- QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
- else if (supportDirectRendering()) {
- QMetaObject::invokeMethod(this, "paint", Qt::DirectConnection);
- }
- }
-
- setSmooth(smooth);
- unlock();
-}
-
-void QQuickContext2DTexture::paintWithoutTiles()
-{
- QQuickContext2DCommandBuffer* ccb = m_context->buffer();
-
- if (ccb->isEmpty() && m_threadRendering && !m_doGrabImage) {
- lock();
- if (m_item)
- QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, QRectF(0, 0, m_canvasSize.width(), m_canvasSize.height())));
- wait();
- unlock();
- }
- if (ccb->isEmpty()) {
- return;
- }
-
- QPaintDevice* device = beginPainting();
- if (!device) {
- endPainting();
- return;
- }
-
- QPainter p;
- p.begin(device);
- if (m_smooth)
- p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
- | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
- else
- p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
- | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, false);
- p.setCompositionMode(QPainter::CompositionMode_SourceOver);
- ccb->replay(&p, m_state);
-
- ccb->clear();
- markDirtyTexture();
- endPainting();
-}
-
-bool QQuickContext2DTexture::canvasDestroyed()
-{
- bool noCanvas = false;
- lock();
- noCanvas = m_item == 0;
- unlock();
- return noCanvas;
-}
-
-void QQuickContext2DTexture::paint()
-{
- if (canvasDestroyed())
- return;
-
- if (!m_tiledCanvas) {
- paintWithoutTiles();
- } else {
- lock();
- QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize)));
- unlock();
-
- if (!tiledRegion.isEmpty()) {
- if (m_threadRendering && !m_doGrabImage) {
- QRect dirtyRect;
-
- lock();
- foreach (QQuickContext2DTile* tile, m_tiles) {
- if (tile->dirty()) {
- if (dirtyRect.isEmpty())
- dirtyRect = tile->rect();
- else
- dirtyRect |= tile->rect();
- }
- }
- unlock();
-
- if (dirtyRect.isValid()) {
- lock();
- if (m_item)
- QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, dirtyRect));
- wait();
- unlock();
- }
- }
-
- if (beginPainting()) {
- QQuickContext2D::State oldState = m_state;
- QQuickContext2DCommandBuffer* ccb = m_context->buffer();
- foreach (QQuickContext2DTile* tile, m_tiles) {
- bool dirtyTile = false, dirtyCanvas = false, smooth = false;
-
- lock();
- dirtyTile = tile->dirty();
- smooth = m_smooth;
- dirtyCanvas = m_dirtyCanvas;
- unlock();
-
- //canvas size or tile size may change during painting tiles
- if (dirtyCanvas) {
- if (m_threadRendering)
- QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
- endPainting();
- return;
- } else if (dirtyTile) {
- ccb->replay(tile->createPainter(smooth), oldState);
- tile->drawFinished();
- lock();
- tile->markDirty(false);
- unlock();
- }
-
- compositeTile(tile);
- }
- ccb->clear();
- endPainting();
- m_state = oldState;
- markDirtyTexture();
- }
- }
- }
-}
-
-QRect QQuickContext2DTexture::tiledRect(const QRectF& window, const QSize& tileSize)
-{
- if (window.isEmpty())
- return QRect();
-
- const int tw = tileSize.width();
- const int th = tileSize.height();
- const int h1 = window.left() / tw;
- const int v1 = window.top() / th;
-
- const int htiles = ((window.right() - h1 * tw) + tw - 1)/tw;
- const int vtiles = ((window.bottom() - v1 * th) + th - 1)/th;
-
- return QRect(h1 * tw, v1 * th, htiles * tw, vtiles * th);
-}
-
-QRect QQuickContext2DTexture::createTiles(const QRect& window)
-{
- QList<QQuickContext2DTile*> oldTiles = m_tiles;
- m_tiles.clear();
-
- if (window.isEmpty()) {
- m_dirtyCanvas = false;
- return QRect();
- }
-
- QRect r = tiledRect(window, m_tileSize);
-
- const int tw = m_tileSize.width();
- const int th = m_tileSize.height();
- const int h1 = window.left() / tw;
- const int v1 = window.top() / th;
-
-
- const int htiles = r.width() / tw;
- const int vtiles = r.height() / th;
-
- for (int yy = 0; yy < vtiles; ++yy) {
- for (int xx = 0; xx < htiles; ++xx) {
- int ht = xx + h1;
- int vt = yy + v1;
-
- QQuickContext2DTile* tile = 0;
-
- QPoint pos(ht * tw, vt * th);
- QRect rect(pos, m_tileSize);
-
- for (int i = 0; i < oldTiles.size(); i++) {
- if (oldTiles[i]->rect() == rect) {
- tile = oldTiles.takeAt(i);
- break;
- }
- }
-
- if (!tile)
- tile = createTile();
-
- tile->setRect(rect);
- m_tiles.append(tile);
- }
- }
-
- qDeleteAll(oldTiles);
-
- m_dirtyCanvas = false;
- return r;
-}
-
-void QQuickContext2DTexture::clearTiles()
-{
- qDeleteAll(m_tiles);
- m_tiles.clear();
-}
-
-QQuickContext2DFBOTexture::QQuickContext2DFBOTexture()
- : QQuickContext2DTexture()
- , m_fbo(0)
- , m_multisampledFbo(0)
- , m_paint_device(0)
-{
- m_threadRendering = false;
-}
-
-QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture()
-{
- delete m_fbo;
- delete m_multisampledFbo;
- delete m_paint_device;
-}
-
-bool QQuickContext2DFBOTexture::setCanvasSize(const QSize &size)
-{
- QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
- , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
-
- if (m_canvasSize != s) {
- m_canvasSize = s;
- m_dirtyCanvas = true;
- return true;
- }
- return false;
-}
-
-bool QQuickContext2DFBOTexture::setTileSize(const QSize &size)
-{
- QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
- , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
- if (m_tileSize != s) {
- m_tileSize = s;
- m_dirtyCanvas = true;
- return true;
- }
- return false;
-}
-
-bool QQuickContext2DFBOTexture::setCanvasWindow(const QRect& canvasWindow)
-{
- QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().width()))
- , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().height())));
-
-
- bool doChanged = false;
- if (m_fboSize != s) {
- m_fboSize = s;
- doChanged = true;
- }
-
- if (m_canvasWindow != canvasWindow)
- m_canvasWindow = canvasWindow;
-
- return doChanged;
-}
-
-void QQuickContext2DFBOTexture::bind()
-{
- glBindTexture(GL_TEXTURE_2D, textureId());
- updateBindOptions();
-}
-
-QRectF QQuickContext2DFBOTexture::textureSubRect() const
-{
- return QRectF(0
- , 0
- , qreal(m_canvasWindow.width()) / m_fboSize.width()
- , qreal(m_canvasWindow.height()) / m_fboSize.height());
-}
-
-
-int QQuickContext2DFBOTexture::textureId() const
-{
- return m_fbo? m_fbo->texture() : 0;
-}
-
-
-bool QQuickContext2DFBOTexture::updateTexture()
-{
- if (!m_context->buffer()->isEmpty()) {
- paint();
- }
-
- bool textureUpdated = m_dirtyTexture;
-
- m_dirtyTexture = false;
-
- if (m_doGrabImage) {
- grabImage();
- m_condition.wakeOne();
- m_doGrabImage = false;
- }
- return textureUpdated;
-}
-
-QQuickContext2DTile* QQuickContext2DFBOTexture::createTile() const
-{
- return new QQuickContext2DFBOTile();
-}
-
-void QQuickContext2DFBOTexture::grabImage()
-{
- if (m_fbo) {
- m_grabedImage = m_fbo->toImage();
- }
-}
-
-bool QQuickContext2DFBOTexture::doMultisampling() const
-{
- static bool extensionsChecked = false;
- static bool multisamplingSupported = false;
-
- if (!extensionsChecked) {
- QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
- multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample")
- && extensions.contains("GL_EXT_framebuffer_blit");
- extensionsChecked = true;
- }
-
- return multisamplingSupported && m_smooth;
-}
-
-QImage QQuickContext2DFBOTexture::toImage(const QRectF& region)
-{
-#define QML_CONTEXT2D_WAIT_MAX 5000
-
- m_doGrabImage = true;
- if (m_item)
- m_item->update();
-
- QImage grabbed;
- m_mutex.lock();
- bool ok = m_condition.wait(&m_mutex, QML_CONTEXT2D_WAIT_MAX);
-
- if (!ok)
- grabbed = QImage();
-
- if (region.isValid())
- grabbed = m_grabedImage.copy(region.toRect());
- else
- grabbed = m_grabedImage;
- m_grabedImage = QImage();
- return grabbed;
-}
-
-void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile)
-{
- QQuickContext2DFBOTile* t = static_cast<QQuickContext2DFBOTile*>(tile);
- QRect target = t->rect().intersect(m_canvasWindow);
- if (target.isValid()) {
- QRect source = target;
-
- source.moveTo(source.topLeft() - t->rect().topLeft());
- target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
-
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, target, t->fbo(), source);
- }
-}
-QQuickCanvasItem::RenderTarget QQuickContext2DFBOTexture::renderTarget() const
-{
- return QQuickCanvasItem::FramebufferObject;
-}
-QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
-{
- QQuickContext2DTexture::beginPainting();
-
- if (m_canvasWindow.size().isEmpty() && !m_threadRendering) {
- delete m_fbo;
- delete m_multisampledFbo;
- m_fbo = 0;
- m_multisampledFbo = 0;
- return 0;
- } else if (!m_fbo || m_fbo->size() != m_fboSize) {
- delete m_fbo;
- delete m_multisampledFbo;
- if (doMultisampling()) {
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setSamples(8);
- m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
- m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- } else {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
-
- m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- }
-
- if (doMultisampling())
- m_multisampledFbo->bind();
- else
- m_fbo->bind();
-
-
- if (!m_paint_device) {
- QOpenGLPaintDevice *gl_device = new QOpenGLPaintDevice(m_fbo->size());
- gl_device->setPaintFlipped(true);
- m_paint_device = gl_device;
- }
-
- return m_paint_device;
-}
-
-void QQuickContext2DFBOTexture::endPainting()
-{
- QQuickContext2DTexture::endPainting();
- if (m_multisampledFbo) {
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo);
- m_multisampledFbo->release();
- } else if (m_fbo)
- m_fbo->release();
-}
-void qt_quit_context2d_render_thread()
-{
- QThread* thread = globalCanvasThreadRenderInstance();
-
- if (thread->isRunning()) {
- thread->exit(0);
- thread->wait(1000);
- }
-}
-
-QQuickContext2DImageTexture::QQuickContext2DImageTexture(bool threadRendering)
- : QQuickContext2DTexture()
- , m_texture(new QSGPlainTexture())
-{
- m_texture->setOwnsTexture(true);
- m_texture->setHasMipmaps(false);
-
- m_threadRendering = threadRendering;
-
- if (m_threadRendering) {
- QThread* thread = globalCanvasThreadRenderInstance();
- moveToThread(thread);
-
- if (!thread->isRunning()) {
- qAddPostRoutine(qt_quit_context2d_render_thread);
- thread->start();
- }
- }
-}
-
-QQuickContext2DImageTexture::~QQuickContext2DImageTexture()
-{
- delete m_texture;
-}
-
-int QQuickContext2DImageTexture::textureId() const
-{
- return m_texture->textureId();
-}
-
-void QQuickContext2DImageTexture::lock()
-{
- if (m_threadRendering)
- m_mutex.lock();
-}
-void QQuickContext2DImageTexture::unlock()
-{
- if (m_threadRendering)
- m_mutex.unlock();
-}
-
-void QQuickContext2DImageTexture::wait()
-{
- if (m_threadRendering)
- m_waitCondition.wait(&m_mutex);
-}
-
-void QQuickContext2DImageTexture::wake()
-{
- if (m_threadRendering)
- m_waitCondition.wakeOne();
-}
-
-bool QQuickContext2DImageTexture::supportDirectRendering() const
-{
- return !m_threadRendering;
-}
-
-QQuickCanvasItem::RenderTarget QQuickContext2DImageTexture::renderTarget() const
-{
- return QQuickCanvasItem::Image;
-}
-
-void QQuickContext2DImageTexture::bind()
-{
- m_texture->bind();
-}
-
-bool QQuickContext2DImageTexture::updateTexture()
-{
- lock();
- bool textureUpdated = m_dirtyTexture;
- if (m_dirtyTexture) {
- m_texture->setImage(m_image);
- m_dirtyTexture = false;
- }
- unlock();
- return textureUpdated;
-}
-
-QQuickContext2DTile* QQuickContext2DImageTexture::createTile() const
-{
- return new QQuickContext2DImageTile();
-}
-
-void QQuickContext2DImageTexture::grabImage(const QRect& r)
-{
- m_doGrabImage = true;
- paint();
- m_doGrabImage = false;
- m_grabedImage = m_image.copy(r);
-}
-
-QImage QQuickContext2DImageTexture::toImage(const QRectF& region)
-{
- QRect r = region.isValid() ? region.toRect() : QRect(QPoint(0, 0), m_canvasWindow.size());
- if (threadRendering()) {
- wake();
- QMetaObject::invokeMethod(this, "grabImage", Qt::BlockingQueuedConnection, Q_ARG(QRect, r));
- } else {
- QMetaObject::invokeMethod(this, "grabImage", Qt::DirectConnection, Q_ARG(QRect, r));
- }
- QImage image = m_grabedImage;
- m_grabedImage = QImage();
- return image;
-}
-
-QPaintDevice* QQuickContext2DImageTexture::beginPainting()
-{
- QQuickContext2DTexture::beginPainting();
-
- if (m_canvasWindow.size().isEmpty())
- return 0;
-
- lock();
- if (m_image.size() != m_canvasWindow.size()) {
- m_image = QImage(m_canvasWindow.size(), QImage::Format_ARGB32_Premultiplied);
- m_image.fill(0x00000000);
- }
- unlock();
- return &m_image;
-}
-
-void QQuickContext2DImageTexture::compositeTile(QQuickContext2DTile* tile)
-{
- Q_ASSERT(!tile->dirty());
- QQuickContext2DImageTile* t = static_cast<QQuickContext2DImageTile*>(tile);
- QRect target = t->rect().intersect(m_canvasWindow);
- if (target.isValid()) {
- QRect source = target;
- source.moveTo(source.topLeft() - t->rect().topLeft());
- target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
-
- lock();
- m_painter.begin(&m_image);
- m_painter.setCompositionMode(QPainter::CompositionMode_Source);
- m_painter.drawImage(target, t->image(), source);
- m_painter.end();
- unlock();
- }
-}
diff --git a/src/declarative/items/context2d/qquickcontext2dtexture_p.h b/src/declarative/items/context2d/qquickcontext2dtexture_p.h
deleted file mode 100644
index ed45a09f7c..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dtexture_p.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCONTEXT2DTEXTURE_P_H
-#define QQUICKCONTEXT2DTEXTURE_P_H
-
-#include <qsgtexture.h>
-#include "qquickcanvasitem_p.h"
-#include "qquickcontext2d_p.h"
-
-#include <QOpenGLContext>
-#include <QOpenGLFramebufferObject>
-
-#include <QtCore/QMutex>
-#include <QtCore/QWaitCondition>
-#include <QtCore/QThread>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickContext2DTile;
-class QQuickContext2DCommandBuffer;
-
-class QQuickContext2DTexture : public QSGDynamicTexture
-{
- Q_OBJECT
-public:
- QQuickContext2DTexture();
- ~QQuickContext2DTexture();
-
- virtual bool hasAlphaChannel() const {return true;}
- virtual bool hasMipmaps() const {return false;}
- virtual QSize textureSize() const;
- virtual void lock() {}
- virtual void unlock() {}
- virtual void wait() {}
- virtual void wake() {}
- bool threadRendering() const {return m_threadRendering;}
- virtual bool supportThreadRendering() const = 0;
- virtual bool supportDirectRendering() const = 0;
- virtual QQuickCanvasItem::RenderTarget renderTarget() const = 0;
- virtual QImage toImage(const QRectF& region = QRectF()) = 0;
- static QRect tiledRect(const QRectF& window, const QSize& tileSize);
-
- virtual bool setCanvasSize(const QSize &size);
- virtual bool setTileSize(const QSize &size);
- virtual bool setCanvasWindow(const QRect& canvasWindow);
- void setSmooth(bool smooth);
- bool setDirtyRect(const QRect &dirtyRect);
- virtual void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
- bool canvasDestroyed();
-Q_SIGNALS:
- void textureChanged();
-
-public Q_SLOTS:
- void markDirtyTexture();
- void setItem(QQuickCanvasItem* item);
- void paint();
-
-protected:
- void paintWithoutTiles();
- virtual QPaintDevice* beginPainting() {m_painting = true; return 0; }
- virtual void endPainting() {m_painting = false;}
- virtual QQuickContext2DTile* createTile() const = 0;
- virtual void compositeTile(QQuickContext2DTile* tile) = 0;
-
- void clearTiles();
- QRect createTiles(const QRect& window);
-
- QList<QQuickContext2DTile*> m_tiles;
- QQuickContext2D* m_context;
-
- QQuickContext2D::State m_state;
-
- QQuickCanvasItem* m_item;
- QSize m_canvasSize;
- QSize m_tileSize;
- QRect m_canvasWindow;
-
- uint m_dirtyCanvas : 1;
- uint m_dirtyTexture : 1;
- uint m_threadRendering : 1;
- uint m_smooth : 1;
- uint m_tiledCanvas : 1;
- uint m_doGrabImage : 1;
- uint m_painting : 1;
-};
-
-class QQuickContext2DFBOTexture : public QQuickContext2DTexture
-{
- Q_OBJECT
-
-public:
- QQuickContext2DFBOTexture();
- ~QQuickContext2DFBOTexture();
- virtual int textureId() const;
- virtual bool updateTexture();
- virtual QQuickContext2DTile* createTile() const;
- virtual QImage toImage(const QRectF& region = QRectF());
- virtual QPaintDevice* beginPainting();
- virtual void endPainting();
- QRectF textureSubRect() const;
- virtual bool supportThreadRendering() const {return false;}
- virtual bool supportDirectRendering() const {return false;}
- virtual QQuickCanvasItem::RenderTarget renderTarget() const;
- virtual void compositeTile(QQuickContext2DTile* tile);
- virtual void bind();
- virtual bool setCanvasSize(const QSize &size);
- virtual bool setTileSize(const QSize &size);
- virtual bool setCanvasWindow(const QRect& canvasWindow);
-private Q_SLOTS:
- void grabImage();
-
-private:
- bool doMultisampling() const;
- QImage m_grabedImage;
- QOpenGLFramebufferObject *m_fbo;
- QOpenGLFramebufferObject *m_multisampledFbo;
- QMutex m_mutex;
- QWaitCondition m_condition;
- QSize m_fboSize;
- QPaintDevice *m_paint_device;
-};
-
-class QSGPlainTexture;
-class QQuickContext2DImageTexture : public QQuickContext2DTexture
-{
- Q_OBJECT
-
-public:
- QQuickContext2DImageTexture(bool threadRendering = true);
- ~QQuickContext2DImageTexture();
- virtual int textureId() const;
- virtual void bind();
- virtual bool supportThreadRendering() const {return true;}
- virtual bool supportDirectRendering() const;
- virtual QQuickCanvasItem::RenderTarget renderTarget() const;
- virtual void lock();
- virtual void unlock();
- virtual void wait();
- virtual void wake();
-
- virtual bool updateTexture();
- virtual QQuickContext2DTile* createTile() const;
- virtual QImage toImage(const QRectF& region = QRectF());
- virtual QPaintDevice* beginPainting();
- virtual void compositeTile(QQuickContext2DTile* tile);
-
-private Q_SLOTS:
- void grabImage(const QRect& r);
-private:
- QImage m_image;
- QImage m_grabedImage;
- QMutex m_mutex;
- QWaitCondition m_waitCondition;
- QPainter m_painter;
- QSGPlainTexture* m_texture;
-};
-
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // QQUICKCONTEXT2DTEXTURE_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dtile_p.h b/src/declarative/items/context2d/qquickcontext2dtile_p.h
deleted file mode 100644
index 92c59efbcf..0000000000
--- a/src/declarative/items/context2d/qquickcontext2dtile_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCONTEXT2DTILE_P_H
-#define QQUICKCONTEXT2DTILE_P_H
-
-#include "qquickcontext2d_p.h"
-#include <QOpenGLFramebufferObject>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickContext2DTexture;
-class QQuickContext2DCommandBuffer;
-
-class QQuickContext2DTile
-{
-public:
- QQuickContext2DTile();
- ~QQuickContext2DTile();
-
- bool dirty() const {return m_dirty;}
- void markDirty(bool dirty) {m_dirty = dirty;}
-
- QRect rect() const {return m_rect;}
-
- virtual void setRect(const QRect& r) = 0;
- virtual QPainter* createPainter(bool smooth = false);
- virtual void drawFinished() {}
-
-protected:
- virtual void aboutToDraw() {}
- uint m_dirty : 1;
- QRect m_rect;
- QPaintDevice* m_device;
- QPainter m_painter;
-};
-
-
-class QQuickContext2DFBOTile : public QQuickContext2DTile
-{
-public:
- QQuickContext2DFBOTile();
- ~QQuickContext2DFBOTile();
- virtual void setRect(const QRect& r);
- QOpenGLFramebufferObject* fbo() const {return m_fbo;}
- void drawFinished();
-
-protected:
- void aboutToDraw();
-private:
-
-
- QOpenGLFramebufferObject *m_fbo;
-};
-
-class QQuickContext2DImageTile : public QQuickContext2DTile
-{
-public:
- QQuickContext2DImageTile();
- ~QQuickContext2DImageTile();
- void setRect(const QRect& r);
- const QImage& image() const {return m_image;}
-private:
- QImage m_image;
-};
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // QQUICKCONTEXT2DTILE_P_H
diff --git a/src/declarative/items/qquickanchors_p.h b/src/declarative/items/qquickanchors_p.h
deleted file mode 100644
index 5c66c2e17d..0000000000
--- a/src/declarative/items/qquickanchors_p.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKANCHORS_P_H
-#define QQUICKANCHORS_P_H
-
-#include <qdeclarative.h>
-
-#include <QtCore/QObject>
-
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QQuickAnchorsPrivate;
-class QQuickAnchorLine;
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickAnchors : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QQuickAnchorLine left READ left WRITE setLeft RESET resetLeft NOTIFY leftChanged)
- Q_PROPERTY(QQuickAnchorLine right READ right WRITE setRight RESET resetRight NOTIFY rightChanged)
- Q_PROPERTY(QQuickAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter NOTIFY horizontalCenterChanged)
- Q_PROPERTY(QQuickAnchorLine top READ top WRITE setTop RESET resetTop NOTIFY topChanged)
- Q_PROPERTY(QQuickAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom NOTIFY bottomChanged)
- Q_PROPERTY(QQuickAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged)
- Q_PROPERTY(QQuickAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline NOTIFY baselineChanged)
- Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
- Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
- Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
- Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged)
- Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
- Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
- Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged)
- Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
- Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
- Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
- Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged)
-
-public:
- QQuickAnchors(QQuickItem *item, QObject *parent=0);
- virtual ~QQuickAnchors();
-
- enum Anchor {
- LeftAnchor = 0x01,
- RightAnchor = 0x02,
- TopAnchor = 0x04,
- BottomAnchor = 0x08,
- HCenterAnchor = 0x10,
- VCenterAnchor = 0x20,
- BaselineAnchor = 0x40,
- Horizontal_Mask = LeftAnchor | RightAnchor | HCenterAnchor,
- Vertical_Mask = TopAnchor | BottomAnchor | VCenterAnchor | BaselineAnchor
- };
- Q_DECLARE_FLAGS(Anchors, Anchor)
-
- QQuickAnchorLine left() const;
- void setLeft(const QQuickAnchorLine &edge);
- void resetLeft();
-
- QQuickAnchorLine right() const;
- void setRight(const QQuickAnchorLine &edge);
- void resetRight();
-
- QQuickAnchorLine horizontalCenter() const;
- void setHorizontalCenter(const QQuickAnchorLine &edge);
- void resetHorizontalCenter();
-
- QQuickAnchorLine top() const;
- void setTop(const QQuickAnchorLine &edge);
- void resetTop();
-
- QQuickAnchorLine bottom() const;
- void setBottom(const QQuickAnchorLine &edge);
- void resetBottom();
-
- QQuickAnchorLine verticalCenter() const;
- void setVerticalCenter(const QQuickAnchorLine &edge);
- void resetVerticalCenter();
-
- QQuickAnchorLine baseline() const;
- void setBaseline(const QQuickAnchorLine &edge);
- void resetBaseline();
-
- qreal leftMargin() const;
- void setLeftMargin(qreal);
-
- qreal rightMargin() const;
- void setRightMargin(qreal);
-
- qreal horizontalCenterOffset() const;
- void setHorizontalCenterOffset(qreal);
-
- qreal topMargin() const;
- void setTopMargin(qreal);
-
- qreal bottomMargin() const;
- void setBottomMargin(qreal);
-
- qreal margins() const;
- void setMargins(qreal);
-
- qreal verticalCenterOffset() const;
- void setVerticalCenterOffset(qreal);
-
- qreal baselineOffset() const;
- void setBaselineOffset(qreal);
-
- QQuickItem *fill() const;
- void setFill(QQuickItem *);
- void resetFill();
-
- QQuickItem *centerIn() const;
- void setCenterIn(QQuickItem *);
- void resetCenterIn();
-
- Anchors usedAnchors() const;
-
- bool mirrored();
-
- void classBegin();
- void componentComplete();
-
-Q_SIGNALS:
- void leftChanged();
- void rightChanged();
- void topChanged();
- void bottomChanged();
- void verticalCenterChanged();
- void horizontalCenterChanged();
- void baselineChanged();
- void fillChanged();
- void centerInChanged();
- void leftMarginChanged();
- void rightMarginChanged();
- void topMarginChanged();
- void bottomMarginChanged();
- void marginsChanged();
- void verticalCenterOffsetChanged();
- void horizontalCenterOffsetChanged();
- void baselineOffsetChanged();
- void mirroredChanged();
-
-private:
- friend class QQuickItemPrivate;
- Q_DISABLE_COPY(QQuickAnchors)
- Q_DECLARE_PRIVATE(QQuickAnchors)
-};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAnchors::Anchors)
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickAnchors)
-
-QT_END_HEADER
-
-#endif // QQUICKANCHORS_P_H
diff --git a/src/declarative/items/qquickanimatedimage_p.h b/src/declarative/items/qquickanimatedimage_p.h
deleted file mode 100644
index ae96e4cc15..0000000000
--- a/src/declarative/items/qquickanimatedimage_p.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Commit: 80d0fe9cbd92288a08d5ced8767f1edb651dae37
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKANIMATEDIMAGE_P_H
-#define QQUICKANIMATEDIMAGE_P_H
-
-#include "qquickimage_p.h"
-
-#ifndef QT_NO_MOVIE
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QMovie;
-class QQuickAnimatedImagePrivate;
-
-class Q_AUTOTEST_EXPORT QQuickAnimatedImage : public QQuickImage
-{
- Q_OBJECT
-
- Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
- Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
- Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
- Q_PROPERTY(int frameCount READ frameCount)
-
- // read-only for AnimatedImage
- Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
-
-public:
- QQuickAnimatedImage(QQuickItem *parent=0);
- ~QQuickAnimatedImage();
-
- bool isPlaying() const;
- void setPlaying(bool play);
-
- bool isPaused() const;
- void setPaused(bool pause);
-
- int currentFrame() const;
- void setCurrentFrame(int frame);
-
- int frameCount() const;
-
- // Extends QQuickImage's src property*/
- virtual void setSource(const QUrl&);
-
-Q_SIGNALS:
- void playingChanged();
- void pausedChanged();
- void frameChanged();
- void sourceSizeChanged();
-
-private Q_SLOTS:
- void movieUpdate();
- void movieRequestFinished();
- void playingStatusChanged();
-
-protected:
- virtual void load();
- void componentComplete();
-
-private:
- Q_DISABLE_COPY(QQuickAnimatedImage)
- Q_DECLARE_PRIVATE(QQuickAnimatedImage)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickAnimatedImage)
-
-QT_END_HEADER
-
-#endif // QT_NO_MOVIE
-
-#endif // QQUICKANIMATEDIMAGE_P_H
diff --git a/src/declarative/items/qquickanimation_p.h b/src/declarative/items/qquickanimation_p.h
deleted file mode 100644
index 2ce72249e2..0000000000
--- a/src/declarative/items/qquickanimation_p.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Commit: e39a2e39451bf106a9845f8a60fc571faaa4dde5
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKANIMATION_H
-#define QQUICKANIMATION_H
-
-#include "qquickitem.h"
-
-#include <private/qdeclarativeanimation_p.h>
-
-#include <QtCore/qabstractanimation.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParentAnimationPrivate;
-class QQuickParentAnimation : public QDeclarativeAnimationGroup
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickParentAnimation)
-
- Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(QQuickItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged)
- Q_PROPERTY(QQuickItem *via READ via WRITE setVia NOTIFY viaChanged)
-
-public:
- QQuickParentAnimation(QObject *parent=0);
- virtual ~QQuickParentAnimation();
-
- QQuickItem *target() const;
- void setTarget(QQuickItem *);
-
- QQuickItem *newParent() const;
- void setNewParent(QQuickItem *);
-
- QQuickItem *via() const;
- void setVia(QQuickItem *);
-
-Q_SIGNALS:
- void targetChanged();
- void newParentChanged();
- void viaChanged();
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QQuickAnchorAnimationPrivate;
-class QQuickAnchorAnimation : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickAnchorAnimation)
- Q_PROPERTY(QDeclarativeListProperty<QQuickItem> targets READ targets)
- Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
- Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
-
-public:
- QQuickAnchorAnimation(QObject *parent=0);
- virtual ~QQuickAnchorAnimation();
-
- QDeclarativeListProperty<QQuickItem> targets();
-
- int duration() const;
- void setDuration(int);
-
- QEasingCurve easing() const;
- void setEasing(const QEasingCurve &);
-
-Q_SIGNALS:
- void durationChanged(int);
- void easingChanged(const QEasingCurve&);
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QQuickItem;
-class QDeclarativePath;
-class QQuickPathAnimationPrivate;
-class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickPathAnimation)
-
- Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
- Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
- Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
- Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
- Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged)
- Q_PROPERTY(qreal orientationEntryInterval READ orientationEntryInterval WRITE setOrientationEntryInterval NOTIFY orientationEntryIntervalChanged)
- Q_PROPERTY(qreal orientationExitInterval READ orientationExitInterval WRITE setOrientationExitInterval NOTIFY orientationExitIntervalChanged)
- Q_PROPERTY(qreal endRotation READ endRotation WRITE setEndRotation NOTIFY endRotationChanged)
-
-public:
- QQuickPathAnimation(QObject *parent=0);
- virtual ~QQuickPathAnimation();
-
- enum Orientation {
- Fixed,
- RightFirst,
- LeftFirst,
- BottomFirst,
- TopFirst
- };
- Q_ENUMS(Orientation)
-
- int duration() const;
- void setDuration(int);
-
- QEasingCurve easing() const;
- void setEasing(const QEasingCurve &);
-
- QDeclarativePath *path() const;
- void setPath(QDeclarativePath *);
-
- QQuickItem *target() const;
- void setTarget(QQuickItem *);
-
- Orientation orientation() const;
- void setOrientation(Orientation orientation);
-
- QPointF anchorPoint() const;
- void setAnchorPoint(const QPointF &point);
-
- qreal orientationEntryInterval() const;
- void setOrientationEntryInterval(qreal);
-
- qreal orientationExitInterval() const;
- void setOrientationExitInterval(qreal);
-
- qreal endRotation() const;
- void setEndRotation(qreal);
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-
-Q_SIGNALS:
- void durationChanged(int);
- void easingChanged(const QEasingCurve &);
- void pathChanged();
- void targetChanged();
- void orientationChanged(Orientation);
- void anchorPointChanged(const QPointF &);
- void orientationEntryIntervalChanged(qreal);
- void orientationExitIntervalChanged(qreal);
- void endRotationChanged(qreal);
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickParentAnimation)
-QML_DECLARE_TYPE(QQuickAnchorAnimation)
-QML_DECLARE_TYPE(QQuickPathAnimation)
-
-QT_END_HEADER
-
-#endif // QQUICKANIMATION_H
diff --git a/src/declarative/items/qquickborderimage_p.h b/src/declarative/items/qquickborderimage_p.h
deleted file mode 100644
index 0af6fca55d..0000000000
--- a/src/declarative/items/qquickborderimage_p.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKBORDERIMAGE_P_H
-#define QQUICKBORDERIMAGE_P_H
-
-#include "qquickimagebase_p.h"
-
-QT_BEGIN_HEADER
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickScaleGrid;
-class QQuickGridScaledImage;
-class QQuickBorderImagePrivate;
-class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase
-{
- Q_OBJECT
- Q_ENUMS(TileMode)
-
- Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
- Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
- Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
- // read-only for BorderImage
- Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
-
-public:
- QQuickBorderImage(QQuickItem *parent=0);
- ~QQuickBorderImage();
-
- QQuickScaleGrid *border();
-
- enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
-
- TileMode horizontalTileMode() const;
- void setHorizontalTileMode(TileMode);
-
- TileMode verticalTileMode() const;
- void setVerticalTileMode(TileMode);
-
- void setSource(const QUrl &url);
-
-Q_SIGNALS:
- void horizontalTileModeChanged();
- void verticalTileModeChanged();
- void sourceSizeChanged();
-
-protected:
- virtual void load();
- virtual void pixmapChange();
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-private:
- void setGridScaledImage(const QQuickGridScaledImage& sci);
-
-private Q_SLOTS:
- void doUpdate();
- void requestFinished();
- void sciRequestFinished();
-
-private:
- Q_DISABLE_COPY(QQuickBorderImage)
- Q_DECLARE_PRIVATE(QQuickBorderImage)
-};
-
-QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickBorderImage)
-QT_END_HEADER
-
-#endif // QQUICKBORDERIMAGE_P_H
diff --git a/src/declarative/items/qquickcanvas.cpp b/src/declarative/items/qquickcanvas.cpp
deleted file mode 100644
index 8022af98f4..0000000000
--- a/src/declarative/items/qquickcanvas.cpp
+++ /dev/null
@@ -1,2644 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickcanvas.h"
-#include "qquickcanvas_p.h"
-
-#include "qquickitem.h"
-#include "qquickitem_p.h"
-
-#include <private/qsgrenderer_p.h>
-#include <private/qsgtexture_p.h>
-#include <private/qsgflashnode_p.h>
-#include <qsgengine.h>
-
-#include <private/qguiapplication_p.h>
-#include <QtGui/QInputPanel>
-
-#include <private/qabstractanimation_p.h>
-
-#include <QtGui/qpainter.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qmatrix4x4.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qabstractanimation.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-
-#include <private/qdeclarativedebugtrace_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#define QQUICK_CANVAS_TIMING
-#ifdef QQUICK_CANVAS_TIMING
-static bool qquick_canvas_timing = !qgetenv("QML_CANVAS_TIMING").isEmpty();
-static QTime threadTimer;
-static int syncTime;
-static int renderTime;
-static int swapTime;
-#endif
-
-DEFINE_BOOL_CONFIG_OPTION(qmlFixedAnimationStep, QML_FIXED_ANIMATION_STEP)
-DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP)
-
-extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-
-void QQuickCanvasPrivate::updateFocusItemTransform()
-{
- Q_Q(QQuickCanvas);
- QQuickItem *focus = q->activeFocusItem();
- if (focus && qApp->inputPanel()->inputItem() == focus)
- qApp->inputPanel()->setInputItemTransform(QQuickItemPrivate::get(focus)->itemToCanvasTransform());
-}
-
-class QQuickCanvasIncubationController : public QObject, public QDeclarativeIncubationController
-{
-public:
- QQuickCanvasIncubationController(QQuickCanvasPrivate *canvas)
- : m_canvas(canvas), m_eventSent(false) {}
-
-protected:
- virtual bool event(QEvent *e)
- {
- if (e->type() == QEvent::User) {
- Q_ASSERT(m_eventSent);
-
- bool *amtp = m_canvas->thread->allowMainThreadProcessing();
- while (incubatingObjectCount()) {
- if (amtp)
- incubateWhile(amtp);
- else
- incubateFor(5);
- QCoreApplication::processEvents();
- }
-
- m_eventSent = false;
- }
- return QObject::event(e);
- }
-
- virtual void incubatingObjectCountChanged(int count)
- {
- if (count && !m_eventSent) {
- m_eventSent = true;
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- }
- }
-
-private:
- QQuickCanvasPrivate *m_canvas;
- bool m_eventSent;
-};
-
-class QQuickCanvasPlainRenderLoop : public QObject, public QQuickCanvasRenderLoop
-{
-public:
- QQuickCanvasPlainRenderLoop()
- : updatePending(false)
- , animationRunning(false)
- {
- }
-
- virtual void paint() {
- updatePending = false;
- if (animationRunning && animationDriver())
- animationDriver()->advance();
- polishItems();
- syncSceneGraph();
- makeCurrent();
- glViewport(0, 0, size.width(), size.height());
- renderSceneGraph(size);
- swapBuffers();
-
- if (animationRunning)
- maybeUpdate();
- }
-
- virtual QImage grab() {
- return qt_gl_read_framebuffer(size, false, false);
- }
-
- virtual void startRendering() {
- if (!glContext()) {
- createGLContext();
- makeCurrent();
- initializeSceneGraph();
- } else {
- makeCurrent();
- }
- maybeUpdate();
- }
-
- virtual void stopRendering() {
- cleanupNodesOnShutdown();
- }
-
- virtual void maybeUpdate() {
- if (!updatePending) {
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- updatePending = true;
- }
- }
-
- virtual void animationStarted() {
- animationRunning = true;
- maybeUpdate();
- }
-
- virtual void animationStopped() {
- animationRunning = false;
- }
-
- virtual bool isRunning() const { return glContext(); } // Event loop is always running...
- virtual void resize(const QSize &s) { size = s; }
- virtual void setWindowSize(const QSize &s) { size = s; }
-
- bool event(QEvent *e) {
- if (e->type() == QEvent::User) {
- paint();
- return true;
- }
- return QObject::event(e);
- }
-
- QSize size;
-
- uint updatePending : 1;
- uint animationRunning : 1;
-};
-
-
-
-/*
-Focus behavior
-==============
-
-Prior to being added to a valid canvas items can set and clear focus with no
-effect. Only once items are added to a canvas (by way of having a parent set that
-already belongs to a canvas) do the focus rules apply. Focus goes back to
-having no effect if an item is removed from a canvas.
-
-When an item is moved into a new focus scope (either being added to a canvas
-for the first time, or having its parent changed), if the focus scope already has
-a scope focused item that takes precedence over the item being added. Otherwise,
-the focus of the added tree is used. In the case of of a tree of items being
-added to a canvas for the first time, which may have a conflicted focus state (two
-or more items in one scope having focus set), the same rule is applied item by item -
-thus the first item that has focus will get it (assuming the scope doesn't already
-have a scope focused item), and the other items will have their focus cleared.
-*/
-
-/*
- Threaded Rendering
- ==================
-
- The threaded rendering uses a number of different variables to track potential
- states used to handle resizing, initial paint, grabbing and driving animations
- while ALWAYS keeping the GL context in the rendering thread and keeping the
- overhead of normal one-shot paints and vblank driven animations at a minimum.
-
- Resize, initial show and grab suffer slightly in this model as they are locked
- to the rendering in the rendering thread, but this is a necessary evil for
- the system to work.
-
- Variables that are used:
-
- Private::animationRunning: This is true while the animations are running, and only
- written to inside locks.
-
- RenderThread::isGuiBlocked: This is used to indicate that the GUI thread owns the
- lock. This variable is an integer to allow for recursive calls to lockInGui()
- without using a recursive mutex. See isGuiBlockPending.
-
- RenderThread::isPaintComplete: This variable is cleared when rendering starts and
- set once rendering is complete. It is monitored in the paintEvent(),
- resizeEvent() and grab() functions to force them to wait for rendering to
- complete.
-
- RenderThread::isGuiBlockPending: This variable is set in the render thread just
- before the sync event is sent to the GUI thread. It is used to avoid deadlocks
- in the case where render thread waits while waiting for GUI to pick up the sync
- event and GUI thread gets a resizeEvent, the initial paintEvent or a grab.
- When this happens, we use the
- exhaustSyncEvent() function to do the sync right there and mark the coming
- sync event to be discarded. There can only ever be one sync incoming.
-
- RenderThread::isRenderBlock: This variable is true when animations are not
- running and the render thread has gone to sleep, waiting for more to do.
-
- RenderThread::isExternalUpdatePending: This variable is set to false when
- a new render pass is started and to true in maybeUpdate(). It is an
- indication to the render thread that another render pass needs to take
- place, rather than the render thread going to sleep after completing its swap.
-
- RenderThread::doGrab: This variable is set by the grab() function and
- tells the renderer to do a grab after rendering is complete and before
- swapping happens.
-
- RenderThread::shouldExit: This variable is used to determine if the render
- thread should do a nother pass. It is typically set as a result of show()
- and unset as a result of hide() or during shutdown()
-
- RenderThread::hasExited: Used by the GUI thread to synchronize the shutdown
- after shouldExit has been set to true.
- */
-
-// #define FOCUS_DEBUG
-// #define MOUSE_DEBUG
-// #define TOUCH_DEBUG
-// #define DIRTY_DEBUG
-// #define THREAD_DEBUG
-
-// #define FRAME_TIMING
-
-#ifdef FRAME_TIMING
-static QTime frameTimer;
-int sceneGraphRenderTime;
-int readbackTime;
-#endif
-
-QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
-: transformNode(0)
-{
-}
-
-QQuickRootItem::QQuickRootItem()
-{
-}
-
-void QQuickCanvas::exposeEvent(QExposeEvent *)
-{
- Q_D(QQuickCanvas);
- d->thread->paint();
-}
-
-void QQuickCanvas::resizeEvent(QResizeEvent *)
-{
- Q_D(QQuickCanvas);
- d->thread->resize(size());
-}
-
-void QQuickCanvas::animationStarted()
-{
- d_func()->thread->animationStarted();
-}
-
-void QQuickCanvas::animationStopped()
-{
- d_func()->thread->animationStopped();
-}
-
-void QQuickCanvas::showEvent(QShowEvent *)
-{
- Q_D(QQuickCanvas);
- if (d->vsyncAnimations) {
- if (!d->animationDriver) {
- d->animationDriver = d->context->createAnimationDriver(this);
- connect(d->animationDriver, SIGNAL(started()), this, SLOT(animationStarted()), Qt::DirectConnection);
- connect(d->animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()), Qt::DirectConnection);
- }
- d->animationDriver->install();
- }
-
- if (!d->thread->isRunning()) {
- d->thread->setWindowSize(size());
- d->thread->startRendering();
- }
-}
-
-void QQuickCanvas::hideEvent(QHideEvent *)
-{
- Q_D(QQuickCanvas);
- d->thread->stopRendering();
-}
-
-void QQuickCanvas::focusOutEvent(QFocusEvent *)
-{
- Q_D(QQuickCanvas);
- d->rootItem->setFocus(false);
-}
-
-void QQuickCanvas::focusInEvent(QFocusEvent *)
-{
- Q_D(QQuickCanvas);
- d->rootItem->setFocus(true);
-}
-
-
-/*!
- Sets weither this canvas should use vsync driven animations.
-
- This option can only be set on one single QQuickCanvas, and that it's
- vsync signal will then be used to drive all animations in the
- process.
-
- This feature is primarily useful for single QQuickCanvas, QML-only
- applications.
-
- \warning Enabling vsync on multiple QQuickCanvas instances has
- undefined behavior.
- */
-void QQuickCanvas::setVSyncAnimations(bool enabled)
-{
- Q_D(QQuickCanvas);
- if (visible()) {
- qWarning("QQuickCanvas::setVSyncAnimations: Cannot be changed when widget is shown");
- return;
- }
- d->vsyncAnimations = enabled;
-}
-
-
-
-/*!
- Returns true if this canvas should use vsync driven animations;
- otherwise returns false.
- */
-bool QQuickCanvas::vsyncAnimations() const
-{
- Q_D(const QQuickCanvas);
- return d->vsyncAnimations;
-}
-
-void QQuickCanvasPrivate::initializeSceneGraph()
-{
- if (!context)
- context = QSGContext::createDefaultContext();
-
- if (context->isReady())
- return;
-
- QOpenGLContext *glctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- context->initialize(glctx);
-
- Q_Q(QQuickCanvas);
-
- if (!QQuickItemPrivate::get(rootItem)->itemNode()->parent()) {
- context->rootNode()->appendChildNode(QQuickItemPrivate::get(rootItem)->itemNode());
- }
-
- engine = new QSGEngine();
- engine->setCanvas(q);
-
- emit q_func()->sceneGraphInitialized();
-}
-
-void QQuickCanvasPrivate::polishItems()
-{
- while (!itemsToPolish.isEmpty()) {
- QSet<QQuickItem *>::Iterator iter = itemsToPolish.begin();
- QQuickItem *item = *iter;
- itemsToPolish.erase(iter);
- QQuickItemPrivate::get(item)->polishScheduled = false;
- item->updatePolish();
- }
- updateFocusItemTransform();
-}
-
-
-void QQuickCanvasPrivate::syncSceneGraph()
-{
- updateDirtyNodes();
-
- // Copy the current state of clearing from canvas into renderer.
- context->renderer()->setClearColor(clearColor);
- QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
- if (clearBeforeRendering)
- mode |= QSGRenderer::ClearColorBuffer;
- context->renderer()->setClearMode(mode);
-}
-
-
-void QQuickCanvasPrivate::renderSceneGraph(const QSize &size)
-{
- Q_Q(QQuickCanvas);
- context->renderer()->setDeviceRect(QRect(QPoint(0, 0), size));
- context->renderer()->setViewportRect(QRect(QPoint(0, 0), renderTarget ? renderTarget->size() : size));
- context->renderer()->setProjectionMatrixToDeviceRect();
-
- emit q->beforeRendering();
- context->renderNextFrame(renderTarget);
- emit q->afterRendering();
-
-#ifdef FRAME_TIMING
- sceneGraphRenderTime = frameTimer.elapsed();
-#endif
-
-#ifdef FRAME_TIMING
-// int pixel;
-// glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
- readbackTime = frameTimer.elapsed();
-#endif
-}
-
-
-QQuickCanvasPrivate::QQuickCanvasPrivate()
- : rootItem(0)
- , activeFocusItem(0)
- , mouseGrabberItem(0)
- , dirtyItemList(0)
- , context(0)
- , clearColor(Qt::white)
- , vsyncAnimations(false)
- , clearBeforeRendering(true)
- , thread(0)
- , animationDriver(0)
- , renderTarget(0)
- , incubationController(0)
-{
-}
-
-QQuickCanvasPrivate::~QQuickCanvasPrivate()
-{
-}
-
-void QQuickCanvasPrivate::init(QQuickCanvas *c)
-{
- QUnifiedTimer* ut = QUnifiedTimer::instance(true);
- if (qmlFixedAnimationStep())
- ut->setConsistentTiming(true);
-
- q_ptr = c;
-
- Q_Q(QQuickCanvas);
-
- rootItem = new QQuickRootItem;
- QQuickItemPrivate *rootItemPrivate = QQuickItemPrivate::get(rootItem);
- rootItemPrivate->canvas = q;
- rootItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
-
- // In the absence of a focus in event on some platforms assume the window will
- // be activated immediately and set focus on the rootItem
- // ### Remove when QTBUG-22415 is resolved.
- //It is important that this call happens after the rootItem has a canvas..
- rootItem->setFocus(true);
-
- bool threaded = !qmlNoThreadedRenderer();
-
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)) {
- qWarning("QQuickCanvas: platform does not support threaded rendering!");
- threaded = false;
- }
-
- if (threaded)
- thread = new QQuickCanvasRenderThread();
- else
- thread = new QQuickCanvasPlainRenderLoop();
-
- thread->renderer = q;
- thread->d = this;
-
- context = QSGContext::createDefaultContext();
- thread->moveContextToThread(context);
-
- q->setSurfaceType(QWindow::OpenGLSurface);
- q->setFormat(context->defaultSurfaceFormat());
-}
-
-QDeclarativeListProperty<QObject> QQuickCanvasPrivate::data()
-{
- initRootItem();
- return QQuickItemPrivate::get(rootItem)->data();
-}
-
-void QQuickCanvasPrivate::initRootItem()
-{
- Q_Q(QQuickCanvas);
- q->connect(q, SIGNAL(widthChanged(int)),
- rootItem, SLOT(setWidth(int)));
- q->connect(q, SIGNAL(heightChanged(int)),
- rootItem, SLOT(setHeight(int)));
- rootItem->setWidth(q->width());
- rootItem->setHeight(q->height());
-}
-
-void QQuickCanvasPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
-{
- for (int i=0; i<touchPoints.count(); i++) {
- QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
- touchPoint.setRect(transform.mapRect(touchPoint.sceneRect()));
- touchPoint.setStartPos(transform.map(touchPoint.startScenePos()));
- touchPoint.setLastPos(transform.map(touchPoint.lastScenePos()));
- }
-}
-
-
-/*!
-Translates the data in \a touchEvent to this canvas. This method leaves the item local positions in
-\a touchEvent untouched (these are filled in later).
-*/
-void QQuickCanvasPrivate::translateTouchEvent(QTouchEvent *touchEvent)
-{
-// Q_Q(QQuickCanvas);
-
-// touchEvent->setWidget(q); // ### refactor...
-
- QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
- for (int i = 0; i < touchPoints.count(); ++i) {
- QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
-
- touchPoint.setScreenRect(touchPoint.sceneRect());
- touchPoint.setStartScreenPos(touchPoint.startScenePos());
- touchPoint.setLastScreenPos(touchPoint.lastScenePos());
-
- touchPoint.setSceneRect(touchPoint.rect());
- touchPoint.setStartScenePos(touchPoint.startPos());
- touchPoint.setLastScenePos(touchPoint.lastPos());
-
- if (touchPoint.isPrimary())
- lastMousePosition = touchPoint.pos().toPoint();
- }
- touchEvent->setTouchPoints(touchPoints);
-}
-
-void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
-{
- Q_Q(QQuickCanvas);
-
- Q_ASSERT(item);
- Q_ASSERT(scope || item == rootItem);
-
-#ifdef FOCUS_DEBUG
- qWarning() << "QQuickCanvasPrivate::setFocusInScope():";
- qWarning() << " scope:" << (QObject *)scope;
- if (scope)
- qWarning() << " scopeSubFocusItem:" << (QObject *)QQuickItemPrivate::get(scope)->subFocusItem;
- qWarning() << " item:" << (QObject *)item;
- qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
-#endif
-
- QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- QQuickItem *oldActiveFocusItem = 0;
- QQuickItem *newActiveFocusItem = 0;
-
- QVarLengthArray<QQuickItem *, 20> changed;
-
- // Does this change the active focus?
- if (item == rootItem || scopePrivate->activeFocus) {
- oldActiveFocusItem = activeFocusItem;
- newActiveFocusItem = item;
- while (newActiveFocusItem->isFocusScope() && newActiveFocusItem->scopedFocusItem())
- newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
-
- if (oldActiveFocusItem) {
-#ifndef QT_NO_IM
- qApp->inputPanel()->commit();
-#endif
-
- activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
- q->sendEvent(oldActiveFocusItem, &event);
-
- QQuickItem *afi = oldActiveFocusItem;
- while (afi != scope) {
- if (QQuickItemPrivate::get(afi)->activeFocus) {
- QQuickItemPrivate::get(afi)->activeFocus = false;
- changed << afi;
- }
- afi = afi->parentItem();
- }
- }
- }
-
- if (item != rootItem) {
- 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;
- }
- }
-
- if (!(options & DontChangeFocusProperty)) {
-// if (item != rootItem || QGuiApplication::focusWindow() == q) { // QTBUG-22415
- itemPrivate->focus = true;
- changed << item;
-// }
- }
-
- if (newActiveFocusItem && rootItem->hasFocus()) {
- activeFocusItem = newActiveFocusItem;
-
- QQuickItemPrivate::get(newActiveFocusItem)->activeFocus = true;
- changed << newActiveFocusItem;
-
- QQuickItem *afi = newActiveFocusItem->parentItem();
- while (afi && afi != scope) {
- if (afi->isFocusScope()) {
- QQuickItemPrivate::get(afi)->activeFocus = true;
- changed << afi;
- }
- afi = afi->parentItem();
- }
-
- updateInputMethodData();
-
- QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
- q->sendEvent(newActiveFocusItem, &event);
- } else {
- updateInputMethodData();
- }
-
- if (!changed.isEmpty())
- notifyFocusChangesRecur(changed.data(), changed.count() - 1);
-}
-
-void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
-{
- Q_Q(QQuickCanvas);
-
- Q_UNUSED(item);
- Q_ASSERT(item);
- Q_ASSERT(scope || item == rootItem);
-
-#ifdef FOCUS_DEBUG
- qWarning() << "QQuickCanvasPrivate::clearFocusInScope():";
- qWarning() << " scope:" << (QObject *)scope;
- qWarning() << " item:" << (QObject *)item;
- qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
-#endif
-
- QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
-
- QQuickItem *oldActiveFocusItem = 0;
- QQuickItem *newActiveFocusItem = 0;
-
- QVarLengthArray<QQuickItem *, 20> changed;
-
- Q_ASSERT(item == rootItem || item == scopePrivate->subFocusItem);
-
- // Does this change the active focus?
- if (item == rootItem || scopePrivate->activeFocus) {
- oldActiveFocusItem = activeFocusItem;
- newActiveFocusItem = scope;
-
- Q_ASSERT(oldActiveFocusItem);
-
-#ifndef QT_NO_IM
- qApp->inputPanel()->commit();
-#endif
-
- activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
- q->sendEvent(oldActiveFocusItem, &event);
-
- QQuickItem *afi = oldActiveFocusItem;
- while (afi != scope) {
- if (QQuickItemPrivate::get(afi)->activeFocus) {
- QQuickItemPrivate::get(afi)->activeFocus = false;
- changed << afi;
- }
- afi = afi->parentItem();
- }
- }
-
- if (item != rootItem) {
- 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;
- }
- } else if (!(options & DontChangeFocusProperty)) {
- QQuickItemPrivate::get(item)->focus = false;
- changed << item;
- }
-
- if (newActiveFocusItem) {
- Q_ASSERT(newActiveFocusItem == scope);
- activeFocusItem = scope;
-
- updateInputMethodData();
-
- QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
- q->sendEvent(newActiveFocusItem, &event);
- } else {
- updateInputMethodData();
- }
-
- if (!changed.isEmpty())
- notifyFocusChangesRecur(changed.data(), changed.count() - 1);
-}
-
-void QQuickCanvasPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining)
-{
- QDeclarativeGuard<QQuickItem> item(*items);
-
- if (remaining)
- notifyFocusChangesRecur(items + 1, remaining - 1);
-
- if (item) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- if (itemPrivate->notifiedFocus != itemPrivate->focus) {
- itemPrivate->notifiedFocus = itemPrivate->focus;
- emit item->focusChanged(itemPrivate->focus);
- }
-
- if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
- itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
- itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
- emit item->activeFocusChanged(itemPrivate->activeFocus);
- }
- }
-}
-
-void QQuickCanvasPrivate::updateInputMethodData()
-{
- QQuickItem *inputItem = 0;
- if (activeFocusItem && activeFocusItem->flags() & QQuickItem::ItemAcceptsInputMethod)
- inputItem = activeFocusItem;
- qApp->inputPanel()->setInputItem(inputItem);
-}
-
-void QQuickCanvasPrivate::dirtyItem(QQuickItem *)
-{
- Q_Q(QQuickCanvas);
- q->maybeUpdate();
-}
-
-void QQuickCanvasPrivate::cleanup(QSGNode *n)
-{
- Q_Q(QQuickCanvas);
-
- Q_ASSERT(!cleanupNodeList.contains(n));
- cleanupNodeList.append(n);
- q->maybeUpdate();
-}
-
-
-/*!
- \qmlclass Window QQuickCanvas
- \inqmlmodule QtQuick.Window 2
- \brief The Window object creates a new top-level window.
-
- The Window object creates a new top-level window for a QtQuick scene. It automatically sets up the
- window for use with QtQuick 2.0 graphical elements.
-*/
-/*!
- \class QQuickCanvas
- \since QtQuick 2.0
- \brief The QQuickCanvas class provides the canvas for displaying a graphical QML scene
-
- QQuickCanvas provides the graphical scene management needed to interact with and display
- a scene of QQuickItems.
-
- A QQuickCanvas always has a single invisible root item. To add items to this canvas,
- 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}.
-*/
-QQuickCanvas::QQuickCanvas(QWindow *parent)
- : QWindow(*(new QQuickCanvasPrivate), parent)
-{
- Q_D(QQuickCanvas);
- d->init(this);
-}
-
-QQuickCanvas::QQuickCanvas(QQuickCanvasPrivate &dd, QWindow *parent)
- : QWindow(dd, parent)
-{
- Q_D(QQuickCanvas);
- d->init(this);
-}
-
-QQuickCanvas::~QQuickCanvas()
-{
- Q_D(QQuickCanvas);
-
- if (d->thread->isRunning())
- d->thread->stopRendering();
-
- // ### 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();
-
- delete d->incubationController; d->incubationController = 0;
-
- delete d->rootItem; d->rootItem = 0;
-
- delete d->thread; d->thread = 0;
-}
-
-/*!
- Returns the invisible root item of the scene.
-
- A QQuickCanvas always has a single invisible root item. To add items to this canvas,
- reparent the items to the root item or to an existing item in the scene.
-*/
-QQuickItem *QQuickCanvas::rootItem() const
-{
- Q_D(const QQuickCanvas);
-
- return d->rootItem;
-}
-
-/*!
- Returns the item which currently has active focus.
-*/
-QQuickItem *QQuickCanvas::activeFocusItem() const
-{
- Q_D(const QQuickCanvas);
-
- return d->activeFocusItem;
-}
-
-/*!
- Returns the item which currently has the mouse grab.
-*/
-QQuickItem *QQuickCanvas::mouseGrabberItem() const
-{
- Q_D(const QQuickCanvas);
-
- return d->mouseGrabberItem;
-}
-
-
-/*!
- \qmlproperty color QtQuick2.Window::Window::color
-
- The background color for the window.
-
- Setting this property is more efficient than using a separate Rectangle.
-*/
-
-bool QQuickCanvasPrivate::clearHover()
-{
- if (hoverItems.isEmpty())
- return false;
-
- QPointF pos = QCursor::pos(); // ### refactor: q->mapFromGlobal(QCursor::pos());
-
- bool accepted = false;
- foreach (QQuickItem* item, hoverItems)
- accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
- hoverItems.clear();
- return accepted;
-}
-
-
-bool QQuickCanvas::event(QEvent *e)
-{
- Q_D(QQuickCanvas);
-
- switch (e->type()) {
-
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- {
- QTouchEvent *touch = static_cast<QTouchEvent *>(e);
- d->translateTouchEvent(touch);
- d->deliverTouchEvent(touch);
- if (!touch->isAccepted())
- return false;
- break;
- }
- case QEvent::Leave:
- d->clearHover();
- d->lastMousePosition = QPoint();
- break;
- case QEvent::DragEnter:
- case QEvent::DragLeave:
- case QEvent::DragMove:
- case QEvent::Drop:
- d->deliverDragEvent(&d->dragGrabber, e);
- break;
- case QEvent::WindowDeactivate:
- rootItem()->windowDeactivateEvent();
- break;
- default:
- break;
- }
-
- return QWindow::event(e);
-}
-
-void QQuickCanvas::keyPressEvent(QKeyEvent *e)
-{
- Q_D(QQuickCanvas);
-
- if (d->activeFocusItem)
- sendEvent(d->activeFocusItem, e);
-}
-
-void QQuickCanvas::keyReleaseEvent(QKeyEvent *e)
-{
- Q_D(QQuickCanvas);
-
- if (d->activeFocusItem)
- sendEvent(d->activeFocusItem, e);
-}
-
-bool QQuickCanvasPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouseEvent *event)
-{
- Q_Q(QQuickCanvas);
-
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (itemPrivate->opacity == 0.0)
- return false;
-
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(event->windowPos());
- if (!QRectF(0, 0, item->width(), item->height()).contains(p))
- return false;
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled())
- continue;
- if (deliverInitialMousePressEvent(child, event))
- return true;
- }
-
- if (itemPrivate->acceptedMouseButtons & event->button()) {
- QPointF p = item->mapFromScene(event->windowPos());
- if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- QMouseEvent me(event->type(), p, event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers());
- me.accept();
- mouseGrabberItem = item;
- q->sendEvent(item, &me);
- event->setAccepted(me.isAccepted());
- if (me.isAccepted())
- return true;
- mouseGrabberItem->ungrabMouse();
- mouseGrabberItem = 0;
- }
- }
-
- return false;
-}
-
-bool QQuickCanvasPrivate::deliverMouseEvent(QMouseEvent *event)
-{
- Q_Q(QQuickCanvas);
-
- lastMousePosition = event->windowPos();
-
- if (!mouseGrabberItem &&
- event->type() == QEvent::MouseButtonPress &&
- (event->button() & event->buttons()) == event->buttons()) {
- return deliverInitialMousePressEvent(rootItem, event);
- }
-
- if (mouseGrabberItem) {
- QQuickItemPrivate *mgPrivate = QQuickItemPrivate::get(mouseGrabberItem);
- const QTransform &transform = mgPrivate->canvasToItemTransform();
- QMouseEvent me(event->type(), transform.map(event->windowPos()), event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers());
- me.accept();
- q->sendEvent(mouseGrabberItem, &me);
- event->setAccepted(me.isAccepted());
- if (me.isAccepted())
- return true;
- }
-
- return false;
-}
-
-void QQuickCanvas::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickCanvas);
-
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons();
-#endif
-
- d->deliverMouseEvent(event);
-}
-
-void QQuickCanvas::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickCanvas);
-
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons();
-#endif
-
- if (!d->mouseGrabberItem) {
- QWindow::mouseReleaseEvent(event);
- return;
- }
-
- d->deliverMouseEvent(event);
- d->mouseGrabberItem = 0;
-}
-
-void QQuickCanvas::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickCanvas);
-
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons();
-#endif
-
- if (!d->mouseGrabberItem && (event->button() & event->buttons()) == event->buttons()) {
- if (d->deliverInitialMousePressEvent(d->rootItem, event))
- event->accept();
- else
- event->ignore();
- return;
- }
-
- d->deliverMouseEvent(event);
-}
-
-bool QQuickCanvasPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
- const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted)
-{
- Q_Q(QQuickCanvas);
- const QTransform transform = QQuickItemPrivate::get(item)->canvasToItemTransform();
-
- //create copy of event
- QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
- hoverEvent.setAccepted(accepted);
-
- q->sendEvent(item, &hoverEvent);
-
- return hoverEvent.isAccepted();
-}
-
-void QQuickCanvas::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickCanvas);
-
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons();
-#endif
-
- if (!d->mouseGrabberItem) {
- if (d->lastMousePosition.isNull())
- d->lastMousePosition = event->windowPos();
- QPointF last = d->lastMousePosition;
- d->lastMousePosition = event->windowPos();
-
- bool accepted = event->isAccepted();
- bool delivered = d->deliverHoverEvent(d->rootItem, event->windowPos(), last, event->modifiers(), accepted);
- if (!delivered) {
- //take care of any exits
- accepted = d->clearHover();
- }
- event->setAccepted(accepted);
- return;
- }
-
- d->deliverMouseEvent(event);
-}
-
-bool QQuickCanvasPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool &accepted)
-{
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (itemPrivate->opacity == 0.0)
- return false;
-
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(scenePos);
- if (!QRectF(0, 0, item->width(), item->height()).contains(p))
- return false;
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled())
- continue;
- if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
- return true;
- }
-
- if (itemPrivate->hoverEnabled) {
- QPointF p = item->mapFromScene(scenePos);
- if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- if (!hoverItems.isEmpty() && hoverItems[0] == item) {
- //move
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
- } else {
- QList<QQuickItem *> itemsToHover;
- QQuickItem* parent = item;
- itemsToHover << item;
- while ((parent = parent->parentItem()))
- itemsToHover << parent;
-
- // Leaving from previous hovered items until we reach the item or one of its ancestors.
- while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
- sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
- hoverItems.removeFirst();
- }
-
- if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
- // ### Shouldn't we send moves for the parent items as well?
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
- } else {
- // Enter items that are not entered yet.
- int startIdx = -1;
- if (!hoverItems.isEmpty())
- startIdx = itemsToHover.indexOf(hoverItems[0]) - 1;
- if (startIdx == -1)
- startIdx = itemsToHover.count() - 1;
-
- for (int i = startIdx; i >= 0; i--) {
- QQuickItem *itemToHover = itemsToHover[i];
- if (QQuickItemPrivate::get(itemToHover)->hoverEnabled) {
- hoverItems.prepend(itemToHover);
- sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
- }
- }
- }
- }
- return true;
- }
- }
-
- return false;
-}
-
-bool QQuickCanvasPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
-{
- Q_Q(QQuickCanvas);
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (itemPrivate->opacity == 0.0)
- return false;
-
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(event->posF());
- if (!QRectF(0, 0, item->width(), item->height()).contains(p))
- return false;
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled())
- continue;
- if (deliverWheelEvent(child, event))
- return true;
- }
-
- QPointF p = item->mapFromScene(event->posF());
- if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- QWheelEvent wheel(p, event->delta(), event->buttons(), event->modifiers(), event->orientation());
- wheel.accept();
- q->sendEvent(item, &wheel);
- if (wheel.isAccepted()) {
- event->accept();
- return true;
- }
- }
-
- return false;
-}
-
-#ifndef QT_NO_WHEELEVENT
-void QQuickCanvas::wheelEvent(QWheelEvent *event)
-{
- Q_D(QQuickCanvas);
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickCanvas::wheelEvent()" << event->pos() << event->delta() << event->orientation();
-#endif
- event->ignore();
- d->deliverWheelEvent(d->rootItem, event);
-}
-#endif // QT_NO_WHEELEVENT
-
-bool QQuickCanvasPrivate::deliverTouchEvent(QTouchEvent *event)
-{
-#ifdef TOUCH_DEBUG
- if (event->type() == QEvent::TouchBegin)
- qWarning("touchBeginEvent");
- else if (event->type() == QEvent::TouchUpdate)
- qWarning("touchUpdateEvent");
- else if (event->type() == QEvent::TouchEnd)
- qWarning("touchEndEvent");
-#endif
-
- QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
-
- if (event->type() == QTouchEvent::TouchBegin) { // all points are new touch points
- QSet<int> acceptedNewPoints;
- deliverTouchPoints(rootItem, event, event->touchPoints(), &acceptedNewPoints, &updatedPoints);
- if (acceptedNewPoints.count() > 0)
- event->accept();
- return event->isAccepted();
- }
-
- const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
- QList<QTouchEvent::TouchPoint> newPoints;
- QQuickItem *item = 0;
- for (int i=0; i<touchPoints.count(); i++) {
- const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
- switch (touchPoint.state()) {
- case Qt::TouchPointPressed:
- newPoints << touchPoint;
- break;
- case Qt::TouchPointMoved:
- case Qt::TouchPointStationary:
- case Qt::TouchPointReleased:
- if (itemForTouchPointId.contains(touchPoint.id())) {
- item = itemForTouchPointId[touchPoint.id()];
- if (item)
- updatedPoints[item].append(touchPoint);
- }
- break;
- default:
- break;
- }
- }
-
- if (newPoints.count() > 0 || updatedPoints.count() > 0) {
- QSet<int> acceptedNewPoints;
- int prevCount = updatedPoints.count();
- deliverTouchPoints(rootItem, event, newPoints, &acceptedNewPoints, &updatedPoints);
- if (acceptedNewPoints.count() > 0 || updatedPoints.count() != prevCount)
- event->accept();
- }
-
- if (event->touchPointStates() & Qt::TouchPointReleased) {
- for (int i=0; i<touchPoints.count(); i++) {
- if (touchPoints[i].state() == Qt::TouchPointReleased)
- itemForTouchPointId.remove(touchPoints[i].id());
- }
- }
-
- return event->isAccepted();
-}
-
-bool QQuickCanvasPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints, QSet<int> *acceptedNewPoints, QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *updatedPoints)
-{
- Q_Q(QQuickCanvas);
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- if (itemPrivate->opacity == 0.0)
- return false;
-
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QRectF bounds(0, 0, item->width(), item->height());
- for (int i=0; i<newPoints.count(); i++) {
- QPointF p = item->mapFromScene(newPoints[i].scenePos());
- if (!bounds.contains(p))
- return false;
- }
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isEnabled())
- continue;
- if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints))
- return true;
- }
-
- QList<QTouchEvent::TouchPoint> matchingPoints;
- if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
- QRectF bounds(0, 0, item->width(), item->height());
- for (int i=0; i<newPoints.count(); i++) {
- if (acceptedNewPoints->contains(newPoints[i].id()))
- continue;
- QPointF p = item->mapFromScene(newPoints[i].scenePos());
- if (bounds.contains(p))
- matchingPoints << newPoints[i];
- }
- }
-
- if (matchingPoints.count() > 0 || (*updatedPoints)[item].count() > 0) {
- QList<QTouchEvent::TouchPoint> &eventPoints = (*updatedPoints)[item];
- eventPoints.append(matchingPoints);
- transformTouchPoints(eventPoints, itemPrivate->canvasToItemTransform());
-
- Qt::TouchPointStates eventStates;
- for (int i=0; i<eventPoints.count(); i++)
- eventStates |= eventPoints[i].state();
- // if all points have the same state, set the event type accordingly
- QEvent::Type eventType;
- switch (eventStates) {
- case Qt::TouchPointPressed:
- eventType = QEvent::TouchBegin;
- break;
- case Qt::TouchPointReleased:
- eventType = QEvent::TouchEnd;
- break;
- default:
- eventType = QEvent::TouchUpdate;
- break;
- }
-
- if (eventStates != Qt::TouchPointStationary) {
- QTouchEvent touchEvent(eventType);
- // touchEvent.setWidget(q); // ### refactor: what is the consequence of not setting the widget?
- touchEvent.setDeviceType(event->deviceType());
- touchEvent.setModifiers(event->modifiers());
- touchEvent.setTouchPointStates(eventStates);
- touchEvent.setTouchPoints(eventPoints);
- touchEvent.setTimestamp(event->timestamp());
-
- touchEvent.accept();
- q->sendEvent(item, &touchEvent);
-
- if (touchEvent.isAccepted()) {
- for (int i=0; i<matchingPoints.count(); i++) {
- itemForTouchPointId[matchingPoints[i].id()] = item;
- acceptedNewPoints->insert(matchingPoints[i].id());
- }
- }
- }
- }
-
- updatedPoints->remove(item);
- if (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty())
- return true;
-
- return false;
-}
-
-void QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
-{
- Q_Q(QQuickCanvas);
- grabber->resetTarget();
- QQuickDragGrabber::iterator grabItem = grabber->begin();
- if (grabItem != grabber->end()) {
- Q_ASSERT(event->type() != QEvent::DragEnter);
- if (event->type() == QEvent::Drop) {
- QDropEvent *e = static_cast<QDropEvent *>(event);
- for (e->setAccepted(false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
- QPointF p = (**grabItem)->mapFromScene(e->pos());
- QDropEvent translatedEvent(
- p.toPoint(),
- e->possibleActions(),
- e->mimeData(),
- e->mouseButtons(),
- e->keyboardModifiers());
- QQuickDropEventEx::copyActions(&translatedEvent, *e);
- q->sendEvent(**grabItem, &translatedEvent);
- e->setAccepted(translatedEvent.isAccepted());
- e->setDropAction(translatedEvent.dropAction());
- grabber->setTarget(**grabItem);
- }
- }
- if (event->type() != QEvent::DragMove) { // Either an accepted drop or a leave.
- QDragLeaveEvent leaveEvent;
- for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
- q->sendEvent(**grabItem, &leaveEvent);
- return;
- } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
- QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
- if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
- moveEvent->setAccepted(true);
- for (++grabItem; grabItem != grabber->end();) {
- QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
- if (QRectF(0, 0, (**grabItem)->width(), (**grabItem)->height()).contains(p)) {
- QDragMoveEvent translatedEvent(
- p.toPoint(),
- moveEvent->possibleActions(),
- moveEvent->mimeData(),
- moveEvent->mouseButtons(),
- moveEvent->keyboardModifiers());
- QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
- q->sendEvent(**grabItem, &translatedEvent);
- ++grabItem;
- } else {
- QDragLeaveEvent leaveEvent;
- q->sendEvent(**grabItem, &leaveEvent);
- grabItem = grabber->release(grabItem);
- }
- }
- return;
- } else {
- QDragLeaveEvent leaveEvent;
- q->sendEvent(**grabItem, &leaveEvent);
- }
- }
- }
- if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
- QDragMoveEvent *e = static_cast<QDragMoveEvent *>(event);
- QDragEnterEvent enterEvent(
- e->pos(),
- e->possibleActions(),
- e->mimeData(),
- e->mouseButtons(),
- e->keyboardModifiers());
- QQuickDropEventEx::copyActions(&enterEvent, *e);
- event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
- }
-}
-
-bool QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
-{
- Q_Q(QQuickCanvas);
- bool accepted = false;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (itemPrivate->opacity == 0.0 || !item->isVisible() || !item->isEnabled())
- return false;
-
- QPointF p = item->mapFromScene(event->pos());
- if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
- QDragMoveEvent translatedEvent(
- p.toPoint(),
- event->possibleActions(),
- event->mimeData(),
- event->mouseButtons(),
- event->keyboardModifiers(),
- event->type());
- QQuickDropEventEx::copyActions(&translatedEvent, *event);
- q->sendEvent(item, &translatedEvent);
- if (event->type() == QEvent::DragEnter) {
- if (translatedEvent.isAccepted()) {
- grabber->grab(item);
- accepted = true;
- }
- } else {
- accepted = true;
- }
- }
- } else if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- return false;
- }
-
- QDragEnterEvent enterEvent(
- event->pos(),
- event->possibleActions(),
- event->mimeData(),
- event->mouseButtons(),
- event->keyboardModifiers());
- QQuickDropEventEx::copyActions(&enterEvent, *event);
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
- return true;
- }
-
- return accepted;
-}
-
-bool QQuickCanvasPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
-{
- if (!target)
- return false;
-
- QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
- if (targetPrivate->filtersChildMouseEvents)
- if (target->childMouseEventFilter(item, event))
- return true;
-
- if (sendFilteredMouseEvent(target->parentItem(), item, event))
- return true;
-
- return false;
-}
-
-/*!
- Propagates an event to a QQuickItem on the canvas
-*/
-bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
-{
- Q_D(QQuickCanvas);
-
- if (!item) {
- qWarning("QQuickCanvas::sendEvent: Cannot send event to a null item");
- return false;
- }
-
- Q_ASSERT(e);
-
- switch (e->type()) {
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- e->accept();
- QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
- while (!e->isAccepted() && (item = item->parentItem())) {
- e->accept();
- QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
- }
- break;
- case QEvent::FocusIn:
- case QEvent::FocusOut:
- QQuickItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e));
- break;
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- case QEvent::MouseMove:
- // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
- if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
- e->accept();
- QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e));
- }
- break;
- case QEvent::Wheel:
- QQuickItemPrivate::get(item)->deliverWheelEvent(static_cast<QWheelEvent *>(e));
- break;
- case QEvent::HoverEnter:
- case QEvent::HoverLeave:
- case QEvent::HoverMove:
- QQuickItemPrivate::get(item)->deliverHoverEvent(static_cast<QHoverEvent *>(e));
- break;
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
- if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
- e->accept();
- QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
- }
- break;
- case QEvent::DragEnter:
- case QEvent::DragMove:
- case QEvent::DragLeave:
- case QEvent::Drop:
- QQuickItemPrivate::get(item)->deliverDragEvent(e);
- break;
- default:
- break;
- }
-
- return false;
-}
-
-void QQuickCanvasPrivate::cleanupNodes()
-{
- for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
- delete cleanupNodeList.at(ii);
- cleanupNodeList.clear();
-}
-
-void QQuickCanvasPrivate::cleanupNodesOnShutdown(QQuickItem *item)
-{
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- if (p->itemNodeInstance) {
- delete p->itemNodeInstance;
- p->itemNodeInstance = 0;
- p->opacityNode = 0;
- p->clipNode = 0;
- p->groupNode = 0;
- p->paintNode = 0;
- }
-
- for (int ii = 0; ii < p->childItems.count(); ++ii)
- cleanupNodesOnShutdown(p->childItems.at(ii));
-}
-
-// This must be called from the render thread, with the main thread frozen
-void QQuickCanvasPrivate::cleanupNodesOnShutdown()
-{
- cleanupNodes();
-
- cleanupNodesOnShutdown(rootItem);
-}
-
-void QQuickCanvasPrivate::updateDirtyNodes()
-{
-#ifdef DIRTY_DEBUG
- qWarning() << "QQuickCanvasPrivate::updateDirtyNodes():";
-#endif
-
- cleanupNodes();
-
- QQuickItem *updateList = dirtyItemList;
- dirtyItemList = 0;
- if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
-
- while (updateList) {
- QQuickItem *item = updateList;
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
- itemPriv->removeFromDirtyList();
-
-#ifdef DIRTY_DEBUG
- qWarning() << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
-#endif
- updateDirtyNode(item);
- }
-}
-
-void QQuickCanvasPrivate::updateDirtyNode(QQuickItem *item)
-{
-#ifdef QML_RUNTIME_TESTING
- bool didFlash = false;
-#endif
-
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
- quint32 dirty = itemPriv->dirtyAttributes;
- itemPriv->dirtyAttributes = 0;
-
- if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
- (dirty & QQuickItemPrivate::Size && itemPriv->origin != QQuickItem::TopLeft &&
- (itemPriv->scale != 1. || itemPriv->rotation != 0.))) {
-
- QMatrix4x4 matrix;
-
- if (itemPriv->x != 0. || itemPriv->y != 0.)
- matrix.translate(itemPriv->x, itemPriv->y);
-
- for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
- itemPriv->transforms.at(ii)->applyTo(&matrix);
-
- if (itemPriv->scale != 1. || itemPriv->rotation != 0.) {
- QPointF origin = item->transformOriginPoint();
- matrix.translate(origin.x(), origin.y());
- if (itemPriv->scale != 1.)
- matrix.scale(itemPriv->scale, itemPriv->scale);
- if (itemPriv->rotation != 0.)
- matrix.rotate(itemPriv->rotation, 0, 0, 1);
- matrix.translate(-origin.x(), -origin.y());
- }
-
- itemPriv->itemNode()->setMatrix(matrix);
- }
-
- bool clipEffectivelyChanged = dirty & QQuickItemPrivate::Clip &&
- ((item->clip() == false) != (itemPriv->clipNode == 0));
- bool effectRefEffectivelyChanged = dirty & QQuickItemPrivate::EffectReference &&
- ((itemPriv->effectRefCount == 0) != (itemPriv->rootNode == 0));
-
- if (clipEffectivelyChanged) {
- QSGNode *parent = itemPriv->opacityNode ? (QSGNode *) itemPriv->opacityNode : (QSGNode *)itemPriv->itemNode();
- QSGNode *child = itemPriv->rootNode ? (QSGNode *)itemPriv->rootNode : (QSGNode *)itemPriv->groupNode;
-
- if (item->clip()) {
- Q_ASSERT(itemPriv->clipNode == 0);
- itemPriv->clipNode = new QQuickDefaultClipNode(item->boundingRect());
- itemPriv->clipNode->update();
-
- if (child)
- parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->clipNode);
- if (child)
- itemPriv->clipNode->appendChildNode(child);
-
- } else {
- Q_ASSERT(itemPriv->clipNode != 0);
- parent->removeChildNode(itemPriv->clipNode);
- if (child)
- itemPriv->clipNode->removeChildNode(child);
- delete itemPriv->clipNode;
- itemPriv->clipNode = 0;
- if (child)
- parent->appendChildNode(child);
- }
- }
-
- if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
- itemPriv->childContainerNode()->removeAllChildNodes();
-
- if (effectRefEffectivelyChanged) {
- QSGNode *parent = itemPriv->clipNode;
- if (!parent)
- parent = itemPriv->opacityNode;
- if (!parent)
- parent = itemPriv->itemNode();
- QSGNode *child = itemPriv->groupNode;
-
- if (itemPriv->effectRefCount) {
- Q_ASSERT(itemPriv->rootNode == 0);
- itemPriv->rootNode = new QSGRootNode;
-
- if (child)
- parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->rootNode);
- if (child)
- itemPriv->rootNode->appendChildNode(child);
- } else {
- Q_ASSERT(itemPriv->rootNode != 0);
- parent->removeChildNode(itemPriv->rootNode);
- if (child)
- itemPriv->rootNode->removeChildNode(child);
- delete itemPriv->rootNode;
- itemPriv->rootNode = 0;
- if (child)
- parent->appendChildNode(child);
- }
- }
-
- if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
- QSGNode *groupNode = itemPriv->groupNode;
- if (groupNode)
- groupNode->removeAllChildNodes();
-
- QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
- int ii = 0;
-
- for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
- if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
- continue;
- if (childPrivate->itemNode()->parent())
- childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
-
- itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
- }
- itemPriv->beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
-
- if (itemPriv->paintNode)
- itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
-
- for (; ii < orderedChildren.count(); ++ii) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
- if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
- continue;
- if (childPrivate->itemNode()->parent())
- childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
-
- itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
- }
- }
-
- if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode) {
- itemPriv->clipNode->setRect(item->boundingRect());
- itemPriv->clipNode->update();
- }
-
- if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible | QQuickItemPrivate::HideReference)) {
- qreal opacity = itemPriv->explicitVisible && itemPriv->hideRefCount == 0
- ? itemPriv->opacity : qreal(0);
-
- if (opacity != 1 && !itemPriv->opacityNode) {
- itemPriv->opacityNode = new QSGOpacityNode;
-
- QSGNode *parent = itemPriv->itemNode();
- QSGNode *child = itemPriv->clipNode;
- if (!child)
- child = itemPriv->rootNode;
- if (!child)
- child = itemPriv->groupNode;
-
- if (child)
- parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->opacityNode);
- if (child)
- itemPriv->opacityNode->appendChildNode(child);
- }
- if (itemPriv->opacityNode)
- itemPriv->opacityNode->setOpacity(opacity);
- }
-
- if (dirty & QQuickItemPrivate::ContentUpdateMask) {
-
- if (itemPriv->flags & QQuickItem::ItemHasContents) {
- updatePaintNodeData.transformNode = itemPriv->itemNode();
- itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
-
- Q_ASSERT(itemPriv->paintNode == 0 ||
- itemPriv->paintNode->parent() == 0 ||
- itemPriv->paintNode->parent() == itemPriv->childContainerNode());
-
- if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
- if (itemPriv->beforePaintNode)
- itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->beforePaintNode);
- else
- itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
- }
- } else if (itemPriv->paintNode) {
- delete itemPriv->paintNode;
- itemPriv->paintNode = 0;
- }
- }
-
-#ifndef QT_NO_DEBUG
- // Check consistency.
- const QSGNode *nodeChain[] = {
- itemPriv->itemNodeInstance,
- itemPriv->opacityNode,
- itemPriv->clipNode,
- itemPriv->rootNode,
- itemPriv->groupNode,
- itemPriv->paintNode,
- };
-
- int ip = 0;
- for (;;) {
- while (ip < 5 && nodeChain[ip] == 0)
- ++ip;
- if (ip == 5)
- break;
- int ic = ip + 1;
- while (ic < 5 && nodeChain[ic] == 0)
- ++ic;
- const QSGNode *parent = nodeChain[ip];
- const QSGNode *child = nodeChain[ic];
- if (child == 0) {
- Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
- } else {
- Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
- Q_ASSERT(child->parent() == parent);
- bool containsChild = false;
- for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
- containsChild |= (n == child);
- Q_ASSERT(containsChild);
- }
- ip = ic;
- }
-#endif
-
-#ifdef QML_RUNTIME_TESTING
- if (itemPriv->sceneGraphContext()->isFlashModeEnabled()) {
- QSGFlashNode *flash = new QSGFlashNode();
- flash->setRect(item->boundingRect());
- itemPriv->childContainerNode()->appendChildNode(flash);
- didFlash = true;
- }
- Q_Q(QQuickCanvas);
- if (didFlash) {
- q->maybeUpdate();
- }
-#endif
-
-}
-
-void QQuickCanvas::maybeUpdate()
-{
- Q_D(QQuickCanvas);
-
- if (d->thread && d->thread->isRunning())
- d->thread->maybeUpdate();
-}
-
-/*!
- \fn void QSGEngine::sceneGraphInitialized();
-
- This signal is emitted when the scene graph has been initialized.
-
- This signal will be emitted from the scene graph rendering thread.
- */
-
-/*!
- Returns the QSGEngine used for this scene.
-
- The engine will only be available once the scene graph has been
- initialized. Register for the sceneGraphEngine() signal to get
- notification about this.
-
- \deprecated
- */
-
-QSGEngine *QQuickCanvas::sceneGraphEngine() const
-{
- Q_D(const QQuickCanvas);
- qWarning("QQuickCanvas::sceneGraphEngine() is deprecated, use members of QQuickCanvas instead");
- if (d->context && d->context->isReady())
- return d->engine;
- return 0;
-}
-
-
-
-/*!
- Sets the render target for this canvas to be \a fbo.
-
- The specified fbo must be created in the context of the canvas
- or one that shares with it.
-
- \warning
- This function can only be called from the thread doing
- the rendering.
- */
-
-void QQuickCanvas::setRenderTarget(QOpenGLFramebufferObject *fbo)
-{
- Q_D(QQuickCanvas);
- if (d->context && d->context && QThread::currentThread() != d->context->thread()) {
- qWarning("QQuickCanvas::setRenderThread: Cannot set render target from outside the rendering thread");
- return;
- }
-
- d->renderTarget = fbo;
-}
-
-
-
-/*!
- Returns the render target for this canvas.
-
- The default is to render to the surface of the canvas, in which
- case the render target is 0.
- */
-QOpenGLFramebufferObject *QQuickCanvas::renderTarget() const
-{
- Q_D(const QQuickCanvas);
- return d->renderTarget;
-}
-
-
-/*!
- Grabs the contents of the framebuffer and returns it as an image.
-
- This function might not work if the view is not visible.
-
- \warning Calling this function will cause performance problems.
-
- \warning This function can only be called from the GUI thread.
- */
-QImage QQuickCanvas::grabFrameBuffer()
-{
- Q_D(QQuickCanvas);
- return d->thread ? d->thread->grab() : QImage();
-}
-
-/*!
- Returns an incubation controller that splices incubation between frames
- for this canvas. QQuickView automatically installs this controller for you,
- otherwise you will need to install it yourself using \l{QDeclarativeEngine::setIncubationController}
-
- The controller is owned by the canvas and will be destroyed when the canvas
- is deleted.
-*/
-QDeclarativeIncubationController *QQuickCanvas::incubationController() const
-{
- Q_D(const QQuickCanvas);
-
- if (!d->incubationController)
- d->incubationController = new QQuickCanvasIncubationController(const_cast<QQuickCanvasPrivate *>(d));
- return d->incubationController;
-}
-
-
-
-/*!
- \enum QQuickCanvas::CreateTextureOption
-
- The CreateTextureOption enums are used to customize a texture is wrapped.
-
- \value TextureHasAlphaChannel The texture has an alpha channel and should
- be drawn using blending.
-
- \value TextureHasMipmaps The texture has mipmaps and can be drawn with
- mipmapping enabled.
-
- \value TextureOwnsGLTexture The texture object owns the texture id and
- will delete the GL texture when the texture object is deleted.
- */
-
-/*!
- \fn void QQuickCanvas::beforeRendering()
-
- This signal is emitted before the scene starts rendering.
-
- Combined with the modes for clearing the background, this option
- can be used to paint using raw GL under QML content.
-
- The GL context used for rendering the scene graph will be bound
- at this point.
-
- Since this signal is emitted from the scene graph rendering thread, the receiver should
- be on the scene graph thread or the connection should be Qt::DirectConnection.
-
-*/
-
-/*!
- \fn void QQuickCanvas::afterRendering()
-
- This signal is emitted after the scene has completed rendering, before swapbuffers is called.
-
- This signal can be used to paint using raw GL on top of QML content,
- or to do screen scraping of the current frame buffer.
-
- The GL context used for rendering the scene graph will be bound at this point.
-
- Since this signal is emitted from the scene graph rendering thread, the receiver should
- be on the scene graph thread or the connection should be Qt::DirectConnection.
- */
-
-
-
-/*!
- Sets weither the scene graph rendering of QML should clear the color buffer
- before it starts rendering to \a enbled.
-
- By disabling clearing of the color buffer, it is possible to do GL painting
- under the scene graph.
-
- The color buffer is cleared by default.
-
- \sa beforeRendering()
- */
-
-void QQuickCanvas::setClearBeforeRendering(bool enabled)
-{
- Q_D(QQuickCanvas);
- d->clearBeforeRendering = enabled;
-}
-
-
-
-/*!
- Returns weither clearing of the color buffer is done before rendering or not.
- */
-
-bool QQuickCanvas::clearBeforeRendering() const
-{
- Q_D(const QQuickCanvas);
- return d->clearBeforeRendering;
-}
-
-
-
-/*!
- Creates a new QSGTexture from the supplied \a image. If the image has an
- alpha channel, the corresponding texture will have an alpha channel.
-
- The caller of the function is responsible for deleting the returned texture.
- The actual GL texture will be deleted when the texture object is deleted.
-
- \warning This function will return 0 if the scene graph has not yet been
- initialized.
-
- This function can be called both from the GUI thread and the rendering thread.
-
- \sa sceneGraphInitialized()
- */
-
-QSGTexture *QQuickCanvas::createTextureFromImage(const QImage &image) const
-{
- Q_D(const QQuickCanvas);
- if (d->context)
- return d->context->createTexture(image);
- else
- return 0;
-}
-
-
-
-/*!
- Creates a new QSGTexture object from an existing GL texture \a id.
-
- The caller of the function is responsible for deleting the returned texture.
-
- Use \a options to customize the texture attributes.
-
- \warning This function will return 0 if the scenegraph has not yet been
- initialized.
-
- \sa sceneGraphInitialized()
- */
-QSGTexture *QQuickCanvas::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
-{
- Q_D(const QQuickCanvas);
- if (d->context) {
- QSGPlainTexture *texture = new QSGPlainTexture();
- texture->setTextureId(id);
- texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
- texture->setHasMipmaps(options & TextureHasMipmaps);
- texture->setOwnsTexture(options & TextureOwnsGLTexture);
- texture->setTextureSize(size);
- return texture;
- }
- return 0;
-}
-
-
-/*!
- Sets the color used to clear the opengl context to \a color.
-
- Setting the clear color has no effect when clearing is disabled.
-
- \sa setClearBeforeRendering()
- */
-
-void QQuickCanvas::setClearColor(const QColor &color)
-{
- if (color == d_func()->clearColor)
- return;
- d_func()->clearColor = color;
- emit clearColorChanged(color);
-}
-
-
-
-/*!
- Returns the color used to clear the opengl context.
- */
-
-QColor QQuickCanvas::clearColor() const
-{
- return d_func()->clearColor;
-}
-
-
-
-void QQuickCanvasRenderLoop::createGLContext()
-{
- gl = new QOpenGLContext();
- gl->setFormat(renderer->requestedFormat());
- gl->create();
-}
-
-void QQuickCanvasRenderThread::run()
-{
-#ifdef THREAD_DEBUG
- qDebug("QML Rendering Thread Started");
-#endif
-
- if (!glContext()) {
- createGLContext();
- makeCurrent();
- initializeSceneGraph();
- } else {
- makeCurrent();
- }
-
- while (!shouldExit) {
- lock();
-
- bool sizeChanged = false;
- isExternalUpdatePending = false;
-
- if (renderedSize != windowSize) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: window has changed size...\n");
-#endif
- glViewport(0, 0, windowSize.width(), windowSize.height());
- sizeChanged = true;
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: preparing to sync...\n");
-#endif
-
- if (!isGuiBlocked) {
- isGuiBlockPending = true;
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: aquired sync lock...\n");
-#endif
- allowMainThreadProcessingFlag = false;
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
-#ifdef THREAD_DEBUG
- printf(" RenderThread: going to sleep...\n");
-#endif
- wait();
-
- isGuiBlockPending = false;
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: Doing locked sync\n");
-#endif
-#ifdef QQUICK_CANVAS_TIMING
- if (qquick_canvas_timing)
- threadTimer.start();
-#endif
- inSync = true;
- syncSceneGraph();
- inSync = false;
-
- // Wake GUI after sync to let it continue animating and event processing.
- allowMainThreadProcessingFlag = true;
- wake();
- unlock();
-#ifdef THREAD_DEBUG
- printf(" RenderThread: sync done\n");
-#endif
-#ifdef QQUICK_CANVAS_TIMING
- if (qquick_canvas_timing)
- syncTime = threadTimer.elapsed();
-#endif
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: rendering... %d x %d\n", windowSize.width(), windowSize.height());
-#endif
-
- renderSceneGraph(windowSize);
-#ifdef QQUICK_CANVAS_TIMING
- if (qquick_canvas_timing)
- renderTime = threadTimer.elapsed() - syncTime;
-#endif
-
- // The content of the target buffer is undefined after swap() so grab needs
- // to happen before swap();
- if (doGrab) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: doing a grab...\n");
-#endif
- grabContent = qt_gl_read_framebuffer(windowSize, false, false);
- doGrab = false;
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: wait for swap...\n");
-#endif
-
- swapBuffers();
-#ifdef THREAD_DEBUG
- printf(" RenderThread: swap complete...\n");
-#endif
-#ifdef QQUICK_CANVAS_TIMING
- if (qquick_canvas_timing) {
- swapTime = threadTimer.elapsed() - renderTime;
- qDebug() << "- Breakdown of frame time: sync:" << syncTime
- << "ms render:" << renderTime << "ms swap:" << swapTime
- << "ms total:" << swapTime + renderTime << "ms";
- }
-#endif
-
- lock();
- isPaintCompleted = true;
- if (sizeChanged)
- renderedSize = windowSize;
-
- // Wake the GUI thread now that rendering is complete, to signal that painting
- // is done, resizing is done or grabbing is completed. For grabbing, we're
- // signalling this much later than needed (we could have done it before swap)
- // but we don't want to lock an extra time.
- wake();
-
- if (!animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
-#ifdef THREAD_DEBUG
- printf(" RenderThread: nothing to do, going to sleep...\n");
-#endif
- isRenderBlocked = true;
- wait();
- isRenderBlocked = false;
- }
-
- unlock();
-
- QCoreApplication::processEvents();
-
- // Process any "deleteLater" objects...
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- }
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: deleting all outstanding nodes\n");
-#endif
- cleanupNodesOnShutdown();
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: render loop exited... Good Night!\n");
-#endif
-
- doneCurrent();
-
- lock();
- hasExited = true;
-#ifdef THREAD_DEBUG
- printf(" RenderThread: waking GUI for final sleep..\n");
-#endif
- wake();
- unlock();
-
-#ifdef THREAD_DEBUG
- printf(" RenderThread: All done...\n");
-#endif
-}
-
-
-
-bool QQuickCanvasRenderThread::event(QEvent *e)
-{
- Q_ASSERT(QThread::currentThread() == qApp->thread());
-
- if (e->type() == QEvent::User) {
- if (!syncAlreadyHappened)
- sync(false);
-
- syncAlreadyHappened = false;
-
- if (animationRunning && animationDriver()) {
-#ifdef THREAD_DEBUG
- qDebug("GUI: Advancing animations...\n");
-#endif
-
- animationDriver()->advance();
-
-#ifdef THREAD_DEBUG
- qDebug("GUI: Animations advanced...\n");
-#endif
- }
-
- return true;
- }
-
- return QThread::event(e);
-}
-
-
-
-void QQuickCanvasRenderThread::exhaustSyncEvent()
-{
- if (isGuiBlockPending) {
- sync(true);
- syncAlreadyHappened = true;
- }
-}
-
-
-
-void QQuickCanvasRenderThread::sync(bool guiAlreadyLocked)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event");
-#endif
- if (!guiAlreadyLocked)
- lockInGui();
-
- renderThreadAwakened = false;
-
- polishItems();
-
- wake();
- wait();
-
- if (!guiAlreadyLocked)
- unlockInGui();
-}
-
-
-
-
-/*!
- Acquires the mutex for the GUI thread. The function uses the isGuiBlocked
- variable to keep track of how many recursion levels the gui is locked with.
- We only actually acquire the mutex for the first level to avoid deadlocking
- ourselves.
- */
-
-void QQuickCanvasRenderThread::lockInGui()
-{
- // We must avoid recursive locking in the GUI thread, hence we
- // only lock when we are the first one to try to block.
- if (!isGuiBlocked)
- lock();
-
- isGuiBlocked++;
-
-#ifdef THREAD_DEBUG
- printf("GUI: aquired lock... %d\n", isGuiBlocked);
-#endif
-}
-
-
-
-void QQuickCanvasRenderThread::unlockInGui()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: releasing lock... %d\n", isGuiBlocked);
-#endif
- --isGuiBlocked;
- if (!isGuiBlocked)
- unlock();
-}
-
-
-
-
-void QQuickCanvasRenderThread::animationStarted()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: animationStarted()\n");
-#endif
-
- lockInGui();
-
- animationRunning = true;
-
- if (isRenderBlocked)
- wake();
-
- unlockInGui();
-}
-
-
-
-void QQuickCanvasRenderThread::animationStopped()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: animationStopped()...\n");
-#endif
-
- lockInGui();
- animationRunning = false;
- unlockInGui();
-}
-
-
-void QQuickCanvasRenderThread::paint()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: paint called..\n");
-#endif
-
- lockInGui();
- exhaustSyncEvent();
-
- isPaintCompleted = false;
- while (isRunning() && !isPaintCompleted) {
- if (isRenderBlocked)
- wake();
- wait();
- }
- unlockInGui();
-}
-
-
-
-void QQuickCanvasRenderThread::resize(const QSize &size)
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Resize Event: %dx%d\n", size.width(), size.height());
-#endif
-
- if (!isRunning()) {
- windowSize = size;
- return;
- }
-
- lockInGui();
- exhaustSyncEvent();
-
- windowSize = size;
-
- while (isRunning() && renderedSize != windowSize) {
- if (isRenderBlocked)
- wake();
- wait();
- }
- unlockInGui();
-}
-
-
-
-void QQuickCanvasRenderThread::startRendering()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: Starting Render Thread\n");
-#endif
- hasExited = false;
- shouldExit = false;
- isGuiBlocked = 0;
- isGuiBlockPending = false;
- start();
-}
-
-
-
-void QQuickCanvasRenderThread::stopRendering()
-{
-#ifdef THREAD_DEBUG
- printf("GUI: stopping render thread\n");
-#endif
-
- lockInGui();
- exhaustSyncEvent();
- shouldExit = true;
-
- if (isRenderBlocked) {
-#ifdef THREAD_DEBUG
- printf("GUI: waking up render thread\n");
-#endif
- wake();
- }
-
- while (!hasExited) {
-#ifdef THREAD_DEBUG
- printf("GUI: waiting for render thread to have exited..\n");
-#endif
- wait();
- }
-
- unlockInGui();
-
-#ifdef THREAD_DEBUG
- printf("GUI: waiting for render thread to terminate..\n");
-#endif
- // Actually wait for the thread to terminate. Otherwise we can delete it
- // too early and crash.
- QThread::wait();
-
-#ifdef THREAD_DEBUG
- printf("GUI: thread has terminated and we're all good..\n");
-#endif
-
-}
-
-
-
-QImage QQuickCanvasRenderThread::grab()
-{
- if (!isRunning())
- return QImage();
-
- if (QThread::currentThread() != qApp->thread()) {
- qWarning("QQuickCanvas::grabFrameBuffer: can only be called from the GUI thread");
- return QImage();
- }
-
-#ifdef THREAD_DEBUG
- printf("GUI: doing a pixelwise grab..\n");
-#endif
-
- lockInGui();
- exhaustSyncEvent();
-
- doGrab = true;
- isPaintCompleted = false;
- while (isRunning() && !isPaintCompleted) {
- if (isRenderBlocked)
- wake();
- wait();
- }
-
- QImage grabbed = grabContent;
- grabContent = QImage();
-
- unlockInGui();
-
- return grabbed;
-}
-
-
-
-void QQuickCanvasRenderThread::maybeUpdate()
-{
- Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || inSync,
- "QQuickCanvas::update",
- "Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
-
- if (inSync) {
- isExternalUpdatePending = true;
-
- } else if (!renderThreadAwakened) {
-#ifdef THREAD_DEBUG
- printf("GUI: doing update...\n");
-#endif
- renderThreadAwakened = true;
- lockInGui();
- isExternalUpdatePending = true;
- if (isRenderBlocked)
- wake();
- unlockInGui();
- }
-}
-
-
-#include "moc_qquickcanvas.cpp"
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickcanvas.h b/src/declarative/items/qquickcanvas.h
deleted file mode 100644
index c27776f234..0000000000
--- a/src/declarative/items/qquickcanvas.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCANVAS_H
-#define QQUICKCANVAS_H
-
-#include <QtCore/qmetatype.h>
-#include <QtGui/qopengl.h>
-#include <QtGui/qwindow.h>
-#include <QtGui/qevent.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGEngine;
-class QQuickItem;
-class QSGTexture;
-class QInputMethodEvent;
-class QQuickCanvasPrivate;
-class QOpenGLFramebufferObject;
-class QDeclarativeIncubationController;
-class QInputMethodEvent;
-
-class Q_DECLARATIVE_EXPORT QQuickCanvas : public QWindow
-{
- Q_OBJECT
- Q_PRIVATE_PROPERTY(QQuickCanvas::d_func(), QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
- Q_PROPERTY(QColor color READ clearColor WRITE setClearColor NOTIFY clearColorChanged)
- Q_CLASSINFO("DefaultProperty", "data")
- Q_DECLARE_PRIVATE(QQuickCanvas)
-public:
- enum CreateTextureOption {
- TextureHasAlphaChannel = 0x0001,
- TextureHasMipmaps = 0x0002,
- TextureOwnsGLTexture = 0x0004
- };
-
- Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
-
- QQuickCanvas(QWindow *parent = 0);
-
- virtual ~QQuickCanvas();
-
- QQuickItem *rootItem() const;
- QQuickItem *activeFocusItem() const;
-
- QQuickItem *mouseGrabberItem() const;
-
- bool sendEvent(QQuickItem *, QEvent *);
-
- QSGEngine *sceneGraphEngine() const;
-
- void setVSyncAnimations(bool enabled);
- bool vsyncAnimations() const;
-
- QImage grabFrameBuffer();
-
- void setRenderTarget(QOpenGLFramebufferObject *fbo);
- QOpenGLFramebufferObject *renderTarget() const;
-
- QDeclarativeIncubationController *incubationController() const;
-
- // Scene graph specific functions
- QSGTexture *createTextureFromImage(const QImage &image) const;
- QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption(0)) const;
-
- void setClearBeforeRendering(bool enabled);
- bool clearBeforeRendering() const;
-
- void setClearColor(const QColor &color);
- QColor clearColor() const;
-
- QOpenGLContext *openglContext() const;
-
-Q_SIGNALS:
- void frameSwapped();
- void sceneGraphInitialized();
- void beforeRendering();
- void afterRendering();
- void clearColorChanged(const QColor &);
-
-protected:
- QQuickCanvas(QQuickCanvasPrivate &dd, QWindow *parent = 0);
-
- virtual void exposeEvent(QExposeEvent *);
- virtual void resizeEvent(QResizeEvent *);
-
- virtual void showEvent(QShowEvent *);
- virtual void hideEvent(QHideEvent *);
-
- virtual void focusInEvent(QFocusEvent *);
- virtual void focusOutEvent(QFocusEvent *);
-
- virtual bool event(QEvent *);
- virtual void keyPressEvent(QKeyEvent *);
- virtual void keyReleaseEvent(QKeyEvent *);
- virtual void mousePressEvent(QMouseEvent *);
- virtual void mouseReleaseEvent(QMouseEvent *);
- virtual void mouseDoubleClickEvent(QMouseEvent *);
- virtual void mouseMoveEvent(QMouseEvent *);
-#ifndef QT_NO_WHEELEVENT
- virtual void wheelEvent(QWheelEvent *);
-#endif
-
-private Q_SLOTS:
- void maybeUpdate();
- void animationStarted();
- void animationStopped();
-
-private:
- friend class QQuickItem;
- friend class QQuickCanvasRenderLoop;
- Q_DISABLE_COPY(QQuickCanvas)
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QQuickCanvas *)
-
-QT_END_HEADER
-
-#endif // QQUICKCANVAS_H
-
diff --git a/src/declarative/items/qquickcanvas_p.h b/src/declarative/items/qquickcanvas_p.h
deleted file mode 100644
index 13ca288cb1..0000000000
--- a/src/declarative/items/qquickcanvas_p.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCANVAS_P_H
-#define QQUICKCANVAS_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qquickitem.h"
-#include "qquickcanvas.h"
-#include <private/qdeclarativeguard_p.h>
-
-#include <private/qsgcontext_p.h>
-#include <private/qquickdrag_p.h>
-
-#include <QtCore/qthread.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qwaitcondition.h>
-#include <private/qwindow_p.h>
-#include <private/qopengl_p.h>
-#include <qopenglcontext.h>
-#include <QtGui/qopenglframebufferobject.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qinputpanel.h>
-
-QT_BEGIN_NAMESPACE
-
-//Make it easy to identify and customize the root item if needed
-
-class QQuickRootItem : public QQuickItem
-{
- Q_OBJECT
-public:
- QQuickRootItem();
-public Q_SLOTS:
- void setWidth(int w) {QQuickItem::setWidth(qreal(w));}
- void setHeight(int h) {QQuickItem::setHeight(qreal(h));}
-};
-
-class QQuickItemPrivate;
-class QQuickCanvasPrivate;
-
-class QTouchEvent;
-class QQuickCanvasRenderLoop;
-class QQuickCanvasIncubationController;
-
-class QQuickCanvasPrivate : public QWindowPrivate
-{
-public:
- Q_DECLARE_PUBLIC(QQuickCanvas)
-
- static inline QQuickCanvasPrivate *get(QQuickCanvas *c) { return c->d_func(); }
-
- QQuickCanvasPrivate();
- virtual ~QQuickCanvasPrivate();
-
- void init(QQuickCanvas *);
- void initRootItem();//Currently only used if items added in QML
-
- QQuickRootItem *rootItem;
- QDeclarativeListProperty<QObject> data();
-
- QQuickItem *activeFocusItem;
- QQuickItem *mouseGrabberItem;
- QQuickDragGrabber dragGrabber;
-
- // Mouse positions are saved in widget coordinates
- QPointF lastMousePosition;
- void translateTouchEvent(QTouchEvent *touchEvent);
- static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
- bool deliverInitialMousePressEvent(QQuickItem *, QMouseEvent *);
- bool deliverMouseEvent(QMouseEvent *);
- bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *);
- bool deliverWheelEvent(QQuickItem *, QWheelEvent *);
- bool deliverTouchPoints(QQuickItem *, QTouchEvent *, const QList<QTouchEvent::TouchPoint> &, QSet<int> *,
- QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *);
- bool deliverTouchEvent(QTouchEvent *);
- bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
- bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted);
- bool clearHover();
- void deliverDragEvent(QQuickDragGrabber *, QEvent *);
- bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
-
- QList<QQuickItem*> hoverItems;
- enum FocusOption {
- DontChangeFocusProperty = 0x01,
- };
- Q_DECLARE_FLAGS(FocusOptions, FocusOption)
-
- void setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
- void clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
- void notifyFocusChangesRecur(QQuickItem **item, int remaining);
-
- void updateInputMethodData();
- void updateFocusItemTransform();
-
- void dirtyItem(QQuickItem *);
- void cleanup(QSGNode *);
-
- void initializeSceneGraph();
- void polishItems();
- void syncSceneGraph();
- void renderSceneGraph(const QSize &size);
-
- QQuickItem::UpdatePaintNodeData updatePaintNodeData;
-
- QQuickItem *dirtyItemList;
- QList<QSGNode *> cleanupNodeList;
-
- QSet<QQuickItem *> itemsToPolish;
-
- void updateDirtyNodes();
- void cleanupNodes();
- void cleanupNodesOnShutdown();
- bool updateEffectiveOpacity(QQuickItem *);
- void updateEffectiveOpacityRoot(QQuickItem *, qreal);
- void updateDirtyNode(QQuickItem *);
-
- QSGEngine *engine;
- QSGContext *context;
- QColor clearColor;
-
- uint vsyncAnimations : 1;
- uint clearBeforeRendering : 1;
-
- QQuickCanvasRenderLoop *thread;
- QSize widgetSize;
- QSize viewportSize;
-
- QAnimationDriver *animationDriver;
-
- QOpenGLFramebufferObject *renderTarget;
-
- QHash<int, QQuickItem *> itemForTouchPointId;
-
- mutable QQuickCanvasIncubationController *incubationController;
-
-private:
- static void cleanupNodesOnShutdown(QQuickItem *);
-};
-
-class QQuickCanvasRenderLoop
-{
-public:
- QQuickCanvasRenderLoop()
- : d(0)
- , renderer(0)
- , gl(0)
- {
- }
- virtual ~QQuickCanvasRenderLoop()
- {
- delete gl;
- }
-
- friend class QQuickCanvasPrivate;
-
- virtual void paint() = 0;
- virtual void resize(const QSize &size) = 0;
- virtual void startRendering() = 0;
- virtual void stopRendering() = 0;
- virtual QImage grab() = 0;
- virtual void setWindowSize(const QSize &size) = 0;
- virtual void maybeUpdate() = 0;
- virtual bool isRunning() const = 0;
- virtual void animationStarted() = 0;
- virtual void animationStopped() = 0;
- virtual void moveContextToThread(QSGContext *) { }
- virtual bool *allowMainThreadProcessing() { return 0; }
-
-protected:
- void initializeSceneGraph() { d->initializeSceneGraph(); }
- void syncSceneGraph() { d->syncSceneGraph(); }
- void cleanupNodesOnShutdown() { d->cleanupNodesOnShutdown(); }
- void renderSceneGraph(const QSize &size) { d->renderSceneGraph(size); }
- void polishItems() { d->polishItems(); }
- QAnimationDriver *animationDriver() const { return d->animationDriver; }
-
- inline QOpenGLContext *glContext() const { return gl; }
- void createGLContext();
- void makeCurrent() { gl->makeCurrent(renderer); }
- void doneCurrent() { gl->doneCurrent(); }
- void swapBuffers() {
- gl->swapBuffers(renderer);
- emit renderer->frameSwapped();
- }
-
-private:
- QQuickCanvasPrivate *d;
- QQuickCanvas *renderer;
-
- QOpenGLContext *gl;
-};
-
-class QQuickCanvasRenderThread : public QThread, public QQuickCanvasRenderLoop
-{
- Q_OBJECT
-public:
- QQuickCanvasRenderThread()
- : mutex(QMutex::NonRecursive)
- , allowMainThreadProcessingFlag(true)
- , animationRunning(false)
- , isGuiBlocked(0)
- , isPaintCompleted(false)
- , isGuiBlockPending(false)
- , isRenderBlocked(false)
- , isExternalUpdatePending(false)
- , syncAlreadyHappened(false)
- , inSync(false)
- , doGrab(false)
- , shouldExit(false)
- , hasExited(false)
- , renderThreadAwakened(false)
- {}
-
- inline void lock() { mutex.lock(); }
- inline void unlock() { mutex.unlock(); }
- inline void wait() { condition.wait(&mutex); }
- inline void wake() { condition.wakeOne(); }
-
- void lockInGui();
- void unlockInGui();
-
- void paint();
- void resize(const QSize &size);
- void startRendering();
- void stopRendering();
- void exhaustSyncEvent();
- void sync(bool guiAlreadyLocked);
- bool isRunning() const { return QThread::isRunning(); }
- void setWindowSize(const QSize &size) { windowSize = size; }
- void maybeUpdate();
- void moveContextToThread(QSGContext *c) { c->moveToThread(this); }
- bool *allowMainThreadProcessing() { return &allowMainThreadProcessingFlag; }
-
- bool event(QEvent *);
-
- QImage grab();
-
-public slots:
- void animationStarted();
- void animationStopped();
-
-public:
- QMutex mutex;
- QWaitCondition condition;
-
- bool allowMainThreadProcessingFlag;
-
- QSize windowSize;
- QSize renderedSize;
-
- uint animationRunning: 1;
- int isGuiBlocked;
- uint isPaintCompleted : 1;
- uint isGuiBlockPending : 1;
- uint isRenderBlocked : 1;
- uint isExternalUpdatePending : 1;
- uint syncAlreadyHappened : 1;
- uint inSync : 1;
- uint doGrab : 1;
- uint shouldExit : 1;
- uint hasExited : 1;
- uint renderThreadAwakened : 1;
-
- QImage grabContent;
-
- void run();
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickCanvasPrivate::FocusOptions)
-
-QT_END_NAMESPACE
-
-#endif // QQUICKCANVAS_P_H
diff --git a/src/declarative/items/qquickclipnode_p.h b/src/declarative/items/qquickclipnode_p.h
deleted file mode 100644
index 0323c9a24a..0000000000
--- a/src/declarative/items/qquickclipnode_p.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKCLIPNODE_P_H
-#define QQUICKCLIPNODE_P_H
-
-#include <qsgnode.h>
-
-class QQuickDefaultClipNode : public QSGClipNode
-{
-public:
- QQuickDefaultClipNode(const QRectF &);
-
- void setRect(const QRectF &);
- QRectF rect() const { return m_rect; }
-
- void setRadius(qreal radius);
- qreal radius() const { return m_radius; }
-
- virtual void update();
-
-private:
- void updateGeometry();
- QRectF m_rect;
- qreal m_radius;
-
- uint m_dirty_geometry : 1;
- uint m_reserved : 31;
-
- QSGGeometry m_geometry;
-};
-
-#endif // QQUICKCLIPNODE_P_H
diff --git a/src/declarative/items/qquickdrag.cpp b/src/declarative/items/qquickdrag.cpp
deleted file mode 100644
index 9dcc4ac7fe..0000000000
--- a/src/declarative/items/qquickdrag.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickdrag_p.h"
-
-#include <private/qquickitem_p.h>
-#include <private/qquickevents_p_p.h>
-#include <private/qquickitemchangelistener_p.h>
-#include <private/qv8engine_p.h>
-
-#include <QtGui/qevent.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickDragAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
-{
- Q_DECLARE_PUBLIC(QQuickDragAttached)
-public:
- static QQuickDragAttachedPrivate *get(QQuickDragAttached *attached) {
- return static_cast<QQuickDragAttachedPrivate *>(QObjectPrivate::get(attached)); }
-
- QQuickDragAttachedPrivate()
- : attachedItem(0)
- , mimeData(0)
- , proposedAction(Qt::MoveAction)
- , supportedActions(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction)
- , active(false)
- , listening(false)
- {
- }
-
- void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
- void start() { start(supportedActions); }
- void start(Qt::DropActions supportedActions);
- void setTarget(QQuickItem *item);
-
- QQuickDragGrabber dragGrabber;
-
- QDeclarativeGuard<QObject> source;
- QDeclarativeGuard<QObject> target;
- QQuickItem *attachedItem;
- QQuickDragMimeData *mimeData;
- Qt::DropAction proposedAction;
- Qt::DropActions supportedActions;
- bool active : 1;
- bool listening : 1;
- QPointF hotSpot;
- QStringList keys;
-};
-
-/*!
- \qmlclass Drag QQuickDrag
- \inqmlmodule QtQuick 2
- \brief The Drag attached property provides drag and drop events for moved Items.
-
- Using the Drag attached property any Item can made a source of drag and drop
- events within a scene.
-
- When a drag is \l active on an item any change in that items position will
- generate a drag events that will be sent to any DropArea that intersects
- the with new position of the item. Other items which implement drag and
- drop event handlers can also receive these events.
-
- The following snippet shows how an item can be dragged with a MouseArea.
- However, dragging is not limited to mouse drags, anything that can move an item
- can generate drag events, this can include touch events, animations and bindings.
-
- \snippet doc/src/snippets/declarative/drag.qml 0
-
- A drag can be terminated either by canceling it with Drag.cancel() or setting
- Drag.active to false, or it can be terminated with a drop event by calling
- Drag.drop(). If the drop event is accepted Drag.drop() will return the
- \l {supportedActions}{drop action} chosen by the recipient of the event,
- otherwise it will return Qt.IgnoreAction.
-
-*/
-
-void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_Q(QQuickDragAttached);
- if (newGeometry.topLeft() == oldGeometry.topLeft() || !active)
- return;
-
- if (QQuickCanvas *canvas = attachedItem->canvas()) {
- QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
- QDragMoveEvent event(scenePos, mimeData->m_supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
- QQuickDropEventEx::setProposedAction(&event, proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
- if (target != dragGrabber.target()) {
- target = dragGrabber.target();
- emit q->targetChanged();
- }
- }
-}
-
-QQuickDragAttached::QQuickDragAttached(QObject *parent)
- : QObject(*new QQuickDragAttachedPrivate, parent)
-{
- Q_D(QQuickDragAttached);
- d->attachedItem = qobject_cast<QQuickItem *>(parent);
- d->source = d->attachedItem;
-}
-
-QQuickDragAttached::~QQuickDragAttached()
-{
- Q_D(QQuickDragAttached);
- delete d->mimeData;
-}
-
-/*!
- \qmlattachedproperty bool QtQuick2::Drag::active
-
- This property holds whether a drag event sequence is currently active.
-
- Setting this property to true will send a QDragEnter event to the scene
- with the item's current position. Setting it to false will send a
- QDragLeave event.
-
- While a drag is active any change in an item's position will send a QDragMove
- event with item's new position to the scene.
-*/
-
-bool QQuickDragAttached::isActive() const
-{
- Q_D(const QQuickDragAttached);
- return d->active;
-}
-
-void QQuickDragAttached::setActive(bool active)
-{
- Q_D(QQuickDragAttached);
- if (d->active != active) {
- if (active)
- d->start(d->supportedActions);
- else
- cancel();
- }
-}
-
-/*!
- \qmlattachedproperty Object QtQuick2::Drag::source
-
- This property holds an object that is identified to recipients of drag events as
- the source of the events. By default this is the item Drag property is attached to.
-
- Changes to source while a Drag is active don't take effect until a new drag is started.
-*/
-
-QObject *QQuickDragAttached::source() const
-{
- Q_D(const QQuickDragAttached);
- return d->source;
-}
-
-void QQuickDragAttached::setSource(QObject *item)
-{
- Q_D(QQuickDragAttached);
- if (d->source != item) {
- d->source = item;
- emit sourceChanged();
- }
-}
-
-void QQuickDragAttached::resetSource()
-{
- Q_D(QQuickDragAttached);
- if (d->source != d->attachedItem) {
- d->source = d->attachedItem;
- emit sourceChanged();
- }
-}
-
-/*!
- \qmlattachedproperty Object QtQuick2::Drag::target
-
- While a drag is active this property holds the last object to accept an
- enter event from the dragged item, if the current drag position doesn't
- intersect any accepting targets it is null.
-
- When a drag is not active this property holds the object that accepted
- the drop event that ended the drag, if no object accepted the drop or
- the drag was canceled the target will then be null.
-*/
-
-QObject *QQuickDragAttached::target() const
-{
- Q_D(const QQuickDragAttached);
- return d->target;
-}
-
-/*!
- \qmlattachedproperty QPointF QtQuick2::Drag::hotSpot
-
- This property holds the drag position relative to the top left of the item.
-
- By default this is (0, 0).
-
- Changes to hotSpot will take effect when the next event is sent.
-*/
-
-QPointF QQuickDragAttached::hotSpot() const
-{
- Q_D(const QQuickDragAttached);
- return d->hotSpot;
-}
-
-void QQuickDragAttached::setHotSpot(const QPointF &hotSpot)
-{
- Q_D(QQuickDragAttached);
- if (d->hotSpot != hotSpot) {
- d->hotSpot = hotSpot;
- emit hotSpotChanged();
- // Send a move event if active?
- }
-}
-
-/*!
- \qmlattachedproperty stringlist QtQuick2::Drag::keys
-
- This property holds a list of keys that can be used by a DropArea to filter drag events.
-
- Changes to keys while a Drag is active don't take effect until a new drag is started.
-*/
-
-QStringList QQuickDragAttached::keys() const
-{
- Q_D(const QQuickDragAttached);
- return d->keys;
-}
-
-void QQuickDragAttached::setKeys(const QStringList &keys)
-{
- Q_D(QQuickDragAttached);
- if (d->keys != keys) {
- d->keys = keys;
- emit keysChanged();
- }
-}
-
-/*!
- \qmlattachedproperty flags QtQuick2::Drag::supportedActions
-
- This property holds return values of Drag.drop() supported by the drag source.
-
- Changes to supportedActions while a Drag is active don't take effect
- until a new drag is started.
-*/
-
-Qt::DropActions QQuickDragAttached::supportedActions() const
-{
- Q_D(const QQuickDragAttached);
- return d->supportedActions;
-}
-
-void QQuickDragAttached::setSupportedActions(Qt::DropActions actions)
-{
- Q_D(QQuickDragAttached);
- if (d->supportedActions != actions) {
- d->supportedActions = actions;
- emit supportedActionsChanged();
- }
-}
-
-/*!
- \qmlattachedproperty enumeration QtQuick2::Drag::proposedAction
-
- This property holds an action that is recommended by the drag source as a
- return value from Drag.drop().
-
- Changes to proposedAction will take effect when the next event is sent.
-*/
-
-Qt::DropAction QQuickDragAttached::proposedAction() const
-{
- Q_D(const QQuickDragAttached);
- return d->proposedAction;
-}
-
-void QQuickDragAttached::setProposedAction(Qt::DropAction action)
-{
- Q_D(QQuickDragAttached);
- if (d->proposedAction != action) {
- d->proposedAction = action;
- emit proposedActionChanged();
- // send a move event with the new default action if active?
- }
-}
-
-void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
-{
- Q_Q(QQuickDragAttached);
- Q_ASSERT(!active);
-
- if (QQuickCanvas *canvas = attachedItem ? attachedItem->canvas() : 0) {
- if (!mimeData)
- mimeData = new QQuickDragMimeData;
- if (!listening) {
- QQuickItemPrivate::get(attachedItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- listening = true;
- }
-
- mimeData->m_source = source;
- mimeData->m_supportedActions = supportedActions;
- mimeData->m_keys = keys;
- active = true;
-
- QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
- QDragEnterEvent event(scenePos, supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
- QQuickDropEventEx::setProposedAction(&event, proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
-
- emit q->activeChanged();
- if (target != dragGrabber.target()) {
- target = dragGrabber.target();
- emit q->targetChanged();
- }
- }
-}
-
-/*!
- \qmlattachedmethod void QtQuick2::Drag::start(flags supportedActions)
-
- Starts sending drag events.
-
- The optional \a supportedActions argument can be used to override the \l supportedActions
- property for the started sequence.
-*/
-
-void QQuickDragAttached::start(QDeclarativeV8Function *args)
-{
- Q_D(QQuickDragAttached);
- if (d->active)
- cancel();
-
- Qt::DropActions supportedActions = d->supportedActions;
- // check arguments for supportedActions, maybe data?
- if (args->Length() >= 1) {
- v8::Local<v8::Value> v = (*args)[0];
- if (v->IsInt32())
- supportedActions = Qt::DropActions(v->Int32Value());
- }
-
- d->start(supportedActions);
-}
-
-/*!
- \qmlattachedmethod enum QtQuick2::Drag::drop()
-
- Ends a drag sequence by sending a drop event to the target item.
-
- Returns the action accepted by the target item. If the target item or a parent doesn't accept
- the drop event then Qt.IgnoreAction will be returned.
-
- The returned drop action may be one of:
-
- \list
- \o Qt.CopyAction Copy the data to the target
- \o Qt.MoveAction Move the data from the source to the target
- \o Qt.LinkAction Create a link from the source to the target.
- \o Qt.IgnoreAction Ignore the action (do nothing with the data).
- \endlist
-
-*/
-
-int QQuickDragAttached::drop()
-{
- Q_D(QQuickDragAttached);
- Qt::DropAction acceptedAction = Qt::IgnoreAction;
-
- if (!d->active)
- return acceptedAction;
-
- QObject *target = 0;
-
- if (QQuickCanvas *canvas = d->attachedItem->canvas()) {
- QPoint scenePos = d->attachedItem->mapToScene(d->hotSpot).toPoint();
-
- QDropEvent event(
- scenePos, d->mimeData->m_supportedActions, d->mimeData, Qt::NoButton, Qt::NoModifier);
- QQuickDropEventEx::setProposedAction(&event, d->proposedAction);
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
-
- if (event.isAccepted()) {
- acceptedAction = event.dropAction();
- target = d->dragGrabber.target();
- }
- }
-
- d->active = false;
- if (d->target != target) {
- d->target = target;
- emit targetChanged();
- }
-
- emit activeChanged();
- return acceptedAction;
-}
-
-/*!
- \qmlattachedmethod void QtQuick2::Drag::cancel()
-
- Ends a drag sequence.
-*/
-
-void QQuickDragAttached::cancel()
-{
- Q_D(QQuickDragAttached);
- if (!d->active)
- return;
-
- if (QQuickCanvas *canvas = d->attachedItem->canvas()) {
- QDragLeaveEvent event;
- QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
- }
-
- d->active = false;
- if (d->target) {
- d->target = 0;
- emit targetChanged();
- }
- emit activeChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickdrag_p.h b/src/declarative/items/qquickdrag_p.h
deleted file mode 100644
index 1d950299d7..0000000000
--- a/src/declarative/items/qquickdrag_p.h
+++ /dev/null
@@ -1,208 +0,0 @@
-// Commit: c6e6a35aeb8794d68a3ca0c4e27a3a1181c066b5
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKDRAG_P_H
-#define QQUICKDRAG_P_H
-
-#include <qquickitem.h>
-
-#include <private/qv8engine_p.h>
-
-#include <QtCore/qmimedata.h>
-#include <QtCore/qstringlist.h>
-
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QQuickDrag;
-class QQuickDragPrivate;
-
-class QQuickDragGrabber
-{
- class Item : public QDeclarativeGuard<QQuickItem>
- {
- public:
- Item(QQuickItem *item) : QDeclarativeGuard<QQuickItem>(item) {}
-
- QIntrusiveListNode node;
- protected:
- void objectDestroyed(QQuickItem *) { delete this; }
- };
-
- typedef QIntrusiveList<Item, &Item::node> ItemList;
-
-public:
- QQuickDragGrabber() : m_target(0) {}
- ~QQuickDragGrabber() { while (!m_items.isEmpty()) delete m_items.first(); }
-
-
- QObject *target() const
- {
- if (m_target)
- return m_target;
- else if (!m_items.isEmpty())
- return *m_items.first();
- else
- return 0;
- }
- void setTarget(QObject *target) { m_target = target; }
- void resetTarget() { m_target = 0; }
-
- typedef ItemList::iterator iterator;
- iterator begin() { return m_items.begin(); }
- iterator end() { return m_items.end(); }
-
- void grab(QQuickItem *item) { m_items.insert(new Item(item)); }
- iterator release(iterator at) { Item *item = *at; at = at.erase(); delete item; return at; }
-
-private:
-
- ItemList m_items;
- QObject *m_target;
-};
-
-class QQuickDropEventEx : public QDropEvent
-{
-public:
- void setProposedAction(Qt::DropAction action) { default_action = action; drop_action = action; }
-
- static void setProposedAction(QDropEvent *event, Qt::DropAction action) {
- static_cast<QQuickDropEventEx *>(event)->setProposedAction(action);
- }
-
- void copyActions(const QDropEvent &from) {
- default_action = from.proposedAction(); drop_action = from.dropAction(); }
-
- static void copyActions(QDropEvent *to, const QDropEvent &from) {
- static_cast<QQuickDropEventEx *>(to)->copyActions(from);
- }
-};
-
-class QQuickDragMimeData : public QMimeData
-{
- Q_OBJECT
-public:
- QQuickDragMimeData()
- : m_source(0)
- {
- }
-
- QStringList keys() const { return m_keys; }
- QObject *source() const { return m_source; }
-
-private:
- QObject *m_source;
- Qt::DropActions m_supportedActions;
- QStringList m_keys;
-
- friend class QQuickDragAttached;
- friend class QQuickDragAttachedPrivate;
-};
-
-class QDeclarativeV8Function;
-
-class QQuickDragAttachedPrivate;
-class QQuickDragAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
- Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
- Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
- Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
- Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
- Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
-public:
- QQuickDragAttached(QObject *parent);
- ~QQuickDragAttached();
-
- bool isActive() const;
- void setActive(bool active);
-
- QObject *source() const;
- void setSource(QObject *item);
- void resetSource();
-
- QObject *target() const;
-
- QPointF hotSpot() const;
- void setHotSpot(const QPointF &hotSpot);
-
- QStringList keys() const;
- void setKeys(const QStringList &keys);
-
- Qt::DropActions supportedActions() const;
- void setSupportedActions(Qt::DropActions actions);
-
- Qt::DropAction proposedAction() const;
- void setProposedAction(Qt::DropAction action);
-
- Q_INVOKABLE int drop();
-
-public Q_SLOTS:
- void start(QDeclarativeV8Function *);
- void cancel();
-
-Q_SIGNALS:
- void activeChanged();
- void sourceChanged();
- void targetChanged();
- void hotSpotChanged();
- void keysChanged();
- void supportedActionsChanged();
- void proposedActionChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickDragAttached)
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/items/qquickdroparea_p.h b/src/declarative/items/qquickdroparea_p.h
deleted file mode 100644
index 31e2bd7813..0000000000
--- a/src/declarative/items/qquickdroparea_p.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKDROPAREA_P_H
-#define QQUICKDROPAREA_P_H
-
-#include "qquickitem.h"
-
-#include <private/qdeclarativeguard_p.h>
-#include <private/qv8engine_p.h>
-
-#include <QtGui/qevent.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickDropAreaPrivate;
-class QQuickDropEvent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(qreal x READ x)
- Q_PROPERTY(qreal y READ y)
- Q_PROPERTY(QObject *source READ source)
- Q_PROPERTY(QStringList keys READ keys)
- Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions)
- Q_PROPERTY(Qt::DropAction action READ action WRITE setAction RESET resetAction)
- Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
-public:
- QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
-
- qreal x() const { return event->pos().x(); }
- qreal y() const { return event->pos().y(); }
-
- QObject *source();
-
- Qt::DropActions supportedActions() const { return event->possibleActions(); }
- Qt::DropAction action() const { return event->dropAction(); }
- void setAction(Qt::DropAction action) { event->setDropAction(action); }
- void resetAction() { event->setDropAction(event->proposedAction()); }
-
- QStringList keys() const;
-
- bool accepted() const { return event->isAccepted(); }
- void setAccepted(bool accepted) { event->setAccepted(accepted); }
-
- Q_INVOKABLE void accept(QDeclarativeV8Function *);
-
-private:
- QQuickDropAreaPrivate *d;
- QDropEvent *event;
-};
-
-class QQuickDropAreaDrag : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(qreal x READ x NOTIFY positionChanged)
- Q_PROPERTY(qreal y READ y NOTIFY positionChanged)
- Q_PROPERTY(QObject *source READ source NOTIFY sourceChanged)
-public:
- QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent = 0);
- ~QQuickDropAreaDrag();
-
- qreal x() const;
- qreal y() const;
- QObject *source() const;
-
-Q_SIGNALS:
- void positionChanged();
- void sourceChanged();
-
-private:
- QQuickDropAreaPrivate *d;
-
- friend class QQuickDropArea;
- friend class QQuickDropAreaPrivate;
-};
-
-class QQuickDropAreaPrivate;
-class Q_AUTOTEST_EXPORT QQuickDropArea : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(bool containsDrag READ containsDrag NOTIFY containsDragChanged)
- Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
- Q_PROPERTY(QQuickDropAreaDrag *drag READ drag CONSTANT)
-
-public:
- QQuickDropArea(QQuickItem *parent=0);
- ~QQuickDropArea();
-
- bool containsDrag() const;
- void setContainsDrag(bool drag);
-
- QStringList keys() const;
- void setKeys(const QStringList &keys);
-
- QQuickDropAreaDrag *drag();
-
-Q_SIGNALS:
- void containsDragChanged();
- void keysChanged();
- void sourceChanged();
-
- void entered(QQuickDropEvent *drag);
- void exited();
- void positionChanged(QQuickDropEvent *drag);
- void dropped(QQuickDropEvent *drop);
-
-protected:
- void dragMoveEvent(QDragMoveEvent *event);
- void dragEnterEvent(QDragEnterEvent *event);
- void dragLeaveEvent(QDragLeaveEvent *event);
- void dropEvent(QDropEvent *event);
-
-private:
- Q_DISABLE_COPY(QQuickDropArea)
- Q_DECLARE_PRIVATE(QQuickDropArea)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickDropEvent)
-QML_DECLARE_TYPE(QQuickDropArea)
-
-QT_END_HEADER
-
-#endif // QQUICKDROPAREA_P_H
diff --git a/src/declarative/items/qquickevents_p_p.h b/src/declarative/items/qquickevents_p_p.h
deleted file mode 100644
index cc5ed4f01e..0000000000
--- a/src/declarative/items/qquickevents_p_p.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKEVENTS_P_P_H
-#define QQUICKEVENTS_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-#include <QtGui/qevent.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickKeyEvent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int key READ key)
- Q_PROPERTY(QString text READ text)
- Q_PROPERTY(int modifiers READ modifiers)
- Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
- Q_PROPERTY(int count READ count)
- Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
-
-public:
- QQuickKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
- : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
- QQuickKeyEvent(const QKeyEvent &ke)
- : event(ke) { event.setAccepted(false); }
-
- int key() const { return event.key(); }
- QString text() const { return event.text(); }
- int modifiers() const { return event.modifiers(); }
- bool isAutoRepeat() const { return event.isAutoRepeat(); }
- int count() const { return event.count(); }
-
- bool isAccepted() { return event.isAccepted(); }
- void setAccepted(bool accepted) { event.setAccepted(accepted); }
-
-private:
- QKeyEvent event;
-};
-
-// used in QtLocation
-class Q_DECLARATIVE_EXPORT QQuickMouseEvent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(qreal x READ x)
- Q_PROPERTY(qreal y READ y)
- Q_PROPERTY(int button READ button)
- Q_PROPERTY(int buttons READ buttons)
- Q_PROPERTY(int modifiers READ modifiers)
- Q_PROPERTY(bool wasHeld READ wasHeld)
- Q_PROPERTY(bool isClick READ isClick)
- Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
-
-public:
- QQuickMouseEvent(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
- , bool isClick=false, bool wasHeld=false)
- : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
- , _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
-
- qreal x() const { return _x; }
- qreal y() const { return _y; }
- int button() const { return _button; }
- int buttons() const { return _buttons; }
- int modifiers() const { return _modifiers; }
- bool wasHeld() const { return _wasHeld; }
- bool isClick() const { return _isClick; }
-
- // only for internal usage
- void setX(qreal x) { _x = x; }
- void setY(qreal y) { _y = y; }
- void setPosition(const QPointF &point) { _x = point.x(); _y = point.y(); }
-
- bool isAccepted() { return _accepted; }
- void setAccepted(bool accepted) { _accepted = accepted; }
-
-private:
- qreal _x;
- qreal _y;
- Qt::MouseButton _button;
- Qt::MouseButtons _buttons;
- Qt::KeyboardModifiers _modifiers;
- bool _wasHeld;
- bool _isClick;
- bool _accepted;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickKeyEvent)
-QML_DECLARE_TYPE(QQuickMouseEvent)
-
-#endif // QQUICKEVENTS_P_P_H
diff --git a/src/declarative/items/qquickflickable_p.h b/src/declarative/items/qquickflickable_p.h
deleted file mode 100644
index 658db94846..0000000000
--- a/src/declarative/items/qquickflickable_p.h
+++ /dev/null
@@ -1,277 +0,0 @@
-// Commit: 1bcddaaf318fc37c71c5191913f3487c49444ec6
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKFLICKABLE_P_H
-#define QQUICKFLICKABLE_P_H
-
-#include "qquickitem.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickFlickablePrivate;
-class QQuickFlickableVisibleArea;
-class Q_DECLARATIVE_EXPORT QQuickFlickable : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
- Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
- Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
- Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
- Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT)
-
- Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
- Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
- Q_PROPERTY(qreal yOrigin READ yOrigin NOTIFY yOriginChanged)
-
- Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
- Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
- Q_PROPERTY(qreal xOrigin READ xOrigin NOTIFY xOriginChanged)
-
- Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
- Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
-
- Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged)
- Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged)
- Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
- Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
- Q_PROPERTY(bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
- Q_PROPERTY(bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
- Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
- Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
- Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
- Q_PROPERTY(bool dragging READ isDragging NOTIFY draggingChanged)
- Q_PROPERTY(bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
- Q_PROPERTY(bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
- Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged)
-
- Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
- Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
-
- Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
- Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
- Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged)
- Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged)
-
- Q_PROPERTY(QQuickFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
-
- Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
-
- Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
- Q_PROPERTY(QDeclarativeListProperty<QQuickItem> flickableChildren READ flickableChildren)
- Q_CLASSINFO("DefaultProperty", "flickableData")
-
- Q_ENUMS(FlickableDirection)
- Q_ENUMS(BoundsBehavior)
-
-public:
- QQuickFlickable(QQuickItem *parent=0);
- ~QQuickFlickable();
-
- QDeclarativeListProperty<QObject> flickableData();
- QDeclarativeListProperty<QQuickItem> flickableChildren();
-
- enum BoundsBehavior { StopAtBounds, DragOverBounds, DragAndOvershootBounds };
- BoundsBehavior boundsBehavior() const;
- void setBoundsBehavior(BoundsBehavior);
-
- qreal contentWidth() const;
- void setContentWidth(qreal);
-
- qreal contentHeight() const;
- void setContentHeight(qreal);
-
- qreal contentX() const;
- virtual void setContentX(qreal pos);
-
- qreal contentY() const;
- virtual void setContentY(qreal pos);
-
- qreal topMargin() const;
- void setTopMargin(qreal m);
-
- qreal bottomMargin() const;
- void setBottomMargin(qreal m);
-
- qreal leftMargin() const;
- void setLeftMargin(qreal m);
-
- qreal rightMargin() const;
- void setRightMargin(qreal m);
-
- virtual qreal yOrigin() const;
- virtual qreal xOrigin() const;
-
- bool isMoving() const;
- bool isMovingHorizontally() const;
- bool isMovingVertically() const;
- bool isFlicking() const;
- bool isFlickingHorizontally() const;
- bool isFlickingVertically() const;
- bool isDragging() const;
- bool isDraggingHorizontally() const;
- bool isDraggingVertically() const;
-
- int pressDelay() const;
- void setPressDelay(int delay);
-
- qreal maximumFlickVelocity() const;
- void setMaximumFlickVelocity(qreal);
-
- qreal flickDeceleration() const;
- void setFlickDeceleration(qreal);
-
- bool isInteractive() const;
- void setInteractive(bool);
-
- qreal horizontalVelocity() const;
- qreal verticalVelocity() const;
-
- bool isAtXEnd() const;
- bool isAtXBeginning() const;
- bool isAtYEnd() const;
- bool isAtYBeginning() const;
-
- QQuickItem *contentItem();
-
- enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
- FlickableDirection flickableDirection() const;
- void setFlickableDirection(FlickableDirection);
-
- bool pixelAligned() const;
- void setPixelAligned(bool align);
-
- Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center);
- Q_INVOKABLE void returnToBounds();
-
-Q_SIGNALS:
- void contentWidthChanged();
- void contentHeightChanged();
- void contentXChanged();
- void contentYChanged();
- void topMarginChanged();
- void bottomMarginChanged();
- void leftMarginChanged();
- void rightMarginChanged();
- void yOriginChanged();
- void xOriginChanged();
- void movingChanged();
- void movingHorizontallyChanged();
- void movingVerticallyChanged();
- void flickingChanged();
- void flickingHorizontallyChanged();
- void flickingVerticallyChanged();
- void draggingChanged();
- void draggingHorizontallyChanged();
- void draggingVerticallyChanged();
- void horizontalVelocityChanged();
- void verticalVelocityChanged();
- void isAtBoundaryChanged();
- void flickableDirectionChanged();
- void interactiveChanged();
- void boundsBehaviorChanged();
- void maximumFlickVelocityChanged();
- void flickDecelerationChanged();
- void pressDelayChanged();
- void movementStarted();
- void movementEnded();
- void flickStarted();
- void flickEnded();
- void dragStarted();
- void dragEnded();
- void pixelAlignedChanged();
-
-protected:
- virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void wheelEvent(QWheelEvent *event);
- virtual void timerEvent(QTimerEvent *event);
-
- QQuickFlickableVisibleArea *visibleArea();
-
-protected Q_SLOTS:
- virtual void ticked();
- void movementStarting();
- void movementEnding();
-
-protected:
- void movementXEnding();
- void movementYEnding();
- virtual qreal minXExtent() const;
- virtual qreal minYExtent() const;
- virtual qreal maxXExtent() const;
- virtual qreal maxYExtent() const;
- qreal vWidth() const;
- qreal vHeight() const;
- virtual void componentComplete();
- virtual void viewportMoved();
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- void mouseUngrabEvent();
- bool sendMouseEvent(QMouseEvent *event);
-
- bool xflick() const;
- bool yflick() const;
- void cancelFlick();
-
-protected:
- QQuickFlickable(QQuickFlickablePrivate &dd, QQuickItem *parent);
-
-private:
- Q_DISABLE_COPY(QQuickFlickable)
- Q_DECLARE_PRIVATE(QQuickFlickable)
- friend class QQuickFlickableVisibleArea;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickFlickable)
-
-QT_END_HEADER
-
-#endif // QQUICKFLICKABLE_P_H
diff --git a/src/declarative/items/qquickflipable_p.h b/src/declarative/items/qquickflipable_p.h
deleted file mode 100644
index 698ec0fcb2..0000000000
--- a/src/declarative/items/qquickflipable_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKFLIPABLE_P_H
-#define QQUICKFLIPABLE_P_H
-
-#include "qquickitem.h"
-
-#include <QtGui/qtransform.h>
-#include <QtGui/qvector3d.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickFlipablePrivate;
-class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem
-{
- Q_OBJECT
-
- Q_ENUMS(Side)
- Q_PROPERTY(QQuickItem *front READ front WRITE setFront NOTIFY frontChanged)
- Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged)
- Q_PROPERTY(Side side READ side NOTIFY sideChanged)
- //### flipAxis
- //### flipRotation
-public:
- QQuickFlipable(QQuickItem *parent=0);
- ~QQuickFlipable();
-
- QQuickItem *front();
- void setFront(QQuickItem *);
-
- QQuickItem *back();
- void setBack(QQuickItem *);
-
- enum Side { Front, Back };
- Side side() const;
-
-Q_SIGNALS:
- void frontChanged();
- void backChanged();
- void sideChanged();
-
-protected:
- virtual void updatePolish();
-
-private Q_SLOTS:
- void retransformBack();
-
-private:
- Q_DISABLE_COPY(QQuickFlipable)
- Q_DECLARE_PRIVATE(QQuickFlipable)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickFlipable)
-
-QT_END_HEADER
-
-#endif // QQUICKFLIPABLE_P_H
diff --git a/src/declarative/items/qquickfocusscope_p.h b/src/declarative/items/qquickfocusscope_p.h
deleted file mode 100644
index ff1a389f62..0000000000
--- a/src/declarative/items/qquickfocusscope_p.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKFOCUSSCOPE_P_H
-#define QQUICKFOCUSSCOPE_P_H
-
-#include "qquickitem.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_AUTOTEST_EXPORT QQuickFocusScope : public QQuickItem
-{
- Q_OBJECT
-public:
- QQuickFocusScope(QQuickItem *parent=0);
- virtual ~QQuickFocusScope();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickFocusScope)
-
-QT_END_HEADER
-
-#endif // QQUICKFOCUSSCOPE_P_H
diff --git a/src/declarative/items/qquickgridview_p.h b/src/declarative/items/qquickgridview_p.h
deleted file mode 100644
index b02c0a8350..0000000000
--- a/src/declarative/items/qquickgridview_p.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Commit: 95814418f9d6adeba365c795462e8afb00138211
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKGRIDVIEW_P_H
-#define QQUICKGRIDVIEW_P_H
-
-#include "qquickitemview_p.h"
-
-#include <private/qdeclarativeguard_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class QQuickVisualModel;
-class QQuickGridViewAttached;
-class QQuickGridViewPrivate;
-class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickGridView)
-
- Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
- Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
- Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
-
- Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
-
- Q_ENUMS(SnapMode)
- Q_ENUMS(Flow)
- Q_CLASSINFO("DefaultProperty", "data")
-
-public:
- QQuickGridView(QQuickItem *parent=0);
- ~QQuickGridView();
-
- virtual void setHighlightFollowsCurrentItem(bool);
- virtual void setHighlightMoveDuration(int);
-
- enum Flow { LeftToRight, TopToBottom };
- Flow flow() const;
- void setFlow(Flow);
-
- qreal cellWidth() const;
- void setCellWidth(qreal);
-
- qreal cellHeight() const;
- void setCellHeight(qreal);
-
- enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
- SnapMode snapMode() const;
- void setSnapMode(SnapMode mode);
-
- static QQuickGridViewAttached *qmlAttachedProperties(QObject *);
-
-public Q_SLOTS:
- void moveCurrentIndexUp();
- void moveCurrentIndexDown();
- void moveCurrentIndexLeft();
- void moveCurrentIndexRight();
-
-Q_SIGNALS:
- void cellWidthChanged();
- void cellHeightChanged();
- void highlightMoveDurationChanged();
- void flowChanged();
- void snapModeChanged();
-
-protected:
- virtual void viewportMoved();
- virtual void keyPressEvent(QKeyEvent *);
-};
-
-class QQuickGridViewAttached : public QQuickItemViewAttached
-{
- Q_OBJECT
-public:
- QQuickGridViewAttached(QObject *parent)
- : QQuickItemViewAttached(parent), m_view(0) {}
- ~QQuickGridViewAttached() {}
-
- Q_PROPERTY(QQuickGridView *view READ view NOTIFY viewChanged)
- QQuickGridView *view() { return m_view; }
- void setView(QQuickGridView *view) {
- if (view != m_view) {
- m_view = view;
- emit viewChanged();
- }
- }
-
-Q_SIGNALS:
- void viewChanged();
-
-public:
- QDeclarativeGuard<QQuickGridView> m_view;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickGridView)
-QML_DECLARE_TYPEINFO(QQuickGridView, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-
-#endif // QQUICKGRIDVIEW_P_H
diff --git a/src/declarative/items/qquickimage.cpp b/src/declarative/items/qquickimage.cpp
deleted file mode 100644
index 46b8ea0915..0000000000
--- a/src/declarative/items/qquickimage.cpp
+++ /dev/null
@@ -1,746 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickimage_p.h"
-#include "qquickimage_p_p.h"
-
-#include <private/qsgtextureprovider_p.h>
-
-#include <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-#include <QtGui/qpainter.h>
-#include <qmath.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickImageTextureProvider : public QSGTextureProvider
-{
- Q_OBJECT
-public:
- QQuickImageTextureProvider()
- : m_texture(0)
- , m_smooth(false)
- {
- }
-
- QSGTexture *texture() const {
-
- if (m_texture && m_texture->isAtlasTexture())
- const_cast<QQuickImageTextureProvider *>(this)->m_texture = m_texture->removedFromAtlas();
-
- if (m_texture) {
- m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- m_texture->setMipmapFiltering(QSGTexture::Nearest);
- m_texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- m_texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
- }
- return m_texture;
- }
-
- friend class QQuickImage;
-
- QSGTexture *m_texture;
- bool m_smooth;
-};
-
-#include "qquickimage.moc"
-
-QQuickImagePrivate::QQuickImagePrivate()
- : fillMode(QQuickImage::Stretch)
- , paintedWidth(0)
- , paintedHeight(0)
- , pixmapChanged(false)
- , hAlign(QQuickImage::AlignHCenter)
- , vAlign(QQuickImage::AlignVCenter)
- , provider(0)
-{
-}
-
-/*!
- \qmlclass Image QQuickImage
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The Image element displays an image in a declarative user interface
- \inherits Item
-
- The Image element is used to display images in a declarative user interface.
-
- The source of the image is specified as a URL using the \l source property.
- Images can be supplied in any of the standard image formats supported by Qt,
- including bitmap formats such as PNG and JPEG, and vector graphics formats
- such as SVG. If you need to display animated images, use the \l AnimatedImage
- element.
-
- If the \l{Item::width}{width} and \l{Item::height}{height} properties are not
- specified, the Image element automatically uses the size of the loaded image.
- By default, specifying the width and height of the element causes the image
- to be scaled to that size. This behavior can be changed by setting the
- \l fillMode property, allowing the image to be stretched and tiled instead.
-
- \section1 Example Usage
-
- The following example shows the simplest usage of the Image element.
-
- \snippet doc/src/snippets/declarative/image.qml document
-
- \beginfloatleft
- \image declarative-qtlogo.png
- \endfloat
-
- \clearfloat
-
- \section1 Performance
-
- By default, locally available images are loaded immediately, and the user interface
- is blocked until loading is complete. If a large image is to be loaded, it may be
- preferable to load the image in a low priority thread, by enabling the \l asynchronous
- property.
-
- If the image is obtained from a network rather than a local resource, it is
- automatically loaded asynchronously, and the \l progress and \l status properties
- are updated as appropriate.
-
- Images are cached and shared internally, so if several Image elements have the same \l source,
- only one copy of the image will be loaded.
-
- \bold Note: Images are often the greatest user of memory in QML user interfaces. It is recommended
- that images which do not form part of the user interface have their
- size bounded via the \l sourceSize property. This is especially important for content
- that is loaded from external sources or provided by the user.
-
- \sa {declarative/imageelements/image}{Image example}, QDeclarativeImageProvider
-*/
-
-QQuickImage::QQuickImage(QQuickItem *parent)
- : QQuickImageBase(*(new QQuickImagePrivate), parent)
-{
-}
-
-QQuickImage::QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent)
- : QQuickImageBase(dd, parent)
-{
-}
-
-QQuickImage::~QQuickImage()
-{
- Q_D(QQuickImage);
- if (d->provider)
- d->provider->deleteLater();
-}
-
-void QQuickImagePrivate::setImage(const QImage &image)
-{
- Q_Q(QQuickImage);
- pix.setImage(image);
-
- q->pixmapChange();
- status = pix.isNull() ? QQuickImageBase::Null : QQuickImageBase::Ready;
-
- q->update();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Image::fillMode
-
- Set this property to define what happens when the source image has a different size
- than the item.
-
- \list
- \o Image.Stretch - the image is scaled to fit
- \o Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping
- \o Image.PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary
- \o Image.Tile - the image is duplicated horizontally and vertically
- \o Image.TileVertically - the image is stretched horizontally and tiled vertically
- \o Image.TileHorizontally - the image is stretched vertically and tiled horizontally
- \o Image.Pad - the image is not transformed
- \endlist
-
- \table
-
- \row
- \o \image declarative-qtlogo-stretch.png
- \o Stretch (default)
- \qml
- Image {
- width: 130; height: 100
- smooth: true
- source: "qtlogo.png"
- }
- \endqml
-
- \row
- \o \image declarative-qtlogo-preserveaspectfit.png
- \o PreserveAspectFit
- \qml
- Image {
- width: 130; height: 100
- fillMode: Image.PreserveAspectFit
- smooth: true
- source: "qtlogo.png"
- }
- \endqml
-
- \row
- \o \image declarative-qtlogo-preserveaspectcrop.png
- \o PreserveAspectCrop
- \qml
- Image {
- width: 130; height: 100
- fillMode: Image.PreserveAspectCrop
- smooth: true
- source: "qtlogo.png"
- clip: true
- }
- \endqml
-
- \row
- \o \image declarative-qtlogo-tile.png
- \o Tile
- \qml
- Image {
- width: 120; height: 120
- fillMode: Image.Tile
- source: "qtlogo.png"
- }
- \endqml
-
- \row
- \o \image declarative-qtlogo-tilevertically.png
- \o TileVertically
- \qml
- Image {
- width: 120; height: 120
- fillMode: Image.TileVertically
- smooth: true
- source: "qtlogo.png"
- }
- \endqml
-
- \row
- \o \image declarative-qtlogo-tilehorizontally.png
- \o TileHorizontally
- \qml
- Image {
- width: 120; height: 120
- fillMode: Image.TileHorizontally
- smooth: true
- source: "qtlogo.png"
- }
- \endqml
-
- \endtable
-
- Note that \c clip is \c false by default which means that the element might
- paint outside its bounding rectangle even if the fillMode is set to \c PreserveAspectCrop.
-
- \sa {declarative/imageelements/image}{Image example}
-*/
-QQuickImage::FillMode QQuickImage::fillMode() const
-{
- Q_D(const QQuickImage);
- return d->fillMode;
-}
-
-void QQuickImage::setFillMode(FillMode mode)
-{
- Q_D(QQuickImage);
- if (d->fillMode == mode)
- return;
- d->fillMode = mode;
- update();
- updatePaintedGeometry();
- emit fillModeChanged();
-}
-
-/*!
-
- \qmlproperty real QtQuick2::Image::paintedWidth
- \qmlproperty real QtQuick2::Image::paintedHeight
-
- These properties hold the size of the image that is actually painted.
- In most cases it is the same as \c width and \c height, but when using a
- \c fillMode \c PreserveAspectFit or \c fillMode \c PreserveAspectCrop
- \c paintedWidth or \c paintedHeight can be smaller or larger than
- \c width and \c height of the Image element.
-*/
-qreal QQuickImage::paintedWidth() const
-{
- Q_D(const QQuickImage);
- return d->paintedWidth;
-}
-
-qreal QQuickImage::paintedHeight() const
-{
- Q_D(const QQuickImage);
- return d->paintedHeight;
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Image::status
-
- This property holds the status of image loading. It can be one of:
- \list
- \o Image.Null - no image has been set
- \o Image.Ready - the image has been loaded
- \o Image.Loading - the image is currently being loaded
- \o Image.Error - an error occurred while loading the image
- \endlist
-
- Use this status to provide an update or respond to the status change in some way.
- For example, you could:
-
- \list
- \o Trigger a state change:
- \qml
- State { name: 'loaded'; when: image.status == Image.Ready }
- \endqml
-
- \o Implement an \c onStatusChanged signal handler:
- \qml
- Image {
- id: image
- onStatusChanged: if (image.status == Image.Ready) console.log('Loaded')
- }
- \endqml
-
- \o Bind to the status value:
- \qml
- Text { text: image.status == Image.Ready ? 'Loaded' : 'Not loaded' }
- \endqml
- \endlist
-
- \sa progress
-*/
-
-/*!
- \qmlproperty real QtQuick2::Image::progress
-
- This property holds the progress of image loading, from 0.0 (nothing loaded)
- to 1.0 (finished).
-
- \sa status
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Image::smooth
-
- Set this property if you want the image to be smoothly filtered when scaled or
- transformed. Smooth filtering gives better visual quality, but is slower. If
- the image is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the image is stationary on
- the screen. A common pattern when animating an image is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-*/
-
-/*!
- \qmlproperty QSize QtQuick2::Image::sourceSize
-
- This property holds the actual width and height of the loaded image.
-
- Unlike the \l {Item::}{width} and \l {Item::}{height} properties, which scale
- the painting of the image, this property sets the actual number of pixels
- stored for the loaded image so that large images do not use more
- memory than necessary. For example, this ensures the image in memory is no
- larger than 1024x1024 pixels, regardless of the Image's \l {Item::}{width} and
- \l {Item::}{height} values:
-
- \code
- Rectangle {
- width: ...
- height: ...
-
- Image {
- anchors.fill: parent
- source: "reallyBigImage.jpg"
- sourceSize.width: 1024
- sourceSize.height: 1024
- }
- }
- \endcode
-
- If the image's actual size is larger than the sourceSize, the image is scaled down.
- If only one dimension of the size is set to greater than 0, the
- other dimension is set in proportion to preserve the source image's aspect ratio.
- (The \l fillMode is independent of this.)
-
- If the source is an intrinsically scalable image (eg. SVG), this property
- determines the size of the loaded image regardless of intrinsic size.
- Avoid changing this property dynamically; rendering an SVG is \e slow compared
- to an image.
-
- If the source is a non-scalable image (eg. JPEG), the loaded image will
- be no greater than this property specifies. For some formats (currently only JPEG),
- the whole image will never actually be loaded into memory.
-
- Since QtQuick 1.1 the sourceSize can be cleared to the natural size of the image
- by setting sourceSize to \c undefined.
-
- \note \e {Changing this property dynamically causes the image source to be reloaded,
- potentially even from the network, if it is not in the disk cache.}
-*/
-
-/*!
- \qmlproperty url QtQuick2::Image::source
-
- Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
-
- The URL may be absolute, or relative to the URL of the component.
-
- \sa QDeclarativeImageProvider
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Image::asynchronous
-
- Specifies that images on the local filesystem should be loaded
- asynchronously in a separate thread. The default value is
- false, causing the user interface thread to block while the
- image is loaded. Setting \a asynchronous to true is useful where
- maintaining a responsive user interface is more desirable
- than having images immediately visible.
-
- Note that this property is only valid for images read from the
- local filesystem. Images loaded via a network resource (e.g. HTTP)
- are always loaded asynchronously.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Image::cache
-
- Specifies whether the image should be cached. The default value is
- true. Setting \a cache to false is useful when dealing with large images,
- to make sure that they aren't cached at the expense of small 'ui element' images.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Image::mirror
-
- This property holds whether the image should be horizontally inverted
- (effectively displaying a mirrored image).
-
- The default value is false.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::Image::horizontalAlignment
- \qmlproperty enumeration QtQuick2::Image::verticalAlignment
-
- Sets the horizontal and vertical alignment of the image. By default, the image is top-left aligned.
-
- The valid values for \c horizontalAlignment are \c Image.AlignLeft, \c Image.AlignRight and \c Image.AlignHCenter.
- The valid values for \c verticalAlignment are \c Image.AlignTop, \c Image.AlignBottom
- and \c Image.AlignVCenter.
-*/
-void QQuickImage::updatePaintedGeometry()
-{
- Q_D(QQuickImage);
-
- if (d->fillMode == PreserveAspectFit) {
- if (!d->pix.width() || !d->pix.height()) {
- setImplicitSize(0, 0);
- return;
- }
- qreal w = widthValid() ? width() : d->pix.width();
- qreal widthScale = w / qreal(d->pix.width());
- qreal h = heightValid() ? height() : d->pix.height();
- qreal heightScale = h / qreal(d->pix.height());
- if (widthScale <= heightScale) {
- d->paintedWidth = w;
- d->paintedHeight = widthScale * qreal(d->pix.height());
- } else if (heightScale < widthScale) {
- d->paintedWidth = heightScale * qreal(d->pix.width());
- d->paintedHeight = h;
- }
- qreal iHeight = (widthValid() && !heightValid()) ? d->paintedHeight : d->pix.height();
- qreal iWidth = (heightValid() && !widthValid()) ? d->paintedWidth : d->pix.width();
- setImplicitSize(iWidth, iHeight);
-
- } else if (d->fillMode == PreserveAspectCrop) {
- if (!d->pix.width() || !d->pix.height())
- return;
- qreal widthScale = width() / qreal(d->pix.width());
- qreal heightScale = height() / qreal(d->pix.height());
- if (widthScale < heightScale) {
- widthScale = heightScale;
- } else if (heightScale < widthScale) {
- heightScale = widthScale;
- }
-
- d->paintedHeight = heightScale * qreal(d->pix.height());
- d->paintedWidth = widthScale * qreal(d->pix.width());
- } else if (d->fillMode == Pad) {
- d->paintedWidth = d->pix.width();
- d->paintedHeight = d->pix.height();
- } else {
- d->paintedWidth = width();
- d->paintedHeight = height();
- }
- emit paintedGeometryChanged();
-}
-
-void QQuickImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- QQuickImageBase::geometryChanged(newGeometry, oldGeometry);
- updatePaintedGeometry();
-}
-
-QRectF QQuickImage::boundingRect() const
-{
- Q_D(const QQuickImage);
- return QRectF(0, 0, qMax(width(), d->paintedWidth), qMax(height(), d->paintedHeight));
-}
-
-QSGTextureProvider *QQuickImage::textureProvider() const
-{
- Q_D(const QQuickImage);
- if (!d->provider) {
- // Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(d->canvas
- && d->sceneGraphContext()
- && QThread::currentThread() == d->sceneGraphContext()->thread(),
- "QQuickImage::textureProvider",
- "Cannot be used outside the GUI thread");
- QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d);
- dd->provider = new QQuickImageTextureProvider;
- dd->provider->m_smooth = d->smooth;
- dd->provider->m_texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory());
- }
-
- return d->provider;
-}
-
-QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- Q_D(QQuickImage);
-
- QSGTexture *texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory());
-
- // Copy over the current texture state into the texture provider...
- if (d->provider) {
- d->provider->m_smooth = d->smooth;
- d->provider->m_texture = texture;
- }
-
- if (!texture || width() <= 0 || height() <= 0) {
- delete oldNode;
- return 0;
- }
-
- QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
- if (!node) {
- d->pixmapChanged = true;
- node = d->sceneGraphContext()->createImageNode();
- node->setTexture(texture);
- }
-
- if (d->pixmapChanged) {
- // force update the texture in the node to trigger reconstruction of
- // geometry and the likes when a atlas segment has changed.
- node->setTexture(0);
- node->setTexture(texture);
- d->pixmapChanged = false;
- }
-
- QRectF targetRect;
- QRectF sourceRect;
- QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge;
- QSGTexture::WrapMode vWrap = QSGTexture::ClampToEdge;
-
- qreal pixWidth = (d->fillMode == PreserveAspectFit) ? d->paintedWidth : d->pix.width();
- qreal pixHeight = (d->fillMode == PreserveAspectFit) ? d->paintedHeight : d->pix.height();
-
- int xOffset = 0;
- if (d->hAlign == QQuickImage::AlignHCenter)
- xOffset = qCeil((width() - pixWidth) / 2.);
- else if (d->hAlign == QQuickImage::AlignRight)
- xOffset = qCeil(width() - pixWidth);
-
- int yOffset = 0;
- if (d->vAlign == QQuickImage::AlignVCenter)
- yOffset = qCeil((height() - pixHeight) / 2.);
- else if (d->vAlign == QQuickImage::AlignBottom)
- yOffset = qCeil(height() - pixHeight);
-
- switch (d->fillMode) {
- default:
- case Stretch:
- targetRect = QRectF(0, 0, width(), height());
- sourceRect = d->pix.rect();
- break;
-
- case PreserveAspectFit:
- targetRect = QRectF(xOffset, yOffset, d->paintedWidth, d->paintedHeight);
- sourceRect = d->pix.rect();
- break;
-
- case PreserveAspectCrop: {
- targetRect = QRect(0, 0, width(), height());
- qreal wscale = width() / qreal(d->pix.width());
- qreal hscale = height() / qreal(d->pix.height());
-
- if (wscale > hscale) {
- int src = (hscale / wscale) * qreal(d->pix.height());
- int y = 0;
- if (d->vAlign == QQuickImage::AlignVCenter)
- y = qCeil((d->pix.height() - src) / 2.);
- else if (d->vAlign == QQuickImage::AlignBottom)
- y = qCeil(d->pix.height() - src);
- sourceRect = QRectF(0, y, d->pix.width(), src);
-
- } else {
- int src = (wscale / hscale) * qreal(d->pix.width());
- int x = 0;
- if (d->hAlign == QQuickImage::AlignHCenter)
- x = qCeil((d->pix.width() - src) / 2.);
- else if (d->hAlign == QQuickImage::AlignRight)
- x = qCeil(d->pix.width() - src);
- sourceRect = QRectF(x, 0, src, d->pix.height());
- }
- }
- break;
-
- case Tile:
- targetRect = QRectF(0, 0, width(), height());
- sourceRect = QRectF(-xOffset, -yOffset, width(), height());
- hWrap = QSGTexture::Repeat;
- vWrap = QSGTexture::Repeat;
- break;
-
- case TileHorizontally:
- targetRect = QRectF(0, 0, width(), height());
- sourceRect = QRectF(-xOffset, 0, width(), d->pix.height());
- hWrap = QSGTexture::Repeat;
- break;
-
- case TileVertically:
- targetRect = QRectF(0, 0, width(), height());
- sourceRect = QRectF(0, -yOffset, d->pix.width(), height());
- vWrap = QSGTexture::Repeat;
- break;
-
- case Pad:
- qreal w = qMin(qreal(d->pix.width()), width());
- qreal h = qMin(qreal(d->pix.height()), height());
- qreal x = (d->pix.width() > width()) ? -xOffset : 0;
- qreal y = (d->pix.height() > height()) ? -yOffset : 0;
- targetRect = QRectF(x + xOffset, y + yOffset, w, h);
- sourceRect = QRectF(x, y, w, h);
- break;
- };
-
- QRectF nsrect(sourceRect.x() / d->pix.width(),
- sourceRect.y() / d->pix.height(),
- sourceRect.width() / d->pix.width(),
- sourceRect.height() / d->pix.height());
-
- if (d->mirror) {
- qreal oldLeft = nsrect.left();
- nsrect.setLeft(nsrect.right());
- nsrect.setRight(oldLeft);
- }
-
- node->setHorizontalWrapMode(hWrap);
- node->setVerticalWrapMode(vWrap);
- node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
-
- node->setTargetRect(targetRect);
- node->setSourceRect(nsrect);
- node->update();
-
- return node;
-}
-
-void QQuickImage::pixmapChange()
-{
- Q_D(QQuickImage);
- // PreserveAspectFit calculates the implicit size differently so we
- // don't call our superclass pixmapChange(), since that would
- // result in the implicit size being set incorrectly, then updated
- // in updatePaintedGeometry()
- if (d->fillMode != PreserveAspectFit)
- QQuickImageBase::pixmapChange();
- updatePaintedGeometry();
- d->pixmapChanged = true;
-
- // When the pixmap changes, such as being deleted, we need to update the textures
- update();
-}
-
-QQuickImage::VAlignment QQuickImage::verticalAlignment() const
-{
- Q_D(const QQuickImage);
- return d->vAlign;
-}
-
-void QQuickImage::setVerticalAlignment(VAlignment align)
-{
- Q_D(QQuickImage);
- if (d->vAlign == align)
- return;
-
- d->vAlign = align;
- update();
- updatePaintedGeometry();
- emit verticalAlignmentChanged(align);
-}
-
-QQuickImage::HAlignment QQuickImage::horizontalAlignment() const
-{
- Q_D(const QQuickImage);
- return d->hAlign;
-}
-
-void QQuickImage::setHorizontalAlignment(HAlignment align)
-{
- Q_D(QQuickImage);
- if (d->hAlign == align)
- return;
-
- d->hAlign = align;
- update();
- updatePaintedGeometry();
- emit horizontalAlignmentChanged(align);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickimage_p.h b/src/declarative/items/qquickimage_p.h
deleted file mode 100644
index 0d1c8dcba3..0000000000
--- a/src/declarative/items/qquickimage_p.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKIMAGE_P_H
-#define QQUICKIMAGE_P_H
-
-#include "qquickimagebase_p.h"
-#include <private/qsgtextureprovider_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickImagePrivate;
-class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
-{
- Q_OBJECT
- Q_ENUMS(FillMode)
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
-
- Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
- Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
- Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
- Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged)
- Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
-
-public:
- QQuickImage(QQuickItem *parent=0);
- ~QQuickImage();
-
- enum HAlignment { AlignLeft = Qt::AlignLeft,
- AlignRight = Qt::AlignRight,
- AlignHCenter = Qt::AlignHCenter };
- enum VAlignment { AlignTop = Qt::AlignTop,
- AlignBottom = Qt::AlignBottom,
- AlignVCenter = Qt::AlignVCenter };
-
- enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad };
-
- FillMode fillMode() const;
- void setFillMode(FillMode);
-
- qreal paintedWidth() const;
- qreal paintedHeight() const;
-
- QRectF boundingRect() const;
-
- HAlignment horizontalAlignment() const;
- void setHorizontalAlignment(HAlignment align);
-
- VAlignment verticalAlignment() const;
- void setVerticalAlignment(VAlignment align);
-
- bool isTextureProvider() const { return true; }
- QSGTextureProvider *textureProvider() const;
-
-Q_SIGNALS:
- void fillModeChanged();
- void paintedGeometryChanged();
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
-
-protected:
- QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent);
- void pixmapChange();
- void updatePaintedGeometry();
-
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-private:
- Q_DISABLE_COPY(QQuickImage)
- Q_DECLARE_PRIVATE(QQuickImage)
-};
-
-QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickImage)
-QT_END_HEADER
-
-#endif // QQUICKIMAGE_P_H
diff --git a/src/declarative/items/qquickimagebase_p_p.h b/src/declarative/items/qquickimagebase_p_p.h
deleted file mode 100644
index 2347a82e92..0000000000
--- a/src/declarative/items/qquickimagebase_p_p.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKIMAGEBASE_P_P_H
-#define QQUICKIMAGEBASE_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qquickimplicitsizeitem_p_p.h"
-#include "qquickimagebase_p.h"
-
-#include <private/qdeclarativepixmapcache_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QNetworkReply;
-class QQuickImageBasePrivate : public QQuickImplicitSizeItemPrivate
-{
- Q_DECLARE_PUBLIC(QQuickImageBase)
-
-public:
- QQuickImageBasePrivate()
- : status(QQuickImageBase::Null),
- progress(0.0),
- explicitSourceSize(false),
- async(false),
- cache(true),
- mirror(false)
- {
- }
-
- QDeclarativePixmap pix;
- QQuickImageBase::Status status;
- QUrl url;
- qreal progress;
- QSize sourcesize;
- bool explicitSourceSize : 1;
- bool async : 1;
- bool cache : 1;
- bool mirror: 1;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKIMAGEBASE_P_P_H
diff --git a/src/declarative/items/qquickitem.cpp b/src/declarative/items/qquickitem.cpp
deleted file mode 100644
index 9c11196944..0000000000
--- a/src/declarative/items/qquickitem.cpp
+++ /dev/null
@@ -1,5236 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickitem.h"
-
-#include "qquickcanvas.h"
-#include <QtDeclarative/qjsengine.h>
-#include "qquickcanvas_p.h"
-
-#include "qquickevents_p_p.h"
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qpen.h>
-#include <QtGui/qcursor.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qinputpanel.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qnumeric.h>
-
-#include <private/qdeclarativeengine_p.h>
-#include <private/qdeclarativestategroup_p.h>
-#include <private/qdeclarativeopenmetaobject_p.h>
-#include <private/qdeclarativestate_p.h>
-#include <private/qlistmodelinterface_p.h>
-#include <private/qquickitem_p.h>
-
-#include <float.h>
-
-// XXX todo Readd parentNotifier for faster parent bindings
-// XXX todo Check that elements that create items handle memory correctly after visual ownership change
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass Transform QQuickTransform
- \inqmlmodule QtQuick 2
- \ingroup qml-transform-elements
- \brief The Transform elements provide a way of building advanced transformations on Items.
-
- The Transform element is a base type which cannot be instantiated directly.
- The following concrete Transform types are available:
-
- \list
- \o \l Rotation
- \o \l Scale
- \o \l Translate
- \endlist
-
- The Transform elements let you create and control advanced transformations that can be configured
- independently using specialized properties.
-
- You can assign any number of Transform elements to an \l Item. Each Transform is applied in order,
- one at a time.
-*/
-
-/*!
- \qmlclass Translate QQuickTranslate
- \inqmlmodule QtQuick 2
- \ingroup qml-transform-elements
- \brief The Translate object provides a way to move an Item without changing its x or y properties.
-
- The Translate object provides independent control over position in addition to the Item's x and y properties.
-
- The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element
- to lay the items out as if they had not been transformed:
- \qml
- import QtQuick 1.0
-
- Row {
- Rectangle {
- width: 100; height: 100
- color: "blue"
- transform: Translate { y: 20 }
- }
- Rectangle {
- width: 100; height: 100
- color: "red"
- transform: Translate { y: -20 }
- }
- }
- \endqml
-
- \image translate.png
-*/
-
-/*!
- \qmlproperty real QtQuick2::Translate::x
-
- The translation along the X axis.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Translate::y
-
- The translation along the Y axis.
-*/
-
-/*!
- \qmlclass Scale QQuickScale
- \inqmlmodule QtQuick 2
- \ingroup qml-transform-elements
- \brief The Scale element provides a way to scale an Item.
-
- The Scale element gives more control over scaling than using \l Item's \l{Item::scale}{scale} property. Specifically,
- it allows a different scale for the x and y axes, and allows the scale to be relative to an
- arbitrary point.
-
- The following example scales the X axis of the Rectangle, relative to its interior point 25, 25:
- \qml
- Rectangle {
- width: 100; height: 100
- color: "blue"
- transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
- }
- \endqml
-
- \sa Rotation, Translate
-*/
-
-/*!
- \qmlproperty real QtQuick2::Scale::origin.x
- \qmlproperty real QtQuick2::Scale::origin.y
-
- The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as
- the rest of the item grows). By default the origin is 0, 0.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Scale::xScale
-
- The scaling factor for the X axis.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Scale::yScale
-
- The scaling factor for the Y axis.
-*/
-
-/*!
- \qmlclass Rotation QQuickRotation
- \inqmlmodule QtQuick 2
- \ingroup qml-transform-elements
- \brief The Rotation object provides a way to rotate an Item.
-
- The Rotation object gives more control over rotation than using \l Item's \l{Item::rotation}{rotation} property.
- Specifically, it allows (z axis) rotation to be relative to an arbitrary point.
-
- The following example rotates a Rectangle around its interior point 25, 25:
- \qml
- Rectangle {
- width: 100; height: 100
- color: "blue"
- transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
- }
- \endqml
-
- Rotation also provides a way to specify 3D-like rotations for Items. For these types of
- rotations you must specify the axis to rotate around in addition to the origin point.
-
- The following example shows various 3D-like rotations applied to an \l Image.
- \snippet doc/src/snippets/declarative/rotation.qml 0
-
- \image axisrotation.png
-
- \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example}
-*/
-
-/*!
- \qmlproperty real QtQuick2::Rotation::origin.x
- \qmlproperty real QtQuick2::Rotation::origin.y
-
- The origin point of the rotation (i.e., the point that stays fixed relative to the parent as
- the rest of the item rotates). By default the origin is 0, 0.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Rotation::axis.x
- \qmlproperty real QtQuick2::Rotation::axis.y
- \qmlproperty real QtQuick2::Rotation::axis.z
-
- The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis,
- as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }).
-
- For a typical 3D-like rotation you will usually specify both the origin and the axis.
-
- \image 3d-rotation-axis.png
-*/
-
-/*!
- \qmlproperty real QtQuick2::Rotation::angle
-
- The angle to rotate, in degrees clockwise.
-*/
-
-QQuickTransformPrivate::QQuickTransformPrivate()
-{
-}
-
-QQuickTransform::QQuickTransform(QObject *parent)
-: QObject(*(new QQuickTransformPrivate), parent)
-{
-}
-
-QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
-: QObject(dd, parent)
-{
-}
-
-QQuickTransform::~QQuickTransform()
-{
- Q_D(QQuickTransform);
- for (int ii = 0; ii < d->items.count(); ++ii) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
- p->transforms.removeOne(this);
- p->dirty(QQuickItemPrivate::Transform);
- }
-}
-
-void QQuickTransform::update()
-{
- Q_D(QQuickTransform);
- for (int ii = 0; ii < d->items.count(); ++ii) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
- p->dirty(QQuickItemPrivate::Transform);
- }
-}
-
-QQuickContents::QQuickContents(QQuickItem *item)
-: m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
-{
-}
-
-QQuickContents::~QQuickContents()
-{
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
- QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
- }
-}
-
-bool QQuickContents::calcHeight(QQuickItem *changed)
-{
- qreal oldy = m_y;
- qreal oldheight = m_height;
-
- if (changed) {
- qreal top = oldy;
- qreal bottom = oldy + oldheight;
- qreal y = changed->y();
- if (y + changed->height() > bottom)
- bottom = y + changed->height();
- if (y < top)
- top = y;
- m_y = top;
- m_height = bottom - top;
- } else {
- qreal top = FLT_MAX;
- qreal bottom = 0;
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
- qreal y = child->y();
- if (y + child->height() > bottom)
- bottom = y + child->height();
- if (y < top)
- top = y;
- }
- if (!children.isEmpty())
- m_y = top;
- m_height = qMax(bottom - top, qreal(0.0));
- }
-
- return (m_height != oldheight || m_y != oldy);
-}
-
-bool QQuickContents::calcWidth(QQuickItem *changed)
-{
- qreal oldx = m_x;
- qreal oldwidth = m_width;
-
- if (changed) {
- qreal left = oldx;
- qreal right = oldx + oldwidth;
- qreal x = changed->x();
- if (x + changed->width() > right)
- right = x + changed->width();
- if (x < left)
- left = x;
- m_x = left;
- m_width = right - left;
- } else {
- qreal left = FLT_MAX;
- qreal right = 0;
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
- qreal x = child->x();
- if (x + child->width() > right)
- right = x + child->width();
- if (x < left)
- left = x;
- }
- if (!children.isEmpty())
- m_x = left;
- m_width = qMax(right - left, qreal(0.0));
- }
-
- return (m_width != oldwidth || m_x != oldx);
-}
-
-void QQuickContents::complete()
-{
- QQuickItemPrivate::get(m_item)->addItemChangeListener(this, QQuickItemPrivate::Children);
-
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
- QQuickItemPrivate::get(child)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
- //###what about changes to visibility?
- }
- calcGeometry();
-}
-
-void QQuickContents::updateRect()
-{
- QQuickItemPrivate::get(m_item)->emitChildrenRectChanged(rectF());
-}
-
-void QQuickContents::itemGeometryChanged(QQuickItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_UNUSED(changed)
- bool wChanged = false;
- bool hChanged = false;
- //### we can only pass changed if the left edge has moved left, or the right edge has moved right
- if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x())
- wChanged = calcWidth(/*changed*/);
- if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y())
- hChanged = calcHeight(/*changed*/);
- if (wChanged || hChanged)
- updateRect();
-}
-
-void QQuickContents::itemDestroyed(QQuickItem *item)
-{
- if (item)
- QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
- calcGeometry();
-}
-
-void QQuickContents::itemChildRemoved(QQuickItem *, QQuickItem *item)
-{
- if (item)
- QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
- calcGeometry();
-}
-
-void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item)
-{
- if (item)
- QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
- calcGeometry(item);
-}
-
-QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
-: m_processPost(false), m_next(0)
-{
- QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):0;
- if (p) {
- m_next = p->keyHandler;
- p->keyHandler = this;
- }
-}
-
-QQuickItemKeyFilter::~QQuickItemKeyFilter()
-{
-}
-
-void QQuickItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
-{
- if (m_next) m_next->keyPressed(event, post);
-}
-
-void QQuickItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
-{
- if (m_next) m_next->keyReleased(event, post);
-}
-
-void QQuickItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
-{
- if (m_next)
- m_next->inputMethodEvent(event, post);
- else
- event->ignore();
-}
-
-QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
-{
- if (m_next) return m_next->inputMethodQuery(query);
- return QVariant();
-}
-
-void QQuickItemKeyFilter::componentComplete()
-{
- if (m_next) m_next->componentComplete();
-}
-/*!
- \qmlclass KeyNavigation QQuickKeyNavigationAttached
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-interaction-elements
- \brief The KeyNavigation attached property supports key navigation by arrow keys.
-
- Key-based user interfaces commonly allow the use of arrow keys to navigate between
- focusable items. The KeyNavigation attached property enables this behavior by providing a
- convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
-
- The following example provides key navigation for a 2x2 grid of items:
-
- \snippet doc/src/snippets/declarative/keynavigation.qml 0
-
- The top-left item initially receives focus by setting \l {Item::}{focus} to
- \c true. When an arrow key is pressed, the focus will move to the
- appropriate item, as defined by the value that has been set for
- the KeyNavigation \l left, \l right, \l up or \l down properties.
-
- Note that if a KeyNavigation attached property receives the key press and release
- events for a requested arrow or tab key, the event is accepted and does not
- propagate any further.
-
- By default, KeyNavigation receives key events after the item to which it is attached.
- If the item accepts the key event, the KeyNavigation attached property will not
- receive an event for that key. Setting the \l priority property to
- \c KeyNavigation.BeforeItem allows the event to be used for key navigation
- before the item, rather than after.
-
- If item to which the focus is switching is not enabled or visible, an attempt will
- be made to skip this item and focus on the next. This is possible if there are
- a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
- or visible, they will also be skipped.
-
- KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
- \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
- item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
- This means that the above example could have been written, with the same behaviour, without specifing
- KeyNavigation.right or KeyNavigation.down for any of the items.
-
- \sa {Keys}{Keys attached property}
-*/
-
-/*!
- \qmlproperty Item QtQuick2::KeyNavigation::left
- \qmlproperty Item QtQuick2::KeyNavigation::right
- \qmlproperty Item QtQuick2::KeyNavigation::up
- \qmlproperty Item QtQuick2::KeyNavigation::down
- \qmlproperty Item QtQuick2::KeyNavigation::tab
- \qmlproperty Item QtQuick2::KeyNavigation::backtab
-
- These properties hold the item to assign focus to
- when the left, right, up or down cursor keys, or the
- tab key are pressed.
-*/
-
-/*!
- \qmlproperty Item QtQuick2::KeyNavigation::tab
- \qmlproperty Item QtQuick2::KeyNavigation::backtab
-
- These properties hold the item to assign focus to
- when the Tab key or Shift+Tab key combination (Backtab) are pressed.
-*/
-
-QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
-: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
- QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
-{
- m_processPost = true;
-}
-
-QQuickKeyNavigationAttached *
-QQuickKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickKeyNavigationAttached(obj);
-}
-
-QQuickItem *QQuickKeyNavigationAttached::left() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->left;
-}
-
-void QQuickKeyNavigationAttached::setLeft(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->left == i)
- return;
- d->left = i;
- d->leftSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->rightSet){
- other->d_func()->right = qobject_cast<QQuickItem*>(parent());
- emit other->rightChanged();
- }
- emit leftChanged();
-}
-
-QQuickItem *QQuickKeyNavigationAttached::right() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->right;
-}
-
-void QQuickKeyNavigationAttached::setRight(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->right == i)
- return;
- d->right = i;
- d->rightSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->leftSet){
- other->d_func()->left = qobject_cast<QQuickItem*>(parent());
- emit other->leftChanged();
- }
- emit rightChanged();
-}
-
-QQuickItem *QQuickKeyNavigationAttached::up() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->up;
-}
-
-void QQuickKeyNavigationAttached::setUp(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->up == i)
- return;
- d->up = i;
- d->upSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->downSet){
- other->d_func()->down = qobject_cast<QQuickItem*>(parent());
- emit other->downChanged();
- }
- emit upChanged();
-}
-
-QQuickItem *QQuickKeyNavigationAttached::down() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->down;
-}
-
-void QQuickKeyNavigationAttached::setDown(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->down == i)
- return;
- d->down = i;
- d->downSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->upSet) {
- other->d_func()->up = qobject_cast<QQuickItem*>(parent());
- emit other->upChanged();
- }
- emit downChanged();
-}
-
-QQuickItem *QQuickKeyNavigationAttached::tab() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->tab;
-}
-
-void QQuickKeyNavigationAttached::setTab(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->tab == i)
- return;
- d->tab = i;
- d->tabSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->backtabSet) {
- other->d_func()->backtab = qobject_cast<QQuickItem*>(parent());
- emit other->backtabChanged();
- }
- emit tabChanged();
-}
-
-QQuickItem *QQuickKeyNavigationAttached::backtab() const
-{
- Q_D(const QQuickKeyNavigationAttached);
- return d->backtab;
-}
-
-void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
-{
- Q_D(QQuickKeyNavigationAttached);
- if (d->backtab == i)
- return;
- d->backtab = i;
- d->backtabSet = true;
- QQuickKeyNavigationAttached* other =
- qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
- if (other && !other->d_func()->tabSet) {
- other->d_func()->tab = qobject_cast<QQuickItem*>(parent());
- emit other->tabChanged();
- }
- emit backtabChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::KeyNavigation::priority
-
- This property determines whether the keys are processed before
- or after the attached item's own key handling.
-
- \list
- \o KeyNavigation.BeforeItem - process the key events before normal
- item key processing. If the event is used for key navigation, it will be accepted and will not
- be passed on to the item.
- \o KeyNavigation.AfterItem (default) - process the key events after normal item key
- handling. If the item accepts the key event it will not be
- handled by the KeyNavigation attached property handler.
- \endlist
-*/
-QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
-{
- return m_processPost ? AfterItem : BeforeItem;
-}
-
-void QQuickKeyNavigationAttached::setPriority(Priority order)
-{
- bool processPost = order == AfterItem;
- if (processPost != m_processPost) {
- m_processPost = processPost;
- emit priorityChanged();
- }
-}
-
-void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
-{
- Q_D(QQuickKeyNavigationAttached);
- event->ignore();
-
- if (post != m_processPost) {
- QQuickItemKeyFilter::keyPressed(event, post);
- return;
- }
-
- bool mirror = false;
- switch (event->key()) {
- case Qt::Key_Left: {
- if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
- mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
- QQuickItem* leftItem = mirror ? d->right : d->left;
- if (leftItem) {
- setFocusNavigation(leftItem, mirror ? "right" : "left");
- event->accept();
- }
- break;
- }
- case Qt::Key_Right: {
- if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
- mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
- QQuickItem* rightItem = mirror ? d->left : d->right;
- if (rightItem) {
- setFocusNavigation(rightItem, mirror ? "left" : "right");
- event->accept();
- }
- break;
- }
- case Qt::Key_Up:
- if (d->up) {
- setFocusNavigation(d->up, "up");
- event->accept();
- }
- break;
- case Qt::Key_Down:
- if (d->down) {
- setFocusNavigation(d->down, "down");
- event->accept();
- }
- break;
- case Qt::Key_Tab:
- if (d->tab) {
- setFocusNavigation(d->tab, "tab");
- event->accept();
- }
- break;
- case Qt::Key_Backtab:
- if (d->backtab) {
- setFocusNavigation(d->backtab, "backtab");
- event->accept();
- }
- break;
- default:
- break;
- }
-
- if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
-}
-
-void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
-{
- Q_D(QQuickKeyNavigationAttached);
- event->ignore();
-
- if (post != m_processPost) {
- QQuickItemKeyFilter::keyReleased(event, post);
- return;
- }
-
- bool mirror = false;
- switch (event->key()) {
- case Qt::Key_Left:
- if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
- mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
- if (mirror ? d->right : d->left)
- event->accept();
- break;
- case Qt::Key_Right:
- if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
- mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
- if (mirror ? d->left : d->right)
- event->accept();
- break;
- case Qt::Key_Up:
- if (d->up) {
- event->accept();
- }
- break;
- case Qt::Key_Down:
- if (d->down) {
- event->accept();
- }
- break;
- case Qt::Key_Tab:
- if (d->tab) {
- event->accept();
- }
- break;
- case Qt::Key_Backtab:
- if (d->backtab) {
- event->accept();
- }
- break;
- default:
- break;
- }
-
- if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
-}
-
-void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir)
-{
- QQuickItem *initialItem = currentItem;
- bool isNextItem = false;
- do {
- isNextItem = false;
- if (currentItem->isVisible() && currentItem->isEnabled()) {
- currentItem->setFocus(true);
- } else {
- QObject *attached =
- qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
- if (attached) {
- QQuickItem *tempItem = qvariant_cast<QQuickItem*>(attached->property(dir));
- if (tempItem) {
- currentItem = tempItem;
- isNextItem = true;
- }
- }
- }
- }
- while (currentItem != initialItem && isNextItem);
-}
-
-const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = {
- { Qt::Key_Left, "leftPressed" },
- { Qt::Key_Right, "rightPressed" },
- { Qt::Key_Up, "upPressed" },
- { Qt::Key_Down, "downPressed" },
- { Qt::Key_Tab, "tabPressed" },
- { Qt::Key_Backtab, "backtabPressed" },
- { Qt::Key_Asterisk, "asteriskPressed" },
- { Qt::Key_NumberSign, "numberSignPressed" },
- { Qt::Key_Escape, "escapePressed" },
- { Qt::Key_Return, "returnPressed" },
- { Qt::Key_Enter, "enterPressed" },
- { Qt::Key_Delete, "deletePressed" },
- { Qt::Key_Space, "spacePressed" },
- { Qt::Key_Back, "backPressed" },
- { Qt::Key_Cancel, "cancelPressed" },
- { Qt::Key_Select, "selectPressed" },
- { Qt::Key_Yes, "yesPressed" },
- { Qt::Key_No, "noPressed" },
- { Qt::Key_Context1, "context1Pressed" },
- { Qt::Key_Context2, "context2Pressed" },
- { Qt::Key_Context3, "context3Pressed" },
- { Qt::Key_Context4, "context4Pressed" },
- { Qt::Key_Call, "callPressed" },
- { Qt::Key_Hangup, "hangupPressed" },
- { Qt::Key_Flip, "flipPressed" },
- { Qt::Key_Menu, "menuPressed" },
- { Qt::Key_VolumeUp, "volumeUpPressed" },
- { Qt::Key_VolumeDown, "volumeDownPressed" },
- { 0, 0 }
-};
-
-bool QQuickKeysAttachedPrivate::isConnected(const char *signalName)
-{
- return isSignalConnected(signalIndex(signalName));
-}
-
-/*!
- \qmlclass Keys QQuickKeysAttached
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-interaction-elements
- \brief The Keys attached property provides key handling to Items.
-
- All visual primitives support key handling via the Keys
- attached property. Keys can be handled via the onPressed
- and onReleased signal properties.
-
- The signal properties have a \l KeyEvent parameter, named
- \e event which contains details of the event. If a key is
- handled \e event.accepted should be set to true to prevent the
- event from propagating up the item hierarchy.
-
- \section1 Example Usage
-
- The following example shows how the general onPressed handler can
- be used to test for a certain key; in this case, the left cursor
- key:
-
- \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
-
- Some keys may alternatively be handled via specific signal properties,
- for example \e onSelectPressed. These handlers automatically set
- \e event.accepted to true.
-
- \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
-
- See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
-
- \section1 Key Handling Priorities
-
- The Keys attached property can be configured to handle key events
- before or after the item it is attached to. This makes it possible
- to intercept events in order to override an item's default behavior,
- or act as a fallback for keys not handled by the item.
-
- If \l priority is Keys.BeforeItem (default) the order of key event processing is:
-
- \list 1
- \o Items specified in \c forwardTo
- \o specific key handlers, e.g. onReturnPressed
- \o onKeyPress, onKeyRelease handlers
- \o Item specific key handling, e.g. TextInput key handling
- \o parent item
- \endlist
-
- If priority is Keys.AfterItem the order of key event processing is:
-
- \list 1
- \o Item specific key handling, e.g. TextInput key handling
- \o Items specified in \c forwardTo
- \o specific key handlers, e.g. onReturnPressed
- \o onKeyPress, onKeyRelease handlers
- \o parent item
- \endlist
-
- If the event is accepted during any of the above steps, key
- propagation stops.
-
- \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Keys::enabled
-
- This flags enables key handling if true (default); otherwise
- no key handlers will be called.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::Keys::priority
-
- This property determines whether the keys are processed before
- or after the attached item's own key handling.
-
- \list
- \o Keys.BeforeItem (default) - process the key events before normal
- item key processing. If the event is accepted it will not
- be passed on to the item.
- \o Keys.AfterItem - process the key events after normal item key
- handling. If the item accepts the key event it will not be
- handled by the Keys attached property handler.
- \endlist
-*/
-
-/*!
- \qmlproperty list<Object> QtQuick2::Keys::forwardTo
-
- This property provides a way to forward key presses, key releases, and keyboard input
- coming from input methods to other items. This can be useful when you want
- one item to handle some keys (e.g. the up and down arrow keys), and another item to
- handle other keys (e.g. the left and right arrow keys). Once an item that has been
- forwarded keys accepts the event it is no longer forwarded to items later in the
- list.
-
- This example forwards key events to two lists:
- \qml
- Item {
- ListView {
- id: list1
- // ...
- }
- ListView {
- id: list2
- // ...
- }
- Keys.forwardTo: [list1, list2]
- focus: true
- }
- \endqml
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onPressed(KeyEvent event)
-
- This handler is called when a key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onReleased(KeyEvent event)
-
- This handler is called when a key has been released. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit0Pressed(KeyEvent event)
-
- This handler is called when the digit '0' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit1Pressed(KeyEvent event)
-
- This handler is called when the digit '1' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit2Pressed(KeyEvent event)
-
- This handler is called when the digit '2' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit3Pressed(KeyEvent event)
-
- This handler is called when the digit '3' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit4Pressed(KeyEvent event)
-
- This handler is called when the digit '4' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit5Pressed(KeyEvent event)
-
- This handler is called when the digit '5' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit6Pressed(KeyEvent event)
-
- This handler is called when the digit '6' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit7Pressed(KeyEvent event)
-
- This handler is called when the digit '7' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit8Pressed(KeyEvent event)
-
- This handler is called when the digit '8' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDigit9Pressed(KeyEvent event)
-
- This handler is called when the digit '9' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onLeftPressed(KeyEvent event)
-
- This handler is called when the Left arrow has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onRightPressed(KeyEvent event)
-
- This handler is called when the Right arrow has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onUpPressed(KeyEvent event)
-
- This handler is called when the Up arrow has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDownPressed(KeyEvent event)
-
- This handler is called when the Down arrow has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onTabPressed(KeyEvent event)
-
- This handler is called when the Tab key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onBacktabPressed(KeyEvent event)
-
- This handler is called when the Shift+Tab key combination (Backtab) has
- been pressed. The \a event parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onAsteriskPressed(KeyEvent event)
-
- This handler is called when the Asterisk '*' has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onEscapePressed(KeyEvent event)
-
- This handler is called when the Escape key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onReturnPressed(KeyEvent event)
-
- This handler is called when the Return key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onEnterPressed(KeyEvent event)
-
- This handler is called when the Enter key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onDeletePressed(KeyEvent event)
-
- This handler is called when the Delete key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onSpacePressed(KeyEvent event)
-
- This handler is called when the Space key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onBackPressed(KeyEvent event)
-
- This handler is called when the Back key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onCancelPressed(KeyEvent event)
-
- This handler is called when the Cancel key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onSelectPressed(KeyEvent event)
-
- This handler is called when the Select key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onYesPressed(KeyEvent event)
-
- This handler is called when the Yes key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onNoPressed(KeyEvent event)
-
- This handler is called when the No key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onContext1Pressed(KeyEvent event)
-
- This handler is called when the Context1 key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onContext2Pressed(KeyEvent event)
-
- This handler is called when the Context2 key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onContext3Pressed(KeyEvent event)
-
- This handler is called when the Context3 key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onContext4Pressed(KeyEvent event)
-
- This handler is called when the Context4 key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onCallPressed(KeyEvent event)
-
- This handler is called when the Call key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onHangupPressed(KeyEvent event)
-
- This handler is called when the Hangup key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onFlipPressed(KeyEvent event)
-
- This handler is called when the Flip key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onMenuPressed(KeyEvent event)
-
- This handler is called when the Menu key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onVolumeUpPressed(KeyEvent event)
-
- This handler is called when the VolumeUp key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-/*!
- \qmlsignal QtQuick2::Keys::onVolumeDownPressed(KeyEvent event)
-
- This handler is called when the VolumeDown key has been pressed. The \a event
- parameter provides information about the event.
-*/
-
-QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
-: QObject(*(new QQuickKeysAttachedPrivate), parent),
- QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
-{
- Q_D(QQuickKeysAttached);
- m_processPost = false;
- d->item = qobject_cast<QQuickItem*>(parent);
-}
-
-QQuickKeysAttached::~QQuickKeysAttached()
-{
-}
-
-QQuickKeysAttached::Priority QQuickKeysAttached::priority() const
-{
- return m_processPost ? AfterItem : BeforeItem;
-}
-
-void QQuickKeysAttached::setPriority(Priority order)
-{
- bool processPost = order == AfterItem;
- if (processPost != m_processPost) {
- m_processPost = processPost;
- emit priorityChanged();
- }
-}
-
-void QQuickKeysAttached::componentComplete()
-{
- Q_D(QQuickKeysAttached);
- if (d->item) {
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *targetItem = d->targets.at(ii);
- if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
- d->item->setFlag(QQuickItem::ItemAcceptsInputMethod);
- break;
- }
- }
- }
-}
-
-void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
-{
- Q_D(QQuickKeysAttached);
- if (post != m_processPost || !d->enabled || d->inPress) {
- event->ignore();
- QQuickItemKeyFilter::keyPressed(event, post);
- return;
- }
-
- // first process forwards
- if (d->item && d->item->canvas()) {
- d->inPress = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible()) {
- d->item->canvas()->sendEvent(i, event);
- if (event->isAccepted()) {
- d->inPress = false;
- return;
- }
- }
- }
- d->inPress = false;
- }
-
- QQuickKeyEvent ke(*event);
- QByteArray keySignal = keyToSignal(event->key());
- if (!keySignal.isEmpty()) {
- keySignal += "(QQuickKeyEvent*)";
- if (d->isConnected(keySignal)) {
- // If we specifically handle a key then default to accepted
- ke.setAccepted(true);
- int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(keySignal);
- metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QQuickKeyEvent*, &ke));
- }
- }
- if (!ke.isAccepted())
- emit pressed(&ke);
- event->setAccepted(ke.isAccepted());
-
- if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
-}
-
-void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
-{
- Q_D(QQuickKeysAttached);
- if (post != m_processPost || !d->enabled || d->inRelease) {
- event->ignore();
- QQuickItemKeyFilter::keyReleased(event, post);
- return;
- }
-
- if (d->item && d->item->canvas()) {
- d->inRelease = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible()) {
- d->item->canvas()->sendEvent(i, event);
- if (event->isAccepted()) {
- d->inRelease = false;
- return;
- }
- }
- }
- d->inRelease = false;
- }
-
- QQuickKeyEvent ke(*event);
- emit released(&ke);
- event->setAccepted(ke.isAccepted());
-
- if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
-}
-
-void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
-{
- Q_D(QQuickKeysAttached);
- if (post == m_processPost && d->item && !d->inIM && d->item->canvas()) {
- d->inIM = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod)) {
- d->item->canvas()->sendEvent(i, event);
- if (event->isAccepted()) {
- d->imeItem = i;
- d->inIM = false;
- return;
- }
- }
- }
- d->inIM = false;
- }
- QQuickItemKeyFilter::inputMethodEvent(event, post);
-}
-
-QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
-{
- Q_D(const QQuickKeysAttached);
- if (d->item) {
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
- //### how robust is i == d->imeItem check?
- QVariant v = i->inputMethodQuery(query);
- if (v.userType() == QVariant::RectF)
- v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
- return v;
- }
- }
- }
- return QQuickItemKeyFilter::inputMethodQuery(query);
-}
-
-QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickKeysAttached(obj);
-}
-
-/*!
- \qmlclass LayoutMirroring QQuickLayoutMirroringAttached
- \inqmlmodule QtQuick 2
- \ingroup qml-utility-elements
- \brief The LayoutMirroring attached property is used to mirror layout behavior.
-
- The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
- \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid)
- and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
- anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the
- horizontal layout of child items.
-
- Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
- only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
- behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined
- for an item, mirroring is not enabled.
-
- The following example shows mirroring in action. The \l Row below is specified as being anchored
- to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
- reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
- from left to right by default, they are now positioned from right to left instead, as demonstrated
- by the numbering and opacity of the items:
-
- \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
-
- \image layoutmirroring.png
-
- Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
- layout versions of an application to target different language areas. The \l childrenInherit
- property allows layout mirroring to be applied without manually setting layout configurations
- for every item in an application. Keep in mind, however, that mirroring does not affect any
- positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
- mirroring enabled, it will often be necessary to apply some layout fixes to support the
- desired layout direction. Also, it may be necessary to disable the mirroring of individual
- child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
- mirroring is not the desired behavior, or if the child item already implements mirroring in
- some custom way.
-
- See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
- other related features to implement right-to-left support for an application.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::LayoutMirroring::enabled
-
- This property holds whether the item's layout is mirrored horizontally. Setting this to true
- horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
- and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements
- (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView})
- this also mirrors the horizontal layout direction of the item.
-
- The default value is false.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::LayoutMirroring::childrenInherit
-
- This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
- is inherited by its children.
-
- The default value is false.
-*/
-
-
-QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
-{
- if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
- itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->attachedLayoutDirection = this;
- } else
- qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
-}
-
-QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
-{
- return new QQuickLayoutMirroringAttached(object);
-}
-
-bool QQuickLayoutMirroringAttached::enabled() const
-{
- return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
-}
-
-void QQuickLayoutMirroringAttached::setEnabled(bool enabled)
-{
- if (!itemPrivate)
- return;
-
- itemPrivate->isMirrorImplicit = false;
- if (enabled != itemPrivate->effectiveLayoutMirror) {
- itemPrivate->setLayoutMirror(enabled);
- if (itemPrivate->inheritMirrorFromItem)
- itemPrivate->resolveLayoutMirror();
- }
-}
-
-void QQuickLayoutMirroringAttached::resetEnabled()
-{
- if (itemPrivate && !itemPrivate->isMirrorImplicit) {
- itemPrivate->isMirrorImplicit = true;
- itemPrivate->resolveLayoutMirror();
- }
-}
-
-bool QQuickLayoutMirroringAttached::childrenInherit() const
-{
- return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
-}
-
-void QQuickLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
- if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
- itemPrivate->inheritMirrorFromItem = childrenInherit;
- itemPrivate->resolveLayoutMirror();
- childrenInheritChanged();
- }
-}
-
-void QQuickItemPrivate::resolveLayoutMirror()
-{
- Q_Q(QQuickItem);
- if (QQuickItem *parentItem = q->parentItem()) {
- QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parentItem);
- setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
- } else {
- setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
- }
-}
-
-void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
-{
- inherit = inherit || inheritMirrorFromItem;
- if (!isMirrorImplicit && inheritMirrorFromItem)
- mirror = effectiveLayoutMirror;
- if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
- return;
-
- inheritMirrorFromParent = inherit;
- inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
-
- if (isMirrorImplicit)
- setLayoutMirror(inherit ? inheritedLayoutMirror : false);
- for (int i = 0; i < childItems.count(); ++i) {
- if (QQuickItem *child = qobject_cast<QQuickItem *>(childItems.at(i))) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
- childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
- }
- }
-}
-
-void QQuickItemPrivate::setLayoutMirror(bool mirror)
-{
- if (mirror != effectiveLayoutMirror) {
- effectiveLayoutMirror = mirror;
- if (_anchors) {
- QQuickAnchorsPrivate *anchor_d = QQuickAnchorsPrivate::get(_anchors);
- anchor_d->fillChanged();
- anchor_d->centerInChanged();
- anchor_d->updateHorizontalAnchors();
- emit _anchors->mirroredChanged();
- }
- mirrorChange();
- if (attachedLayoutDirection) {
- emit attachedLayoutDirection->enabledChanged();
- }
- }
-}
-
-/*!
- \class QQuickItem
- \brief The QQuickItem class provides the most basic of all visual items in QML.
-
- All visual items in Qt Declarative inherit from QQuickItem. Although QQuickItem
- has no visual appearance, it defines all the properties that are
- common across visual items - such as the x and y position, the
- width and height, \l {anchor-layout}{anchoring} and key handling.
-
- You can subclass QQuickItem to provide your own custom visual item that inherits
- these features. Note that, because it does not draw anything, QQuickItem sets the
- QGraphicsItem::ItemHasNoContents flag. If you subclass QQuickItem to create a visual
- item, you will need to unset this flag.
-
-*/
-
-/*!
- \qmlclass Item QQuickItem
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The Item is the most basic of all visual items in QML.
-
- All visual items in Qt Declarative inherit from Item. Although Item
- has no visual appearance, it defines all the properties that are
- common across visual items - such as the x and y position, the
- width and height, \l {anchor-layout}{anchoring} and key handling.
-
- Item is also useful for grouping items together.
-
- \qml
- Item {
- Image {
- source: "tile.png"
- }
- Image {
- x: 80
- width: 100
- height: 100
- source: "tile.png"
- }
- Image {
- x: 190
- width: 100
- height: 100
- fillMode: Image.Tile
- source: "tile.png"
- }
- }
- \endqml
-
-
- \section1 Key Handling
-
- Key handling is available to all Item-based visual elements via the \l {Keys}{Keys}
- attached property. The \e Keys attached property provides basic handlers such
- as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased},
- as well as handlers for specific keys, such as
- \l {Keys::onCancelPressed}{onCancelPressed}. The example below
- assigns \l {qmlfocus}{focus} to the item and handles
- the Left key via the general \e onPressed handler and the Select key via the
- onSelectPressed handler:
-
- \qml
- Item {
- focus: true
- Keys.onPressed: {
- if (event.key == Qt.Key_Left) {
- console.log("move left");
- event.accepted = true;
- }
- }
- Keys.onSelectPressed: console.log("Selected");
- }
- \endqml
-
- See the \l {Keys}{Keys} attached property for detailed documentation.
-
- \section1 Layout Mirroring
-
- Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property.
-
-*/
-
-/*!
- \fn void QQuickItem::childrenRectChanged(const QRectF &)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::baselineOffsetChanged(qreal)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::stateChanged(const QString &state)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::parentChanged(QQuickItem *)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::smoothChanged(bool)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::clipChanged(bool)
- \internal
-*/
-
-/*! \fn void QQuickItem::transformOriginChanged(TransformOrigin)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::focusChanged(bool)
- \internal
-*/
-
-/*!
- \fn void QQuickItem::activeFocusChanged(bool)
- \internal
-*/
-/*!
- \fn QQuickItem::QQuickItem(QQuickItem *parent)
-
- Constructs a QQuickItem with the given \a parent.
-*/
-QQuickItem::QQuickItem(QQuickItem* parent)
-: QObject(*(new QQuickItemPrivate), parent)
-{
- Q_D(QQuickItem);
- d->init(parent);
-}
-
-/*! \internal
-*/
-QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
-: QObject(dd, parent)
-{
- Q_D(QQuickItem);
- d->init(parent);
-}
-
-#ifndef QT_NO_DEBUG
-static int qt_item_count = 0;
-
-static void qt_print_item_count()
-{
- qDebug("Number of leaked items: %i", qt_item_count);
- qt_item_count = -1;
-}
-#endif
-
-/*!
- Destroys the QQuickItem.
-*/
-QQuickItem::~QQuickItem()
-{
-#ifndef QT_NO_DEBUG
- --qt_item_count;
- if (qt_item_count < 0)
- qDebug("Item destroyed after qt_print_item_count() was called.");
-#endif
-
- Q_D(QQuickItem);
-
- if (d->parentItem)
- setParentItem(0);
- else if (d->canvas && d->itemNodeInstance)
- QQuickCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance); // cleanup root
- // XXX todo - optimize
- while (!d->childItems.isEmpty())
- d->childItems.first()->setParentItem(0);
-
- for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
- QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
- if (anchor)
- anchor->clearItem(this);
- }
-
- /*
- update item anchors that depended on us unless they are our child (and will also be destroyed),
- or our sibling, and our parent is also being destroyed.
- */
- for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
- QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
- if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
- anchor->update();
- }
-
- for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Destroyed)
- change.listener->itemDestroyed(this);
- }
- d->changeListeners.clear();
- delete d->_anchorLines; d->_anchorLines = 0;
- delete d->_anchors; d->_anchors = 0;
- delete d->_stateGroup; d->_stateGroup = 0;
- delete d->_contents; d->_contents = 0;
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Item::transformOrigin
- This property holds the origin point around which scale and rotation transform.
-
- Nine transform origins are available, as shown in the image below.
-
- \image declarative-transformorigin.png
-
- This example rotates an image around its bottom-right corner.
- \qml
- Image {
- source: "myimage.png"
- transformOrigin: Item.BottomRight
- rotation: 45
- }
- \endqml
-
- The default transform origin is \c Item.Center.
-
- To set an arbitrary transform origin point use the \l Scale or \l Rotation
- transform elements.
-*/
-
-/*!
- \qmlproperty Item QtQuick2::Item::parent
- This property holds the parent of the item.
-*/
-
-/*!
- \property QQuickItem::parent
- This property holds the parent of the item.
-*/
-void QQuickItem::setParentItem(QQuickItem *parentItem)
-{
- Q_D(QQuickItem);
- if (parentItem == d->parentItem)
- return;
-
- d->removeFromDirtyList();
-
- QQuickItem *oldParentItem = d->parentItem;
- QQuickItem *scopeFocusedItem = 0;
-
- if (oldParentItem) {
- QQuickItemPrivate *op = QQuickItemPrivate::get(oldParentItem);
-
- QQuickItem *scopeItem = 0;
-
- if (d->canvas && hasFocus()) {
- scopeItem = oldParentItem;
- while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
- scopeFocusedItem = this;
- } else if (d->canvas && !isFocusScope() && d->subFocusItem) {
- scopeItem = oldParentItem;
- while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
- scopeFocusedItem = d->subFocusItem;
- }
-
- if (scopeFocusedItem)
- QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
- QQuickCanvasPrivate::DontChangeFocusProperty);
-
- op->removeChild(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);
- }
-
- d->dirty(QQuickItemPrivate::ParentChanged);
-
- if (d->parentItem)
- QQuickItemPrivate::get(d->parentItem)->addChild(this);
-
- d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
- d->setEffectiveEnableRecur(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 (scopeItem->scopedFocusItem()) {
- QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
- emit scopeFocusedItem->focusChanged(false);
- } else {
- QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
- QQuickCanvasPrivate::DontChangeFocusProperty);
- }
- }
-
- d->resolveLayoutMirror();
-
- d->itemChange(ItemParentHasChanged, d->parentItem);
-
- emit parentChanged(d->parentItem);
-}
-
-void QQuickItem::stackBefore(const QQuickItem *sibling)
-{
- Q_D(QQuickItem);
- if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
- qWarning("QQuickItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling);
- return;
- }
-
- QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
-
- int myIndex = parentPrivate->childItems.indexOf(this);
- int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QQuickItem *>(sibling));
-
- Q_ASSERT(myIndex != -1 && siblingIndex != -1);
-
- if (myIndex == siblingIndex - 1)
- return;
-
- parentPrivate->childItems.removeAt(myIndex);
-
- if (myIndex < siblingIndex) --siblingIndex;
-
- parentPrivate->childItems.insert(siblingIndex, this);
-
- parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
- parentPrivate->markSortedChildrenDirty(this);
-
- for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
- QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
-}
-
-void QQuickItem::stackAfter(const QQuickItem *sibling)
-{
- Q_D(QQuickItem);
- if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
- qWarning("QQuickItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling);
- return;
- }
-
- QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
-
- int myIndex = parentPrivate->childItems.indexOf(this);
- int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QQuickItem *>(sibling));
-
- Q_ASSERT(myIndex != -1 && siblingIndex != -1);
-
- if (myIndex == siblingIndex + 1)
- return;
-
- parentPrivate->childItems.removeAt(myIndex);
-
- if (myIndex < siblingIndex) --siblingIndex;
-
- parentPrivate->childItems.insert(siblingIndex + 1, this);
-
- parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
- parentPrivate->markSortedChildrenDirty(this);
-
- for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
- QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
-}
-
-/*!
- Returns the QQuickItem parent of this item.
-*/
-QQuickItem *QQuickItem::parentItem() const
-{
- Q_D(const QQuickItem);
- return d->parentItem;
-}
-
-QSGEngine *QQuickItem::sceneGraphEngine() const
-{
- return canvas()->sceneGraphEngine();
-}
-
-QQuickCanvas *QQuickItem::canvas() const
-{
- Q_D(const QQuickItem);
- return d->canvas;
-}
-
-static bool itemZOrder_sort(QQuickItem *lhs, QQuickItem *rhs)
-{
- return lhs->z() < rhs->z();
-}
-
-QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
-{
- if (sortedChildItems)
- return *sortedChildItems;
-
- // If none of the items have set Z then the paint order list is the same as
- // the childItems list. This is by far the most common case.
- bool haveZ = false;
- for (int i = 0; i < childItems.count(); ++i) {
- if (QQuickItemPrivate::get(childItems.at(i))->z != 0.) {
- haveZ = true;
- break;
- }
- }
- if (haveZ) {
- sortedChildItems = new QList<QQuickItem*>(childItems);
- qStableSort(sortedChildItems->begin(), sortedChildItems->end(), itemZOrder_sort);
- return *sortedChildItems;
- }
-
- sortedChildItems = const_cast<QList<QQuickItem*>*>(&childItems);
-
- return childItems;
-}
-
-void QQuickItemPrivate::addChild(QQuickItem *child)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(!childItems.contains(child));
-
- childItems.append(child);
-
- markSortedChildrenDirty(child);
- dirty(QQuickItemPrivate::ChildrenChanged);
-
- itemChange(QQuickItem::ItemChildAddedChange, child);
-
- emit q->childrenChanged();
-}
-
-void QQuickItemPrivate::removeChild(QQuickItem *child)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(child);
- Q_ASSERT(childItems.contains(child));
- childItems.removeOne(child);
- Q_ASSERT(!childItems.contains(child));
-
- markSortedChildrenDirty(child);
- dirty(QQuickItemPrivate::ChildrenChanged);
-
- itemChange(QQuickItem::ItemChildRemovedChange, child);
-
- emit q->childrenChanged();
-}
-
-void QQuickItemPrivate::InitializationState::clear()
-{
- focusScope = 0;
-}
-
-void QQuickItemPrivate::InitializationState::clear(QQuickItem *fs)
-{
- focusScope = fs;
-}
-
-QQuickItem *QQuickItemPrivate::InitializationState::getFocusScope(QQuickItem *item)
-{
- if (!focusScope) {
- QQuickItem *fs = item->parentItem();
- while (!fs->isFocusScope())
- fs = fs->parentItem();
- focusScope = fs;
- }
- return focusScope;
-}
-
-void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
-{
- Q_Q(QQuickItem);
-
- 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);
- }
-
- canvas = c;
-
- if (canvas && polishScheduled)
- QQuickCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
-
- itemNodeInstance = 0;
- opacityNode = 0;
- clipNode = 0;
- rootNode = 0;
- groupNode = 0;
- paintNode = 0;
- beforePaintNode = 0;
-
- InitializationState _dummy;
- InitializationState *childState = state;
-
- if (c && q->isFocusScope()) {
- _dummy.clear(q);
- childState = &_dummy;
- }
-
- 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);
- }
- }
-
- dirty(Canvas);
-
- itemChange(QQuickItem::ItemSceneChange, c);
-}
-
-/*!
-Returns a transform that maps points from canvas space into item space.
-*/
-QTransform QQuickItemPrivate::canvasToItemTransform() const
-{
- // XXX todo - optimize
- return itemToCanvasTransform().inverted();
-}
-
-/*!
-Returns a transform that maps points from item space into canvas space.
-*/
-QTransform QQuickItemPrivate::itemToCanvasTransform() const
-{
- // XXX todo
- QTransform rv = parentItem?QQuickItemPrivate::get(parentItem)->itemToCanvasTransform():QTransform();
- itemToParentTransform(rv);
- return rv;
-}
-
-/*!
-Motifies \a t with this items local transform relative to its parent.
-*/
-void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
-{
- if (x || y)
- t.translate(x, y);
-
- if (!transforms.isEmpty()) {
- QMatrix4x4 m(t);
- for (int ii = transforms.count() - 1; ii >= 0; --ii)
- transforms.at(ii)->applyTo(&m);
- t = m.toTransform();
- }
-
- if (scale != 1. || rotation != 0.) {
- QPointF tp = computeTransformOrigin();
- t.translate(tp.x(), tp.y());
- t.scale(scale, scale);
- t.rotate(rotation);
- t.translate(-tp.x(), -tp.y());
- }
-}
-
-
-/*!
- \qmlproperty real QtQuick2::Item::childrenRect.x
- \qmlproperty real QtQuick2::Item::childrenRect.y
- \qmlproperty real QtQuick2::Item::childrenRect.width
- \qmlproperty real QtQuick2::Item::childrenRect.height
-
- The childrenRect properties allow an item access to the geometry of its
- children. This property is useful if you have an item that needs to be
- sized to fit its children.
-*/
-
-
-/*!
- \qmlproperty list<Item> QtQuick2::Item::children
- \qmlproperty list<Object> QtQuick2::Item::resources
-
- The children property contains the list of visual children of this item.
- The resources property contains non-visual resources that you want to
- reference by name.
-
- Generally you can rely on Item's default property to handle all this for
- you, but it can come in handy in some cases.
-
- \qml
- Item {
- children: [
- Text {},
- Rectangle {}
- ]
- resources: [
- Component {
- id: myComponent
- Text {}
- }
- ]
- }
- \endqml
-*/
-
-/*!
- Returns true if construction of the QML component is complete; otherwise
- returns false.
-
- It is often desirable to delay some processing until the component is
- completed.
-
- \sa componentComplete()
-*/
-bool QQuickItem::isComponentComplete() const
-{
- Q_D(const QQuickItem);
- return d->componentComplete;
-}
-
-QQuickItemPrivate::QQuickItemPrivate()
-: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QQuickItem::Center),
-
- flags(0), widthValid(false), heightValid(false), componentComplete(true),
- keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(false), 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),
- inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false),
-
- canvas(0), parentItem(0), sortedChildItems(&childItems),
-
- subFocusItem(0),
-
- x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
- z(0), scale(1), rotation(0), opacity(1),
-
- attachedLayoutDirection(0), acceptedMouseButtons(0),
- imHints(Qt::ImhMultiLine),
-
- keyHandler(0),
-
- dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
-
- itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
- , beforePaintNode(0), effectRefCount(0), hideRefCount(0)
-{
-}
-
-QQuickItemPrivate::~QQuickItemPrivate()
-{
- if (sortedChildItems != &childItems)
- delete sortedChildItems;
-}
-
-void QQuickItemPrivate::init(QQuickItem *parent)
-{
-#ifndef QT_NO_DEBUG
- ++qt_item_count;
- static bool atexit_registered = false;
- if (!atexit_registered) {
- atexit(qt_print_item_count);
- atexit_registered = true;
- }
-#endif
-
- Q_Q(QQuickItem);
- baselineOffset.invalidate();
-
- if (parent) {
- q->setParentItem(parent);
- QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
- setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
- }
-}
-
-void QQuickItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
-{
- if (!o)
- return;
-
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
-
- // This test is measurably (albeit only slightly) faster than qobject_cast<>()
- const QMetaObject *mo = o->metaObject();
- while (mo && mo != &QQuickItem::staticMetaObject) {
- mo = mo->d.superdata;
- }
-
- if (mo) {
- QQuickItem *item = static_cast<QQuickItem *>(o);
- item->setParentItem(that);
- } else {
- if (o->inherits("QGraphicsItem"))
- qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
-
- // XXX todo - do we really want this behavior?
- o->setParent(that);
- }
-}
-
-/*!
- \qmlproperty list<Object> QtQuick2::Item::data
- \default
-
- The data property allows you to freely mix visual children and resources
- in an item. If you assign a visual item to the data list it becomes
- a child and if you assign any other object type, it is added as a resource.
-
- So you can write:
- \qml
- Item {
- Text {}
- Rectangle {}
- Timer {}
- }
- \endqml
-
- instead of:
- \qml
- Item {
- children: [
- Text {},
- Rectangle {}
- ]
- resources: [
- Timer {}
- ]
- }
- \endqml
-
- data is a behind-the-scenes property: you should never need to explicitly
- specify it.
- */
-
-int QQuickItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
-{
- Q_UNUSED(prop);
- // XXX todo
- return 0;
-}
-
-QObject *QQuickItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
-{
- Q_UNUSED(prop);
- Q_UNUSED(i);
- // XXX todo
- return 0;
-}
-
-void QQuickItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
-{
- Q_UNUSED(prop);
- // XXX todo
-}
-
-QObject *QQuickItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
-{
- const QObjectList children = prop->object->children();
- if (index < children.count())
- return children.at(index);
- else
- return 0;
-}
-
-void QQuickItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
-{
- // XXX todo - do we really want this behavior?
- o->setParent(prop->object);
-}
-
-int QQuickItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
-{
- return prop->object->children().count();
-}
-
-void QQuickItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
-{
- // XXX todo - do we really want this behavior?
- const QObjectList children = prop->object->children();
- for (int index = 0; index < children.count(); index++)
- children.at(index)->setParent(0);
-}
-
-QQuickItem *QQuickItemPrivate::children_at(QDeclarativeListProperty<QQuickItem> *prop, int index)
-{
- QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
- if (index >= p->childItems.count() || index < 0)
- return 0;
- else
- return p->childItems.at(index);
-}
-
-void QQuickItemPrivate::children_append(QDeclarativeListProperty<QQuickItem> *prop, QQuickItem *o)
-{
- if (!o)
- return;
-
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- if (o->parentItem() == that)
- o->setParentItem(0);
-
- o->setParentItem(that);
-}
-
-int QQuickItemPrivate::children_count(QDeclarativeListProperty<QQuickItem> *prop)
-{
- QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
- return p->childItems.count();
-}
-
-void QQuickItemPrivate::children_clear(QDeclarativeListProperty<QQuickItem> *prop)
-{
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- QQuickItemPrivate *p = QQuickItemPrivate::get(that);
- while (!p->childItems.isEmpty())
- p->childItems.at(0)->setParentItem(0);
-}
-
-int QQuickItemPrivate::transform_count(QDeclarativeListProperty<QQuickTransform> *prop)
-{
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- return QQuickItemPrivate::get(that)->transforms.count();
-}
-
-void QQuickTransform::appendToItem(QQuickItem *item)
-{
- Q_D(QQuickTransform);
- if (!item)
- return;
-
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
-
- if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
- p->transforms.removeOne(this);
- p->transforms.append(this);
- } else {
- p->transforms.append(this);
- d->items.append(item);
- }
-
- p->dirty(QQuickItemPrivate::Transform);
-}
-
-void QQuickTransform::prependToItem(QQuickItem *item)
-{
- Q_D(QQuickTransform);
- if (!item)
- return;
-
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
-
- if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
- p->transforms.removeOne(this);
- p->transforms.prepend(this);
- } else {
- p->transforms.prepend(this);
- d->items.append(item);
- }
-
- p->dirty(QQuickItemPrivate::Transform);
-}
-
-void QQuickItemPrivate::transform_append(QDeclarativeListProperty<QQuickTransform> *prop, QQuickTransform *transform)
-{
- if (!transform)
- return;
-
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- transform->appendToItem(that);
-}
-
-QQuickTransform *QQuickItemPrivate::transform_at(QDeclarativeListProperty<QQuickTransform> *prop, int idx)
-{
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- QQuickItemPrivate *p = QQuickItemPrivate::get(that);
-
- if (idx < 0 || idx >= p->transforms.count())
- return 0;
- else
- return p->transforms.at(idx);
-}
-
-void QQuickItemPrivate::transform_clear(QDeclarativeListProperty<QQuickTransform> *prop)
-{
- QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- QQuickItemPrivate *p = QQuickItemPrivate::get(that);
-
- for (int ii = 0; ii < p->transforms.count(); ++ii) {
- QQuickTransform *t = p->transforms.at(ii);
- QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
- tp->items.removeOne(that);
- }
-
- p->transforms.clear();
-
- p->dirty(QQuickItemPrivate::Transform);
-}
-
-/*!
- \property QQuickItem::childrenRect
- \brief The geometry of an item's children.
-
- This property holds the (collective) position and size of the item's children.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Item::x
- \qmlproperty real QtQuick2::Item::y
- \qmlproperty real QtQuick2::Item::width
- \qmlproperty real QtQuick2::Item::height
-
- Defines the item's position and size relative to its parent.
-
- \qml
- Item { x: 100; y: 100; width: 100; height: 100 }
- \endqml
- */
-
-/*!
- \qmlproperty real QtQuick2::Item::z
-
- Sets the stacking order of sibling items. By default the stacking order is 0.
-
- Items with a higher stacking value are drawn on top of siblings with a
- lower stacking order. Items with the same stacking value are drawn
- bottom up in the order they appear. Items with a negative stacking
- value are drawn under their parent's content.
-
- The following example shows the various effects of stacking order.
-
- \table
- \row
- \o \image declarative-item_stacking1.png
- \o Same \c z - later children above earlier children:
- \qml
- Item {
- Rectangle {
- color: "red"
- width: 100; height: 100
- }
- Rectangle {
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- \endqml
- \row
- \o \image declarative-item_stacking2.png
- \o Higher \c z on top:
- \qml
- Item {
- Rectangle {
- z: 1
- color: "red"
- width: 100; height: 100
- }
- Rectangle {
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- \endqml
- \row
- \o \image declarative-item_stacking3.png
- \o Same \c z - children above parents:
- \qml
- Item {
- Rectangle {
- color: "red"
- width: 100; height: 100
- Rectangle {
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- }
- \endqml
- \row
- \o \image declarative-item_stacking4.png
- \o Lower \c z below:
- \qml
- Item {
- Rectangle {
- color: "red"
- width: 100; height: 100
- Rectangle {
- z: -1
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- }
- \endqml
- \endtable
- */
-
-/*!
- \qmlproperty bool QtQuick2::Item::visible
-
- This property holds whether the item is visible. By default this is true.
-
- Setting this property directly affects the \c visible value of child
- items. When set to \c false, the \c visible values of all child items also
- become \c false. When set to \c true, the \c visible values of child items
- are returned to \c true, unless they have explicitly been set to \c false.
-
- (Because of this flow-on behavior, using the \c visible property may not
- have the intended effect if a property binding should only respond to
- explicit property changes. In such cases it may be better to use the
- \l opacity property instead.)
-
- Setting this property to \c false automatically causes \l focus to be set
- to \c false, and this item will longer receive mouse and keyboard events.
- (In contrast, setting the \l opacity to 0 does not affect the \l focus
- property and the receiving of key events.)
-
- \note This property's value is only affected by changes to this property or
- the parent's \c visible property. It does not change, for example, if this
- item moves off-screen, or if the \l opacity changes to 0.
-*/
-
-
-/*!
- \qmlproperty AnchorLine QtQuick2::Item::anchors.top
- \qmlproperty AnchorLine QtQuick2::Item::anchors.bottom
- \qmlproperty AnchorLine QtQuick2::Item::anchors.left
- \qmlproperty AnchorLine QtQuick2::Item::anchors.right
- \qmlproperty AnchorLine QtQuick2::Item::anchors.horizontalCenter
- \qmlproperty AnchorLine QtQuick2::Item::anchors.verticalCenter
- \qmlproperty AnchorLine QtQuick2::Item::anchors.baseline
-
- \qmlproperty Item QtQuick2::Item::anchors.fill
- \qmlproperty Item QtQuick2::Item::anchors.centerIn
-
- \qmlproperty real QtQuick2::Item::anchors.margins
- \qmlproperty real QtQuick2::Item::anchors.topMargin
- \qmlproperty real QtQuick2::Item::anchors.bottomMargin
- \qmlproperty real QtQuick2::Item::anchors.leftMargin
- \qmlproperty real QtQuick2::Item::anchors.rightMargin
- \qmlproperty real QtQuick2::Item::anchors.horizontalCenterOffset
- \qmlproperty real QtQuick2::Item::anchors.verticalCenterOffset
- \qmlproperty real QtQuick2::Item::anchors.baselineOffset
-
- \qmlproperty bool QtQuick2::Item::anchors.mirrored
-
- Anchors provide a way to position an item by specifying its
- relationship with other items.
-
- Margins apply to top, bottom, left, right, and fill anchors.
- The \c anchors.margins property can be used to set all of the various margins at once, to the same value.
- Note that margins are anchor-specific and are not applied if an item does not
- use anchors.
-
- Offsets apply for horizontal center, vertical center, and baseline anchors.
-
- \table
- \row
- \o \image declarative-anchors_example.png
- \o Text anchored to Image, horizontally centered and vertically below, with a margin.
- \qml
- Item {
- Image {
- id: pic
- // ...
- }
- Text {
- id: label
- anchors.horizontalCenter: pic.horizontalCenter
- anchors.top: pic.bottom
- anchors.topMargin: 5
- // ...
- }
- }
- \endqml
- \row
- \o \image declarative-anchors_example2.png
- \o
- Left of Text anchored to right of Image, with a margin. The y
- property of both defaults to 0.
-
- \qml
- Item {
- Image {
- id: pic
- // ...
- }
- Text {
- id: label
- anchors.left: pic.right
- anchors.leftMargin: 5
- // ...
- }
- }
- \endqml
- \endtable
-
- \c anchors.fill provides a convenient way for one item to have the
- same geometry as another item, and is equivalent to connecting all
- four directional anchors.
-
- To clear an anchor value, set it to \c undefined.
-
- \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}.
-
- \note You can only anchor an item to siblings or a parent.
-
- For more information see \l {anchor-layout}{Anchor Layouts}.
-*/
-
-/*!
- \property QQuickItem::baselineOffset
- \brief The position of the item's baseline in local coordinates.
-
- The baseline of a \l Text item is the imaginary line on which the text
- sits. Controls containing text usually set their baseline to the
- baseline of their text.
-
- For non-text items, a default baseline offset of 0 is used.
-*/
-QQuickAnchors *QQuickItemPrivate::anchors() const
-{
- if (!_anchors) {
- Q_Q(const QQuickItem);
- _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
- if (!componentComplete)
- _anchors->classBegin();
- }
- return _anchors;
-}
-
-QQuickItemPrivate::AnchorLines *QQuickItemPrivate::anchorLines() const
-{
- Q_Q(const QQuickItem);
- if (!_anchorLines) _anchorLines =
- new AnchorLines(const_cast<QQuickItem *>(q));
- return _anchorLines;
-}
-
-void QQuickItemPrivate::siblingOrderChanged()
-{
- Q_Q(QQuickItem);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::SiblingOrder) {
- change.listener->itemSiblingOrderChanged(q);
- }
- }
-}
-
-QDeclarativeListProperty<QObject> QQuickItemPrivate::data()
-{
- return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
- QQuickItemPrivate::data_count,
- QQuickItemPrivate::data_at,
- QQuickItemPrivate::data_clear);
-}
-
-QRectF QQuickItem::childrenRect()
-{
- Q_D(QQuickItem);
- if (!d->_contents) {
- d->_contents = new QQuickContents(this);
- if (d->componentComplete)
- d->_contents->complete();
- }
- return d->_contents->rectF();
-}
-
-QList<QQuickItem *> QQuickItem::childItems() const
-{
- Q_D(const QQuickItem);
- return d->childItems;
-}
-
-bool QQuickItem::clip() const
-{
- return flags() & ItemClipsChildrenToShape;
-}
-
-void QQuickItem::setClip(bool c)
-{
- if (clip() == c)
- return;
-
- setFlag(ItemClipsChildrenToShape, c);
-
- emit clipChanged(c);
-}
-
-
-/*!
- This function is called to handle this item's changes in
- geometry from \a oldGeometry to \a newGeometry. If the two
- geometries are the same, it doesn't do anything.
- */
-void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_D(QQuickItem);
-
- if (d->_anchors)
- QQuickAnchorsPrivate::get(d->_anchors)->updateMe();
-
- bool xChange = (newGeometry.x() != oldGeometry.x());
- bool yChange = (newGeometry.y() != oldGeometry.y());
- bool widthChange = (newGeometry.width() != oldGeometry.width());
- bool heightChange = (newGeometry.height() != oldGeometry.height());
-
- for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Geometry) {
- if (change.gTypes == QQuickItemPrivate::GeometryChange) {
- change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
- } else if ((xChange && (change.gTypes & QQuickItemPrivate::XChange)) ||
- (yChange && (change.gTypes & QQuickItemPrivate::YChange)) ||
- (widthChange && (change.gTypes & QQuickItemPrivate::WidthChange)) ||
- (heightChange && (change.gTypes & QQuickItemPrivate::HeightChange))) {
- change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
- }
- }
- }
-
- if (xChange)
- emit xChanged();
- if (yChange)
- emit yChanged();
- if (widthChange)
- emit widthChanged();
- if (heightChange)
- emit heightChanged();
-}
-
-/*!
- Called by the rendering thread when it is time to sync the state of the QML objects with the
- scene graph objects. The function should return the root of the scene graph subtree for
- this item. \a oldNode is the node that was returned the last time the function was called.
-
- The main thread is blocked while this function is executed so it is safe to read
- values from the QQuickItem instance and other objects in the main thread.
-
- \warning This is the only function in which it is allowed to make use of scene graph
- objects from the main thread. Use of scene graph objects outside this function will
- result in race conditions and potential crashes.
- */
-
-QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- delete oldNode;
- return 0;
-}
-
-QSGTransformNode *QQuickItemPrivate::createTransformNode()
-{
- return new QSGTransformNode;
-}
-
-void QQuickItem::updatePolish()
-{
-}
-
-void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
-{
- ChangeListener change(listener, types);
- changeListeners.removeOne(change);
-}
-
-void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
-{
- ChangeListener change(listener, types);
- int index = changeListeners.find(change);
- if (index > -1)
- changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
- else
- changeListeners.append(change);
-}
-
-void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
-{
- ChangeListener change(listener, types);
- if (types == NoChange) {
- changeListeners.removeOne(change);
- } else {
- int index = changeListeners.find(change);
- if (index > -1)
- changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
- }
-}
-
-void QQuickItem::keyPressEvent(QKeyEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::keyReleaseEvent(QKeyEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::focusInEvent(QFocusEvent *)
-{
-}
-
-void QQuickItem::focusOutEvent(QFocusEvent *)
-{
-}
-
-void QQuickItem::mousePressEvent(QMouseEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::mouseMoveEvent(QMouseEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::mouseDoubleClickEvent(QMouseEvent *event)
-{
- mousePressEvent(event);
-}
-
-void QQuickItem::mouseUngrabEvent()
-{
- // XXX todo
-}
-
-void QQuickItem::touchUngrabEvent()
-{
- // XXX todo
-}
-
-void QQuickItem::wheelEvent(QWheelEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::touchEvent(QTouchEvent *event)
-{
- event->ignore();
-}
-
-void QQuickItem::hoverEnterEvent(QHoverEvent *event)
-{
- Q_UNUSED(event);
-}
-
-void QQuickItem::hoverMoveEvent(QHoverEvent *event)
-{
- Q_UNUSED(event);
-}
-
-void QQuickItem::hoverLeaveEvent(QHoverEvent *event)
-{
- Q_UNUSED(event);
-}
-
-void QQuickItem::dragEnterEvent(QDragEnterEvent *event)
-{
- Q_UNUSED(event);
-}
-
-void QQuickItem::dragMoveEvent(QDragMoveEvent *event)
-{
-
- Q_UNUSED(event);
-}
-
-void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event)
-{
-
- Q_UNUSED(event);
-}
-
-void QQuickItem::dropEvent(QDropEvent *event)
-{
- Q_UNUSED(event);
-}
-
-bool QQuickItem::childMouseEventFilter(QQuickItem *, QEvent *)
-{
- return false;
-}
-
-void QQuickItem::windowDeactivateEvent()
-{
- foreach (QQuickItem* item, childItems()) {
- item->windowDeactivateEvent();
- }
-}
-
-Qt::InputMethodHints QQuickItem::inputMethodHints() const
-{
- Q_D(const QQuickItem);
- return d->imHints;
-}
-
-void QQuickItem::setInputMethodHints(Qt::InputMethodHints hints)
-{
- Q_D(QQuickItem);
- d->imHints = hints;
-
- if (!d->canvas || d->canvas->activeFocusItem() != this)
- return;
-
- QInputPanel *p = qApp->inputPanel();
- if (p->inputItem() == this)
- qApp->inputPanel()->update(Qt::ImHints);
-}
-
-void QQuickItem::updateMicroFocus()
-{
- QInputPanel *p = qApp->inputPanel();
- if (p->inputItem() == this)
- qApp->inputPanel()->update(Qt::ImQueryInput);
-}
-
-QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
-{
- Q_D(const QQuickItem);
- QVariant v;
-
- switch (query) {
- case Qt::ImEnabled:
- v = (bool)(flags() & ItemAcceptsInputMethod);
- break;
- case Qt::ImHints:
- v = (int)inputMethodHints();
- break;
- case Qt::ImCursorRectangle:
- case Qt::ImFont:
- case Qt::ImCursorPosition:
- case Qt::ImSurroundingText:
- case Qt::ImCurrentSelection:
- case Qt::ImMaximumTextLength:
- case Qt::ImAnchorPosition:
- case Qt::ImPreferredLanguage:
- if (d->keyHandler)
- v = d->keyHandler->inputMethodQuery(query);
- default:
- break;
- }
-
- return v;
-}
-
-QQuickAnchorLine QQuickItemPrivate::left() const
-{
- return anchorLines()->left;
-}
-
-QQuickAnchorLine QQuickItemPrivate::right() const
-{
- return anchorLines()->right;
-}
-
-QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
-{
- return anchorLines()->hCenter;
-}
-
-QQuickAnchorLine QQuickItemPrivate::top() const
-{
- return anchorLines()->top;
-}
-
-QQuickAnchorLine QQuickItemPrivate::bottom() const
-{
- return anchorLines()->bottom;
-}
-
-QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
-{
- return anchorLines()->vCenter;
-}
-
-QQuickAnchorLine QQuickItemPrivate::baseline() const
-{
- return anchorLines()->baseline;
-}
-
-qreal QQuickItem::baselineOffset() const
-{
- Q_D(const QQuickItem);
- if (!d->baselineOffset.isValid()) {
- return 0.0;
- } else
- return d->baselineOffset;
-}
-
-void QQuickItem::setBaselineOffset(qreal offset)
-{
- Q_D(QQuickItem);
- if (offset == d->baselineOffset)
- return;
-
- d->baselineOffset = offset;
-
- for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Geometry) {
- QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
- if (anchor)
- anchor->updateVerticalAnchors();
- }
- }
- emit baselineOffsetChanged(offset);
-}
-
-void QQuickItem::update()
-{
- Q_D(QQuickItem);
- Q_ASSERT(flags() & ItemHasContents);
- d->dirty(QQuickItemPrivate::Content);
-}
-
-void QQuickItem::polish()
-{
- Q_D(QQuickItem);
- if (!d->polishScheduled) {
- d->polishScheduled = true;
- if (d->canvas) {
- QQuickCanvasPrivate *p = QQuickCanvasPrivate::get(d->canvas);
- bool maybeupdate = p->itemsToPolish.isEmpty();
- p->itemsToPolish.insert(this);
- if (maybeupdate) d->canvas->maybeUpdate();
- }
- }
-}
-
-void QQuickItem::mapFromItem(QDeclarativeV8Function *args) const
-{
- if (args->Length() != 0) {
- v8::Local<v8::Value> item = (*args)[0];
- QV8Engine *engine = args->engine();
-
- QQuickItem *itemObj = 0;
- if (!item->IsNull())
- itemObj = qobject_cast<QQuickItem*>(engine->toQObject(item));
-
- if (!itemObj && !item->IsNull()) {
- qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
- << "\" which is neither null nor an Item";
- return;
- }
-
- v8::Local<v8::Object> rv = v8::Object::New();
- args->returnValue(rv);
-
- qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
- qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
-
- QPointF p = mapFromItem(itemObj, QPointF(x, y));
-
- rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
- rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
- }
-}
-
-QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
-{
- Q_D(const QQuickItem);
-
- // XXX todo - we need to be able to handle common parents better and detect
- // invalid cases
- if (ok) *ok = true;
-
- QTransform t = d->itemToCanvasTransform();
- if (other) t *= QQuickItemPrivate::get(other)->canvasToItemTransform();
-
- return t;
-}
-
-void QQuickItem::mapToItem(QDeclarativeV8Function *args) const
-{
- if (args->Length() != 0) {
- v8::Local<v8::Value> item = (*args)[0];
- QV8Engine *engine = args->engine();
-
- QQuickItem *itemObj = 0;
- if (!item->IsNull())
- itemObj = qobject_cast<QQuickItem*>(engine->toQObject(item));
-
- if (!itemObj && !item->IsNull()) {
- qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
- << "\" which is neither null nor an Item";
- return;
- }
-
- v8::Local<v8::Object> rv = v8::Object::New();
- args->returnValue(rv);
-
- qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
- qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
-
- QPointF p = mapToItem(itemObj, QPointF(x, y));
-
- rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
- rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
- }
-}
-
-void QQuickItem::forceActiveFocus()
-{
- setFocus(true);
- QQuickItem *parent = parentItem();
- while (parent) {
- if (parent->flags() & QQuickItem::ItemIsFocusScope) {
- parent->setFocus(true);
- }
- parent = parent->parentItem();
- }
-}
-
-QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
-{
- // XXX todo - should this include transform etc.?
- const QList<QQuickItem *> children = childItems();
- for (int i = children.count()-1; i >= 0; --i) {
- QQuickItem *child = children.at(i);
- if (child->isVisible() && child->x() <= x
- && child->x() + child->width() >= x
- && child->y() <= y
- && child->y() + child->height() >= y)
- return child;
- }
- return 0;
-}
-
-QDeclarativeListProperty<QObject> QQuickItemPrivate::resources()
-{
- return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
- QQuickItemPrivate::resources_count,
- QQuickItemPrivate::resources_at,
- QQuickItemPrivate::resources_clear);
-}
-
-QDeclarativeListProperty<QQuickItem> QQuickItemPrivate::children()
-{
- return QDeclarativeListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
- QQuickItemPrivate::children_count,
- QQuickItemPrivate::children_at,
- QQuickItemPrivate::children_clear);
-
-}
-
-QDeclarativeListProperty<QDeclarativeState> QQuickItemPrivate::states()
-{
- return _states()->statesProperty();
-}
-
-QDeclarativeListProperty<QDeclarativeTransition> QQuickItemPrivate::transitions()
-{
- return _states()->transitionsProperty();
-}
-
-QString QQuickItemPrivate::state() const
-{
- if (!_stateGroup)
- return QString();
- else
- return _stateGroup->state();
-}
-
-void QQuickItemPrivate::setState(const QString &state)
-{
- _states()->setState(state);
-}
-
-QString QQuickItem::state() const
-{
- Q_D(const QQuickItem);
- return d->state();
-}
-
-void QQuickItem::setState(const QString &state)
-{
- Q_D(QQuickItem);
- d->setState(state);
-}
-
-QDeclarativeListProperty<QQuickTransform> QQuickItem::transform()
-{
- return QDeclarativeListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
- QQuickItemPrivate::transform_count,
- QQuickItemPrivate::transform_at,
- QQuickItemPrivate::transform_clear);
-}
-
-void QQuickItem::classBegin()
-{
- Q_D(QQuickItem);
- d->componentComplete = false;
- if (d->_stateGroup)
- d->_stateGroup->classBegin();
- if (d->_anchors)
- d->_anchors->classBegin();
-}
-
-void QQuickItem::componentComplete()
-{
- Q_D(QQuickItem);
- d->componentComplete = true;
- if (d->_stateGroup)
- d->_stateGroup->componentComplete();
- if (d->_anchors) {
- d->_anchors->componentComplete();
- QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
- }
- if (d->keyHandler)
- d->keyHandler->componentComplete();
- if (d->_contents)
- d->_contents->complete();
-}
-
-QDeclarativeStateGroup *QQuickItemPrivate::_states()
-{
- Q_Q(QQuickItem);
- if (!_stateGroup) {
- _stateGroup = new QDeclarativeStateGroup;
- if (!componentComplete)
- _stateGroup->classBegin();
- FAST_CONNECT(_stateGroup, SIGNAL(stateChanged(QString)),
- q, SIGNAL(stateChanged(QString)))
- }
-
- return _stateGroup;
-}
-
-QQuickItemPrivate::AnchorLines::AnchorLines(QQuickItem *q)
-{
- left.item = q;
- left.anchorLine = QQuickAnchorLine::Left;
- right.item = q;
- right.anchorLine = QQuickAnchorLine::Right;
- hCenter.item = q;
- hCenter.anchorLine = QQuickAnchorLine::HCenter;
- top.item = q;
- top.anchorLine = QQuickAnchorLine::Top;
- bottom.item = q;
- bottom.anchorLine = QQuickAnchorLine::Bottom;
- vCenter.item = q;
- vCenter.anchorLine = QQuickAnchorLine::VCenter;
- baseline.item = q;
- baseline.anchorLine = QQuickAnchorLine::Baseline;
-}
-
-QPointF QQuickItemPrivate::computeTransformOrigin() const
-{
- switch (origin) {
- default:
- case QQuickItem::TopLeft:
- return QPointF(0, 0);
- case QQuickItem::Top:
- return QPointF(width / 2., 0);
- case QQuickItem::TopRight:
- return QPointF(width, 0);
- case QQuickItem::Left:
- return QPointF(0, height / 2.);
- case QQuickItem::Center:
- return QPointF(width / 2., height / 2.);
- case QQuickItem::Right:
- return QPointF(width, height / 2.);
- case QQuickItem::BottomLeft:
- return QPointF(0, height);
- case QQuickItem::Bottom:
- return QPointF(width / 2., height);
- case QQuickItem::BottomRight:
- return QPointF(width, height);
- }
-}
-
-void QQuickItemPrivate::transformChanged()
-{
-}
-
-void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(e->isAccepted());
- if (keyHandler) {
- if (e->type() == QEvent::KeyPress)
- keyHandler->keyPressed(e, false);
- else
- keyHandler->keyReleased(e, false);
-
- if (e->isAccepted())
- return;
- else
- e->accept();
- }
-
- if (e->type() == QEvent::KeyPress)
- q->keyPressEvent(e);
- else
- q->keyReleaseEvent(e);
-
- if (e->isAccepted())
- return;
-
- if (keyHandler) {
- e->accept();
-
- if (e->type() == QEvent::KeyPress)
- keyHandler->keyPressed(e, true);
- else
- keyHandler->keyReleased(e, true);
- }
-}
-
-void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(e->isAccepted());
- if (keyHandler) {
- keyHandler->inputMethodEvent(e, false);
-
- if (e->isAccepted())
- return;
- else
- e->accept();
- }
-
- q->inputMethodEvent(e);
-
- if (e->isAccepted())
- return;
-
- if (keyHandler) {
- e->accept();
-
- keyHandler->inputMethodEvent(e, true);
- }
-}
-
-void QQuickItemPrivate::deliverFocusEvent(QFocusEvent *e)
-{
- Q_Q(QQuickItem);
-
- if (e->type() == QEvent::FocusIn) {
- q->focusInEvent(e);
- } else {
- q->focusOutEvent(e);
- }
-}
-
-void QQuickItemPrivate::deliverMouseEvent(QMouseEvent *e)
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(e->isAccepted());
-
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::MouseMove:
- q->mouseMoveEvent(e);
- break;
- case QEvent::MouseButtonPress:
- q->mousePressEvent(e);
- break;
- case QEvent::MouseButtonRelease:
- q->mouseReleaseEvent(e);
- break;
- case QEvent::MouseButtonDblClick:
- q->mouseDoubleClickEvent(e);
- break;
- }
-}
-
-void QQuickItemPrivate::deliverWheelEvent(QWheelEvent *e)
-{
- Q_Q(QQuickItem);
- q->wheelEvent(e);
-}
-
-void QQuickItemPrivate::deliverTouchEvent(QTouchEvent *e)
-{
- Q_Q(QQuickItem);
- q->touchEvent(e);
-}
-
-void QQuickItemPrivate::deliverHoverEvent(QHoverEvent *e)
-{
- Q_Q(QQuickItem);
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::HoverEnter:
- q->hoverEnterEvent(e);
- break;
- case QEvent::HoverLeave:
- q->hoverLeaveEvent(e);
- break;
- case QEvent::HoverMove:
- q->hoverMoveEvent(e);
- break;
- }
-}
-
-void QQuickItemPrivate::deliverDragEvent(QEvent *e)
-{
- Q_Q(QQuickItem);
- switch (e->type()) {
- default:
- Q_ASSERT(!"Unknown event type");
- case QEvent::DragEnter:
- q->dragEnterEvent(static_cast<QDragEnterEvent *>(e));
- break;
- case QEvent::DragLeave:
- q->dragLeaveEvent(static_cast<QDragLeaveEvent *>(e));
- break;
- case QEvent::DragMove:
- q->dragMoveEvent(static_cast<QDragMoveEvent *>(e));
- break;
- case QEvent::Drop:
- q->dropEvent(static_cast<QDropEvent *>(e));
- break;
- }
-}
-
-void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
-{
- Q_UNUSED(change);
- Q_UNUSED(value);
-}
-
-/*! \internal */
-// XXX todo - do we want/need this anymore?
-// Note that it's now used for varying clip rect
-QRectF QQuickItem::boundingRect() const
-{
- Q_D(const QQuickItem);
- return QRectF(0, 0, d->width, d->height);
-}
-
-QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
-{
- Q_D(const QQuickItem);
- return d->origin;
-}
-
-void QQuickItem::setTransformOrigin(TransformOrigin origin)
-{
- Q_D(QQuickItem);
- if (origin == d->origin)
- return;
-
- d->origin = origin;
- d->dirty(QQuickItemPrivate::TransformOrigin);
-
- emit transformOriginChanged(d->origin);
-}
-
-QPointF QQuickItem::transformOriginPoint() const
-{
- Q_D(const QQuickItem);
- if (!d->transformOriginPoint.isNull())
- return d->transformOriginPoint;
- return d->computeTransformOrigin();
-}
-
-void QQuickItem::setTransformOriginPoint(const QPointF &point)
-{
- Q_D(QQuickItem);
- if (d->transformOriginPoint == point)
- return;
-
- d->transformOriginPoint = point;
- d->dirty(QQuickItemPrivate::TransformOrigin);
-}
-
-qreal QQuickItem::z() const
-{
- Q_D(const QQuickItem);
- return d->z;
-}
-
-void QQuickItem::setZ(qreal v)
-{
- Q_D(QQuickItem);
- if (d->z == v)
- return;
-
- d->z = v;
-
- d->dirty(QQuickItemPrivate::ZValue);
- if (d->parentItem) {
- QQuickItemPrivate::get(d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
- QQuickItemPrivate::get(d->parentItem)->markSortedChildrenDirty(this);
- }
-
- emit zChanged();
-}
-
-
-/*!
- \qmlproperty real QtQuick2::Item::rotation
- This property holds the rotation of the item in degrees clockwise.
-
- This specifies how many degrees to rotate the item around its transformOrigin.
- The default rotation is 0 degrees (i.e. not rotated at all).
-
- \table
- \row
- \o \image declarative-rotation.png
- \o
- \qml
- Rectangle {
- color: "blue"
- width: 100; height: 100
- Rectangle {
- color: "red"
- x: 25; y: 25; width: 50; height: 50
- rotation: 30
- }
- }
- \endqml
- \endtable
-
- \sa transform, Rotation
-*/
-
-/*!
- \qmlproperty real QtQuick2::Item::scale
- This property holds the scale of the item.
-
- A scale of less than 1 means the item will be displayed smaller than
- normal, and a scale of greater than 1 means the item will be
- displayed larger than normal. A negative scale means the item will
- be mirrored.
-
- By default, items are displayed at a scale of 1 (i.e. at their
- normal size).
-
- Scaling is from the item's transformOrigin.
-
- \table
- \row
- \o \image declarative-scale.png
- \o
- \qml
- Rectangle {
- color: "blue"
- width: 100; height: 100
- Rectangle {
- color: "green"
- width: 25; height: 25
- }
- Rectangle {
- color: "red"
- x: 25; y: 25; width: 50; height: 50
- scale: 1.4
- }
- }
- \endqml
- \endtable
-
- \sa transform, Scale
-*/
-
-/*!
- \qmlproperty real QtQuick2::Item::opacity
-
- This property holds the opacity of the item. Opacity is specified as a
- number between 0 (fully transparent) and 1 (fully opaque). The default is 1.
-
- When this property is set, the specified opacity is also applied
- individually to child items. In almost all cases this is what you want,
- but in some cases it may produce undesired results. For example in the
- second set of rectangles below, the red rectangle has specified an opacity
- of 0.5, which affects the opacity of its blue child rectangle even though
- the child has not specified an opacity.
-
- \table
- \row
- \o \image declarative-item_opacity1.png
- \o
- \qml
- Item {
- Rectangle {
- color: "red"
- width: 100; height: 100
- Rectangle {
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- }
- \endqml
- \row
- \o \image declarative-item_opacity2.png
- \o
- \qml
- Item {
- Rectangle {
- opacity: 0.5
- color: "red"
- width: 100; height: 100
- Rectangle {
- color: "blue"
- x: 50; y: 50; width: 100; height: 100
- }
- }
- }
- \endqml
- \endtable
-
- If an item's opacity is set to 0, the item will no longer receive mouse
- events, but will continue to receive key events and will retain the keyboard
- \l focus if it has been set. (In contrast, setting the \l visible property
- to \c false stops both mouse and keyboard events, and also removes focus
- from the item.)
-*/
-
-/*!
- Returns a value indicating whether mouse input should
- remain with this item exclusively.
-
- \sa setKeepMouseGrab()
- */
-
-qreal QQuickItem::rotation() const
-{
- Q_D(const QQuickItem);
- return d->rotation;
-}
-
-void QQuickItem::setRotation(qreal r)
-{
- Q_D(QQuickItem);
- if (d->rotation == r)
- return;
-
- d->rotation = r;
-
- d->dirty(QQuickItemPrivate::BasicTransform);
-
- d->itemChange(ItemRotationHasChanged, r);
-
- emit rotationChanged();
-}
-
-qreal QQuickItem::scale() const
-{
- Q_D(const QQuickItem);
- return d->scale;
-}
-
-void QQuickItem::setScale(qreal s)
-{
- Q_D(QQuickItem);
- if (d->scale == s)
- return;
-
- d->scale = s;
-
- d->dirty(QQuickItemPrivate::BasicTransform);
-
- emit scaleChanged();
-}
-
-qreal QQuickItem::opacity() const
-{
- Q_D(const QQuickItem);
- return d->opacity;
-}
-
-void QQuickItem::setOpacity(qreal o)
-{
- Q_D(QQuickItem);
- if (d->opacity == o)
- return;
-
- d->opacity = o;
-
- d->dirty(QQuickItemPrivate::OpacityValue);
-
- d->itemChange(ItemOpacityHasChanged, o);
-
- emit opacityChanged();
-}
-
-bool QQuickItem::isVisible() const
-{
- Q_D(const QQuickItem);
- return d->effectiveVisible;
-}
-
-void QQuickItem::setVisible(bool v)
-{
- Q_D(QQuickItem);
- if (v == d->explicitVisible)
- return;
-
- d->explicitVisible = v;
-
- d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
-}
-
-bool QQuickItem::isEnabled() const
-{
- Q_D(const QQuickItem);
- return d->effectiveEnable;
-}
-
-void QQuickItem::setEnabled(bool e)
-{
- Q_D(QQuickItem);
- if (e == d->explicitEnable)
- return;
-
- d->explicitEnable = e;
-
- d->setEffectiveEnableRecur(d->calcEffectiveEnable());
-}
-
-bool QQuickItemPrivate::calcEffectiveVisible() const
-{
- // XXX todo - Should the effective visible of an element with no parent just be the current
- // effective visible? This would prevent pointless re-processing in the case of an element
- // moving to/from a no-parent situation, but it is different from what graphics view does.
- return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
-}
-
-void QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
-{
- Q_Q(QQuickItem);
-
- if (newEffectiveVisible && !explicitVisible) {
- // This item locally overrides visibility
- return;
- }
-
- if (newEffectiveVisible == effectiveVisible) {
- // No change necessary
- return;
- }
-
- effectiveVisible = newEffectiveVisible;
- dirty(Visible);
- if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
-
- if (canvas) {
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
- if (canvasPriv->mouseGrabberItem == q)
- q->ungrabMouse();
- }
-
- for (int ii = 0; ii < childItems.count(); ++ii)
- QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
-
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Visibility)
- change.listener->itemVisibilityChanged(q);
- }
-
- emit q->visibleChanged();
-}
-
-bool QQuickItemPrivate::calcEffectiveEnable() const
-{
- // XXX todo - Should the effective enable of an element with no parent just be the current
- // effective enable? This would prevent pointless re-processing in the case of an element
- // moving to/from a no-parent situation, but it is different from what graphics view does.
- return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
-}
-
-void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
-{
- Q_Q(QQuickItem);
-
- // XXX todo - need to fixup focus
-
- if (newEffectiveEnable && !explicitEnable) {
- // This item locally overrides enable
- return;
- }
-
- if (newEffectiveEnable == effectiveEnable) {
- // No change necessary
- return;
- }
-
- effectiveEnable = newEffectiveEnable;
-
- if (canvas) {
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
- if (canvasPriv->mouseGrabberItem == q)
- q->ungrabMouse();
- }
-
- for (int ii = 0; ii < childItems.count(); ++ii)
- QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
-
- emit q->enabledChanged();
-}
-
-QString QQuickItemPrivate::dirtyToString() const
-{
-#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
- if (!rv.isEmpty()) \
- rv.append(QLatin1String("|")); \
- rv.append(QLatin1String(#value)); \
-}
-
-// QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
- QString rv;
-
- DIRTY_TO_STRING(TransformOrigin);
- DIRTY_TO_STRING(Transform);
- DIRTY_TO_STRING(BasicTransform);
- DIRTY_TO_STRING(Position);
- DIRTY_TO_STRING(Size);
- DIRTY_TO_STRING(ZValue);
- DIRTY_TO_STRING(Content);
- DIRTY_TO_STRING(Smooth);
- DIRTY_TO_STRING(OpacityValue);
- DIRTY_TO_STRING(ChildrenChanged);
- DIRTY_TO_STRING(ChildrenStackingChanged);
- DIRTY_TO_STRING(ParentChanged);
- DIRTY_TO_STRING(Clip);
- DIRTY_TO_STRING(Canvas);
- DIRTY_TO_STRING(EffectReference);
- DIRTY_TO_STRING(Visible);
- DIRTY_TO_STRING(HideReference);
-
- return rv;
-}
-
-void QQuickItemPrivate::dirty(DirtyType type)
-{
- Q_Q(QQuickItem);
- if (type & (TransformOrigin | Transform | BasicTransform | Position | Size))
- transformChanged();
-
- if (!(dirtyAttributes & type) || (canvas && !prevDirtyItem)) {
- dirtyAttributes |= type;
- if (canvas) {
- addToDirtyList();
- QQuickCanvasPrivate::get(canvas)->dirtyItem(q);
- }
- }
-}
-
-void QQuickItemPrivate::addToDirtyList()
-{
- Q_Q(QQuickItem);
-
- Q_ASSERT(canvas);
- if (!prevDirtyItem) {
- Q_ASSERT(!nextDirtyItem);
-
- QQuickCanvasPrivate *p = QQuickCanvasPrivate::get(canvas);
- nextDirtyItem = p->dirtyItemList;
- if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
- prevDirtyItem = &p->dirtyItemList;
- p->dirtyItemList = q;
- p->dirtyItem(q);
- }
- Q_ASSERT(prevDirtyItem);
-}
-
-void QQuickItemPrivate::removeFromDirtyList()
-{
- if (prevDirtyItem) {
- if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem;
- *prevDirtyItem = nextDirtyItem;
- prevDirtyItem = 0;
- nextDirtyItem = 0;
- }
- Q_ASSERT(!prevDirtyItem);
- Q_ASSERT(!nextDirtyItem);
-}
-
-void QQuickItemPrivate::refFromEffectItem(bool hide)
-{
- ++effectRefCount;
- if (1 == effectRefCount) {
- dirty(EffectReference);
- if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
- }
- if (hide) {
- if (++hideRefCount == 1)
- dirty(HideReference);
- }
-}
-
-void QQuickItemPrivate::derefFromEffectItem(bool unhide)
-{
- Q_ASSERT(effectRefCount);
- --effectRefCount;
- if (0 == effectRefCount) {
- dirty(EffectReference);
- if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
- }
- if (unhide) {
- if (--hideRefCount == 0)
- dirty(HideReference);
- }
-}
-
-void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
-{
- Q_Q(QQuickItem);
- switch (change) {
- case QQuickItem::ItemChildAddedChange:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Children) {
- change.listener->itemChildAdded(q, data.item);
- }
- }
- break;
- case QQuickItem::ItemChildRemovedChange:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Children) {
- change.listener->itemChildRemoved(q, data.item);
- }
- }
- break;
- case QQuickItem::ItemSceneChange:
- q->itemChange(change, data);
- break;
- case QQuickItem::ItemVisibleHasChanged:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Visibility) {
- change.listener->itemVisibilityChanged(q);
- }
- }
- break;
- case QQuickItem::ItemParentHasChanged:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Parent) {
- change.listener->itemParentChanged(q, data.item);
- }
- }
- break;
- case QQuickItem::ItemOpacityHasChanged:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Opacity) {
- change.listener->itemOpacityChanged(q);
- }
- }
- break;
- case QQuickItem::ItemActiveFocusHasChanged:
- q->itemChange(change, data);
- break;
- case QQuickItem::ItemRotationHasChanged:
- q->itemChange(change, data);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Rotation) {
- change.listener->itemRotationChanged(q);
- }
- }
- break;
- }
-}
-
-/*!
- \property QQuickItem::smooth
- \brief whether the item is smoothly transformed.
-
- 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.
-
- By default smooth transformations are off.
-*/
-
-/*!
- Returns true if the item should be drawn with antialiasing and
- smooth pixmap filtering, false otherwise.
-
- The default is false.
-
- \sa setSmooth()
-*/
-bool QQuickItem::smooth() const
-{
- Q_D(const QQuickItem);
- return d->smooth;
-}
-
-/*!
- Sets whether the item should be drawn with antialiasing and
- smooth pixmap filtering to \a smooth.
-
- \sa smooth()
-*/
-void QQuickItem::setSmooth(bool smooth)
-{
- Q_D(QQuickItem);
- if (d->smooth == smooth)
- return;
-
- d->smooth = smooth;
- d->dirty(QQuickItemPrivate::Smooth);
-
- emit smoothChanged(smooth);
-}
-
-QQuickItem::Flags QQuickItem::flags() const
-{
- Q_D(const QQuickItem);
- return (QQuickItem::Flags)d->flags;
-}
-
-void QQuickItem::setFlag(Flag flag, bool enabled)
-{
- Q_D(QQuickItem);
- if (enabled)
- setFlags((Flags)(d->flags | (quint32)flag));
- else
- setFlags((Flags)(d->flags & ~(quint32)flag));
-}
-
-void QQuickItem::setFlags(Flags flags)
-{
- Q_D(QQuickItem);
-
- if ((flags & ItemIsFocusScope) != (d->flags & ItemIsFocusScope)) {
- if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->canvas) {
- qWarning("QQuickItem: Cannot set FocusScope once item has children and is in a canvas.");
- flags &= ~ItemIsFocusScope;
- } else if (d->flags & ItemIsFocusScope) {
- qWarning("QQuickItem: Cannot unset FocusScope flag.");
- flags |= ItemIsFocusScope;
- }
- }
-
- if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape))
- d->dirty(QQuickItemPrivate::Clip);
-
- d->flags = flags;
-}
-
-qreal QQuickItem::x() const
-{
- Q_D(const QQuickItem);
- return d->x;
-}
-
-qreal QQuickItem::y() const
-{
- Q_D(const QQuickItem);
- return d->y;
-}
-
-QPointF QQuickItem::pos() const
-{
- Q_D(const QQuickItem);
- return QPointF(d->x, d->y);
-}
-
-void QQuickItem::setX(qreal v)
-{
- Q_D(QQuickItem);
- if (d->x == v)
- return;
-
- qreal oldx = d->x;
- d->x = v;
-
- d->dirty(QQuickItemPrivate::Position);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(oldx, y(), width(), height()));
-}
-
-void QQuickItem::setY(qreal v)
-{
- Q_D(QQuickItem);
- if (d->y == v)
- return;
-
- qreal oldy = d->y;
- d->y = v;
-
- d->dirty(QQuickItemPrivate::Position);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), oldy, width(), height()));
-}
-
-void QQuickItem::setPos(const QPointF &pos)
-{
- Q_D(QQuickItem);
- if (QPointF(d->x, d->y) == pos)
- return;
-
- qreal oldx = d->x;
- qreal oldy = d->y;
-
- d->x = pos.x();
- d->y = pos.y();
-
- d->dirty(QQuickItemPrivate::Position);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(oldx, oldy, width(), height()));
-}
-
-qreal QQuickItem::width() const
-{
- Q_D(const QQuickItem);
- return d->width;
-}
-
-void QQuickItem::setWidth(qreal w)
-{
- Q_D(QQuickItem);
- if (qIsNaN(w))
- return;
-
- d->widthValid = true;
- if (d->width == w)
- return;
-
- qreal oldWidth = d->width;
- d->width = w;
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), oldWidth, height()));
-}
-
-void QQuickItem::resetWidth()
-{
- Q_D(QQuickItem);
- d->widthValid = false;
- setImplicitWidth(implicitWidth());
-}
-
-void QQuickItemPrivate::implicitWidthChanged()
-{
- Q_Q(QQuickItem);
- emit q->implicitWidthChanged();
-}
-
-qreal QQuickItemPrivate::getImplicitWidth() const
-{
- return implicitWidth;
-}
-/*!
- Returns the width of the item that is implied by other properties that determine the content.
-*/
-qreal QQuickItem::implicitWidth() const
-{
- Q_D(const QQuickItem);
- return d->getImplicitWidth();
-}
-
-/*!
- \qmlproperty real QtQuick2::Item::implicitWidth
- \qmlproperty real QtQuick2::Item::implicitHeight
-
- Defines the natural width or height of the Item if no \l width or \l height is specified.
-
- The default implicit size for most items is 0x0, however some elements have an inherent
- implicit size which cannot be overridden, e.g. Image, Text.
-
- Setting the implicit size is useful for defining components that have a preferred size
- based on their content, for example:
-
- \qml
- // Label.qml
- import QtQuick 1.1
-
- Item {
- property alias icon: image.source
- property alias label: text.text
- implicitWidth: text.implicitWidth + image.implicitWidth
- implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
- Image { id: image }
- Text {
- id: text
- wrapMode: Text.Wrap
- anchors.left: image.right; anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- \endqml
-
- \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly
- incurs a performance penalty as the text must be laid out twice.
-*/
-
-/*!
- Sets the implied width of the item to \a w.
- This is the width implied by other properties that determine the content.
-*/
-void QQuickItem::setImplicitWidth(qreal w)
-{
- Q_D(QQuickItem);
- bool changed = w != d->implicitWidth;
- d->implicitWidth = w;
- if (d->width == w || widthValid()) {
- if (changed)
- d->implicitWidthChanged();
- return;
- }
-
- qreal oldWidth = d->width;
- d->width = w;
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), oldWidth, height()));
-
- if (changed)
- d->implicitWidthChanged();
-}
-
-/*!
- Returns whether the width property has been set explicitly.
-*/
-bool QQuickItem::widthValid() const
-{
- Q_D(const QQuickItem);
- return d->widthValid;
-}
-
-qreal QQuickItem::height() const
-{
- Q_D(const QQuickItem);
- return d->height;
-}
-
-void QQuickItem::setHeight(qreal h)
-{
- Q_D(QQuickItem);
- if (qIsNaN(h))
- return;
-
- d->heightValid = true;
- if (d->height == h)
- return;
-
- qreal oldHeight = d->height;
- d->height = h;
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), width(), oldHeight));
-}
-
-void QQuickItem::resetHeight()
-{
- Q_D(QQuickItem);
- d->heightValid = false;
- setImplicitHeight(implicitHeight());
-}
-
-void QQuickItemPrivate::implicitHeightChanged()
-{
- Q_Q(QQuickItem);
- emit q->implicitHeightChanged();
-}
-
-qreal QQuickItemPrivate::getImplicitHeight() const
-{
- return implicitHeight;
-}
-
-/*!
- Returns the height of the item that is implied by other properties that determine the content.
-*/
-qreal QQuickItem::implicitHeight() const
-{
- Q_D(const QQuickItem);
- return d->getImplicitHeight();
-}
-
-
-/*!
- Sets the implied height of the item to \a h.
- This is the height implied by other properties that determine the content.
-*/
-void QQuickItem::setImplicitHeight(qreal h)
-{
- Q_D(QQuickItem);
- bool changed = h != d->implicitHeight;
- d->implicitHeight = h;
- if (d->height == h || heightValid()) {
- if (changed)
- d->implicitHeightChanged();
- return;
- }
-
- qreal oldHeight = d->height;
- d->height = h;
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), width(), oldHeight));
-
- if (changed)
- d->implicitHeightChanged();
-}
-
-void QQuickItem::setImplicitSize(qreal w, qreal h)
-{
- Q_D(QQuickItem);
- bool wChanged = w != d->implicitWidth;
- bool hChanged = h != d->implicitHeight;
-
- d->implicitWidth = w;
- d->implicitHeight = h;
-
- bool wDone = false;
- bool hDone = false;
- if (d->width == w || widthValid()) {
- if (wChanged)
- d->implicitWidthChanged();
- wDone = true;
- }
- if (d->height == h || heightValid()) {
- if (hChanged)
- d->implicitHeightChanged();
- hDone = true;
- }
- if (wDone && hDone)
- return;
-
- qreal oldWidth = d->width;
- qreal oldHeight = d->height;
- if (!wDone)
- d->width = w;
- if (!hDone)
- d->height = h;
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), oldWidth, oldHeight));
-
- if (!wDone && wChanged)
- d->implicitWidthChanged();
- if (!hDone && hChanged)
- d->implicitHeightChanged();
-}
-
-/*!
- Returns whether the height property has been set explicitly.
-*/
-bool QQuickItem::heightValid() const
-{
- Q_D(const QQuickItem);
- return d->heightValid;
-}
-
-void QQuickItem::setSize(const QSizeF &size)
-{
- Q_D(QQuickItem);
- d->heightValid = true;
- d->widthValid = true;
-
- if (QSizeF(d->width, d->height) == size)
- return;
-
- qreal oldHeight = d->height;
- qreal oldWidth = d->width;
- d->height = size.height();
- d->width = size.width();
-
- d->dirty(QQuickItemPrivate::Size);
-
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), oldWidth, oldHeight));
-}
-
-bool QQuickItem::hasActiveFocus() const
-{
- Q_D(const QQuickItem);
- return d->activeFocus;
-}
-
-bool QQuickItem::hasFocus() const
-{
- Q_D(const QQuickItem);
- return d->focus;
-}
-
-void QQuickItem::setFocus(bool focus)
-{
- Q_D(QQuickItem);
- if (d->focus == focus)
- return;
-
- if (d->canvas) {
- // Need to find our nearest focus scope
- QQuickItem *scope = parentItem();
- while (scope && !scope->isFocusScope())
- scope = scope->parentItem();
- if (focus)
- QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
- else
- QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
- } else {
- d->focus = focus;
- emit focusChanged(focus);
- }
-}
-
-bool QQuickItem::isFocusScope() const
-{
- return flags() & ItemIsFocusScope;
-}
-
-QQuickItem *QQuickItem::scopedFocusItem() const
-{
- Q_D(const QQuickItem);
- if (!isFocusScope())
- return 0;
- else
- return d->subFocusItem;
-}
-
-
-Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
-{
- Q_D(const QQuickItem);
- return d->acceptedMouseButtons;
-}
-
-void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
-{
- Q_D(QQuickItem);
- d->acceptedMouseButtons = buttons;
-}
-
-bool QQuickItem::filtersChildMouseEvents() const
-{
- Q_D(const QQuickItem);
- return d->filtersChildMouseEvents;
-}
-
-void QQuickItem::setFiltersChildMouseEvents(bool filter)
-{
- Q_D(QQuickItem);
- d->filtersChildMouseEvents = filter;
-}
-
-bool QQuickItem::isUnderMouse() const
-{
- Q_D(const QQuickItem);
- if (!d->canvas)
- return false;
-
- QPoint cursorPos = QCursor::pos();
- if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos))))
- return true;
- return false;
-}
-
-bool QQuickItem::acceptHoverEvents() const
-{
- Q_D(const QQuickItem);
- return d->hoverEnabled;
-}
-
-void QQuickItem::setAcceptHoverEvents(bool enabled)
-{
- Q_D(QQuickItem);
- d->hoverEnabled = enabled;
-}
-
-void QQuickItem::grabMouse()
-{
- Q_D(QQuickItem);
- if (!d->canvas)
- return;
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
- if (canvasPriv->mouseGrabberItem == this)
- return;
-
- QQuickItem *oldGrabber = canvasPriv->mouseGrabberItem;
- canvasPriv->mouseGrabberItem = this;
- if (oldGrabber)
- oldGrabber->mouseUngrabEvent();
-}
-
-void QQuickItem::ungrabMouse()
-{
- Q_D(QQuickItem);
- if (!d->canvas)
- return;
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
- if (canvasPriv->mouseGrabberItem != this) {
- qWarning("QQuickItem::ungrabMouse(): Item is not the mouse grabber.");
- return;
- }
-
- canvasPriv->mouseGrabberItem = 0;
- mouseUngrabEvent();
-}
-
-bool QQuickItem::keepMouseGrab() const
-{
- Q_D(const QQuickItem);
- return d->keepMouse;
-}
-
-/*!
- The flag indicating whether the mouse should remain
- with this item is set to \a keep.
-
- This is useful for items that wish to grab and keep mouse
- interaction following a predefined gesture. For example,
- an item that is interested in horizontal mouse movement
- may set keepMouseGrab to true once a threshold has been
- exceeded. Once keepMouseGrab has been set to true, filtering
- items will not react to mouse events.
-
- If the item does not indicate that it wishes to retain mouse grab,
- a filtering item may steal the grab. For example, Flickable may attempt
- to steal a mouse grab if it detects that the user has begun to
- move the viewport.
-
- \sa keepMouseGrab()
- */
-void QQuickItem::setKeepMouseGrab(bool keep)
-{
- Q_D(QQuickItem);
- d->keepMouse = keep;
-}
-
-/*!
- Grabs the touch points specified by \a ids.
-
- These touch points will be owned by the item until
- they are released. Alternatively, the grab can be stolen
- by a filtering item like Flickable. Use setKeepTouchGrab()
- to prevent the grab from being stolen.
-
- \sa ungrabTouchPoints(), setKeepTouchGrab()
-*/
-void QQuickItem::grabTouchPoints(const QList<int> &ids)
-{
- Q_D(QQuickItem);
- if (!d->canvas)
- return;
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
-
- QSet<QQuickItem*> ungrab;
- for (int i = 0; i < ids.count(); ++i) {
- QQuickItem *oldGrabber = canvasPriv->itemForTouchPointId.value(ids.at(i));
- if (oldGrabber == this)
- return;
-
- canvasPriv->itemForTouchPointId[ids.at(i)] = this;
- if (oldGrabber)
- ungrab.insert(oldGrabber);
- }
- foreach (QQuickItem *oldGrabber, ungrab)
- oldGrabber->touchUngrabEvent();
-}
-
-/*!
- Ungrabs the touch points owned by this item.
-
- \sa grabTouchPoints()
-*/
-void QQuickItem::ungrabTouchPoints()
-{
- Q_D(QQuickItem);
- if (!d->canvas)
- return;
- QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
-
- QMutableHashIterator<int, QQuickItem*> i(canvasPriv->itemForTouchPointId);
- while (i.hasNext()) {
- i.next();
- if (i.value() == this)
- i.remove();
- }
- touchUngrabEvent();
-}
-
-/*!
- Returns a value indicating whether the touch points grabbed by this item
- should remain with this item exclusively.
-
- \sa setKeepTouchGrab(), keepMouseGrab()
-*/
-bool QQuickItem::keepTouchGrab() const
-{
- Q_D(const QQuickItem);
- return d->keepTouch;
-}
-
-/*!
- The flag indicating whether the touch points grabbed
- by this item should remain with this item is set to \a keep.
-
- This is useful for items that wish to grab and keep specific touch
- points following a predefined gesture. For example,
- an item that is interested in horizontal touch point movement
- may set setKeepTouchGrab to true once a threshold has been
- exceeded. Once setKeepTouchGrab has been set to true, filtering
- items will not react to the relevant touch points.
-
- If the item does not indicate that it wishes to retain touch point grab,
- a filtering item may steal the grab. For example, Flickable may attempt
- to steal a touch point grab if it detects that the user has begun to
- move the viewport.
-
- \sa keepTouchGrab(), setKeepMouseGrab()
- */
-void QQuickItem::setKeepTouchGrab(bool keep)
-{
- Q_D(QQuickItem);
- d->keepTouch = keep;
-}
-
-/*!
- \qmlmethod object QtQuick2::Item::mapFromItem(Item item, real x, real y)
-
- Maps the point (\a x, \a y), which is in \a item's coordinate system, to
- this item's coordinate system, and returns an object with \c x and \c y
- properties matching the mapped coordinate.
-
- If \a item is a \c null value, this maps the point from the coordinate
- system of the root QML view.
-*/
-/*!
- \qmlmethod object QtQuick2::Item::mapToItem(Item item, real x, real y)
-
- Maps the point (\a x, \a y), which is in this item's coordinate system, to
- \a item's coordinate system, and returns an object with \c x and \c y
- properties matching the mapped coordinate.
-
- If \a item is a \c null value, this maps \a x and \a y to the coordinate
- system of the root QML view.
-*/
-QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
-{
- QPointF p = mapToScene(point);
- if (item)
- p = item->mapFromScene(p);
- return p;
-}
-
-QPointF QQuickItem::mapToScene(const QPointF &point) const
-{
- Q_D(const QQuickItem);
- return d->itemToCanvasTransform().map(point);
-}
-
-QRectF QQuickItem::mapRectToItem(const QQuickItem *item, const QRectF &rect) const
-{
- Q_D(const QQuickItem);
- QTransform t = d->itemToCanvasTransform();
- if (item)
- t *= QQuickItemPrivate::get(item)->canvasToItemTransform();
- return t.mapRect(rect);
-}
-
-QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
-{
- Q_D(const QQuickItem);
- return d->itemToCanvasTransform().mapRect(rect);
-}
-
-QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
-{
- QPointF p = item?item->mapToScene(point):point;
- return mapFromScene(p);
-}
-
-QPointF QQuickItem::mapFromScene(const QPointF &point) const
-{
- Q_D(const QQuickItem);
- return d->canvasToItemTransform().map(point);
-}
-
-QRectF QQuickItem::mapRectFromItem(const QQuickItem *item, const QRectF &rect) const
-{
- Q_D(const QQuickItem);
- QTransform t = item?QQuickItemPrivate::get(item)->itemToCanvasTransform():QTransform();
- t *= d->canvasToItemTransform();
- return t.mapRect(rect);
-}
-
-QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
-{
- Q_D(const QQuickItem);
- return d->canvasToItemTransform().mapRect(rect);
-}
-
-
-/*!
- \qmlmethod QtQuick2::Item::forceActiveFocus()
-
- Forces active focus on the item.
-
- This method sets focus on the item and makes sure that all the focus scopes
- higher in the object hierarchy are also given the focus.
-*/
-
-/*!
- Forces active focus on the item.
-
- This method sets focus on the item and makes sure that all the focus scopes
- higher in the object hierarchy are also given the focus.
-*/
-
-/*!
- \qmlmethod QtQuick2::Item::childAt(real x, real y)
-
- Returns the visible child item at point (\a x, \a y), which is in this
- item's coordinate system, or \c null if there is no such item.
-*/
-
-/*!
- Returns the visible child item at point (\a x, \a y), which is in this
- item's coordinate system, or 0 if there is no such item.
-*/
-
-/*!
- \qmlproperty list<State> QtQuick2::Item::states
- This property holds a list of states defined by the item.
-
- \qml
- Item {
- states: [
- State {
- // ...
- },
- State {
- // ...
- }
- // ...
- ]
- }
- \endqml
-
- \sa {qmlstate}{States}
-*/
-/*!
- \qmlproperty list<Transition> QtQuick2::Item::transitions
- This property holds a list of transitions defined by the item.
-
- \qml
- Item {
- transitions: [
- Transition {
- // ...
- },
- Transition {
- // ...
- }
- // ...
- ]
- }
- \endqml
-
- \sa {QML Animation and Transitions}{Transitions}
-*/
-/*
- \qmlproperty list<Filter> QtQuick2::Item::filter
- This property holds a list of graphical filters to be applied to the item.
-
- \l {Filter}{Filters} include things like \l {Blur}{blurring}
- the item, or giving it a \l Reflection. Some
- filters may not be available on all canvases; if a filter is not
- available on a certain canvas, it will simply not be applied for
- that canvas (but the QML will still be considered valid).
-
- \qml
- Item {
- filter: [
- Blur {
- // ...
- },
- Reflection {
- // ...
- }
- // ...
- ]
- }
- \endqml
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Item::clip
- This property holds whether clipping is enabled. The default clip value is \c false.
-
- If clipping is enabled, an item will clip its own painting, as well
- as the painting of its children, to its bounding rectangle.
-
- Non-rectangular clipping regions are not supported for performance reasons.
-*/
-
-/*!
- \property QQuickItem::clip
- This property holds whether clipping is enabled. The default clip value is \c false.
-
- If clipping is enabled, an item will clip its own painting, as well
- as the painting of its children, to its bounding rectangle. If you set
- clipping during an item's paint operation, remember to re-set it to
- prevent clipping the rest of your scene.
-
- Non-rectangular clipping regions are not supported for performance reasons.
-*/
-
-/*!
- \qmlproperty string QtQuick2::Item::state
-
- This property holds the name of the current state of the item.
-
- This property is often used in scripts to change between states. For
- example:
-
- \js
- function toggle() {
- if (button.state == 'On')
- button.state = 'Off';
- else
- button.state = 'On';
- }
- \endjs
-
- If the item is in its base state (i.e. no explicit state has been
- set), \c state will be a blank string. Likewise, you can return an
- item to its base state by setting its current state to \c ''.
-
- \sa {qmlstates}{States}
-*/
-
-/*!
- \qmlproperty list<Transform> QtQuick2::Item::transform
- This property holds the list of transformations to apply.
-
- For more information see \l Transform.
-*/
-
-/*!
- \enum QQuickItem::TransformOrigin
-
- Controls the point about which simple transforms like scale apply.
-
- \value TopLeft The top-left corner of the item.
- \value Top The center point of the top of the item.
- \value TopRight The top-right corner of the item.
- \value Left The left most point of the vertical middle.
- \value Center The center of the item.
- \value Right The right most point of the vertical middle.
- \value BottomLeft The bottom-left corner of the item.
- \value Bottom The center point of the bottom of the item.
- \value BottomRight The bottom-right corner of the item.
-*/
-
-
-/*!
- \qmlproperty bool QtQuick2::Item::activeFocus
-
- This property indicates whether the item has active focus.
-
- An item with active focus will receive keyboard input,
- or is a FocusScope ancestor of the item that will receive keyboard input.
-
- Usually, activeFocus is gained by setting focus on an item and its enclosing
- FocusScopes. In the following example \c input will have activeFocus.
- \qml
- Rectangle {
- FocusScope {
- focus: true
- TextInput {
- id: input
- focus: true
- }
- }
- }
- \endqml
-
- \sa focus, {qmlfocus}{Keyboard Focus}
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Item::focus
- This property indicates whether the item has focus within the enclosing focus scope. If true, this item
- will gain active focus when the enclosing focus scope gains active focus.
- In the following example, \c input will be given active focus when \c scope gains active focus.
- \qml
- Rectangle {
- FocusScope {
- id: scope
- TextInput {
- id: input
- focus: true
- }
- }
- }
- \endqml
-
- For the purposes of this property, the scene as a whole is assumed to act like a focus scope.
- On a practical level, that means the following QML will give active focus to \c input on startup.
-
- \qml
- Rectangle {
- TextInput {
- id: input
- focus: true
- }
- }
- \endqml
-
- \sa activeFocus, {qmlfocus}{Keyboard Focus}
-*/
-
-
-/*!
- \property QQuickItem::anchors
- \internal
-*/
-
-/*!
- \property QQuickItem::left
- \internal
-*/
-
-/*!
- \property QQuickItem::right
- \internal
-*/
-
-/*!
- \property QQuickItem::horizontalCenter
- \internal
-*/
-
-/*!
- \property QQuickItem::top
- \internal
-*/
-
-/*!
- \property QQuickItem::bottom
- \internal
-*/
-
-/*!
- \property QQuickItem::verticalCenter
- \internal
-*/
-
-/*!
- \property QQuickItem::focus
- \internal
-*/
-
-/*!
- \property QQuickItem::transform
- \internal
-*/
-
-/*!
- \property QQuickItem::transformOrigin
- \internal
-*/
-
-/*!
- \property QQuickItem::activeFocus
- \internal
-*/
-
-/*!
- \property QQuickItem::baseline
- \internal
-*/
-
-/*!
- \property QQuickItem::data
- \internal
-*/
-
-/*!
- \property QQuickItem::resources
- \internal
-*/
-
-/*!
- \property QQuickItem::state
- \internal
-*/
-
-/*!
- \property QQuickItem::states
- \internal
-*/
-
-/*!
- \property QQuickItem::transformOriginPoint
- \internal
-*/
-
-/*!
- \property QQuickItem::transitions
- \internal
-*/
-
-bool QQuickItem::event(QEvent *ev)
-{
-#if 0
- if (ev->type() == QEvent::PolishRequest) {
- Q_D(QQuickItem);
- d->polishScheduled = false;
- updatePolish();
- return true;
- } else {
- return QObject::event(ev);
- }
-#endif
- if (ev->type() == QEvent::InputMethodQuery) {
- QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
- Qt::InputMethodQueries queries = query->queries();
- for (uint i = 0; i < 32; ++i) {
- Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
- if (q) {
- QVariant v = inputMethodQuery(q);
- query->setValue(q, v);
- }
- }
- query->accept();
- return true;
- } else if (ev->type() == QEvent::InputMethod) {
- inputMethodEvent(static_cast<QInputMethodEvent *>(ev));
- return true;
- }
- return QObject::event(ev);
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, QQuickItem *item)
-{
- if (!item) {
- debug << "QQuickItem(0)";
- return debug;
- }
-
- debug << item->metaObject()->className() << "(this =" << ((void*)item)
- << ", name=" << item->objectName()
- << ", parent =" << ((void*)item->parentItem())
- << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height()))
- << ", z =" << item->z() << ')';
- return debug;
-}
-#endif
-
-qint64 QQuickItemPrivate::consistentTime = -1;
-void QQuickItemPrivate::setConsistentTime(qint64 t)
-{
- consistentTime = t;
-}
-
-class QElapsedTimerConsistentTimeHack
-{
-public:
- void start() {
- t1 = QQuickItemPrivate::consistentTime;
- t2 = 0;
- }
- qint64 elapsed() {
- return QQuickItemPrivate::consistentTime - t1;
- }
- qint64 restart() {
- qint64 val = QQuickItemPrivate::consistentTime - t1;
- t1 = QQuickItemPrivate::consistentTime;
- t2 = 0;
- return val;
- }
-
-private:
- qint64 t1;
- qint64 t2;
-};
-
-void QQuickItemPrivate::start(QElapsedTimer &t)
-{
- if (QQuickItemPrivate::consistentTime == -1)
- t.start();
- else
- ((QElapsedTimerConsistentTimeHack*)&t)->start();
-}
-
-qint64 QQuickItemPrivate::elapsed(QElapsedTimer &t)
-{
- if (QQuickItemPrivate::consistentTime == -1)
- return t.elapsed();
- else
- return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed();
-}
-
-qint64 QQuickItemPrivate::restart(QElapsedTimer &t)
-{
- if (QQuickItemPrivate::consistentTime == -1)
- return t.restart();
- else
- return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
-}
-
-/*!
- \fn bool QQuickItem::isTextureProvider() const
-
- Returns true if this item is a texture provider. The default
- implementation returns false.
-
- This function can be called from any thread.
- */
-
-/*!
- \fn QSGTextureProvider *QQuickItem::textureProvider() const
-
- Returns the texture provider for an item. The default implementation
- returns 0.
-
- This function may only be called on the rendering thread.
- */
-
-QT_END_NAMESPACE
-
-#include <moc_qquickitem.cpp>
diff --git a/src/declarative/items/qquickitem.h b/src/declarative/items/qquickitem.h
deleted file mode 100644
index a3baecb9ea..0000000000
--- a/src/declarative/items/qquickitem.h
+++ /dev/null
@@ -1,421 +0,0 @@
-// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKITEM_H
-#define QQUICKITEM_H
-
-#include <QtDeclarative/qdeclarative.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-
-#include <QtCore/QObject>
-#include <QtCore/QList>
-#include <QtGui/qevent.h>
-#include <QtGui/qfont.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QQuickTransformPrivate;
-class QQuickTransform : public QObject
-{
- Q_OBJECT
-public:
- QQuickTransform(QObject *parent = 0);
- ~QQuickTransform();
-
- void appendToItem(QQuickItem *);
- void prependToItem(QQuickItem *);
-
- virtual void applyTo(QMatrix4x4 *matrix) const = 0;
-
-protected Q_SLOTS:
- void update();
-
-protected:
- QQuickTransform(QQuickTransformPrivate &dd, QObject *parent);
-
-private:
- Q_DECLARE_PRIVATE(QQuickTransform)
-};
-
-class QDeclarativeV8Function;
-class QDeclarativeState;
-class QQuickAnchorLine;
-class QDeclarativeTransition;
-class QQuickKeyEvent;
-class QQuickAnchors;
-class QQuickItemPrivate;
-class QQuickCanvas;
-class QSGEngine;
-class QTouchEvent;
-class QSGNode;
-class QSGTransformNode;
-class QSGTextureProvider;
-
-class Q_DECLARATIVE_EXPORT QQuickItem : public QObject, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QDeclarativeParserStatus)
-
- Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem NOTIFY parentChanged DESIGNABLE false FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QObject> resources READ resources DESIGNABLE false)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
-
- Q_PROPERTY(QPointF pos READ pos FINAL)
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
- Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
- Q_PROPERTY(qreal z READ z WRITE setZ NOTIFY zChanged FINAL)
- Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
- Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
-
- Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
-
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QDeclarativeState> states READ states DESIGNABLE false)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitions DESIGNABLE false)
- Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
- Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine left READ left CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine right READ right CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine top READ top CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine bottom READ bottom CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
- Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine baseline READ baseline CONSTANT FINAL)
- Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
-
- Q_PROPERTY(bool clip READ clip WRITE setClip NOTIFY clipChanged)
-
- Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
- Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL)
-
- Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
- Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
- Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged)
- Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint) // XXX todo - notify?
- Q_PROPERTY(QDeclarativeListProperty<QQuickTransform> transform READ transform DESIGNABLE false FINAL)
-
- Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged)
- Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged)
- Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged)
-
- Q_ENUMS(TransformOrigin)
- Q_CLASSINFO("DefaultProperty", "data")
-
-public:
- enum Flag {
- ItemClipsChildrenToShape = 0x01,
- ItemAcceptsInputMethod = 0x02,
- ItemIsFocusScope = 0x04,
- ItemHasContents = 0x08,
- ItemAcceptsDrops = 0x10
- // Remember to increment the size of QQuickItemPrivate::flags
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum ItemChange {
- ItemChildAddedChange, // value.item
- ItemChildRemovedChange, // value.item
- ItemSceneChange, // value.canvas
- ItemVisibleHasChanged, // value.realValue
- ItemParentHasChanged, // value.item
- ItemOpacityHasChanged, // value.realValue
- ItemActiveFocusHasChanged, // value.boolValue
- ItemRotationHasChanged // value.realValue
- };
-
- union ItemChangeData {
- ItemChangeData(QQuickItem *v) : item(v) {}
- ItemChangeData(QQuickCanvas *v) : canvas(v) {}
- ItemChangeData(qreal v) : realValue(v) {}
- ItemChangeData(bool v) : boolValue(v) {}
-
- QQuickItem *item;
- QQuickCanvas *canvas;
- qreal realValue;
- bool boolValue;
- };
-
- enum TransformOrigin {
- TopLeft, Top, TopRight,
- Left, Center, Right,
- BottomLeft, Bottom, BottomRight
- };
-
- QQuickItem(QQuickItem *parent = 0);
- virtual ~QQuickItem();
-
- QSGEngine *sceneGraphEngine() const;
-
- QQuickCanvas *canvas() const;
- QQuickItem *parentItem() const;
- void setParentItem(QQuickItem *parent);
- void stackBefore(const QQuickItem *);
- void stackAfter(const QQuickItem *);
-
- QRectF childrenRect();
- QList<QQuickItem *> childItems() const;
-
- bool clip() const;
- void setClip(bool);
-
- QString state() const;
- void setState(const QString &);
-
- qreal baselineOffset() const;
- void setBaselineOffset(qreal);
-
- QDeclarativeListProperty<QQuickTransform> transform();
-
- qreal x() const;
- qreal y() const;
- QPointF pos() const;
- void setX(qreal);
- void setY(qreal);
- void setPos(const QPointF &);
-
- qreal width() const;
- void setWidth(qreal);
- void resetWidth();
- qreal implicitWidth() const;
-
- qreal height() const;
- void setHeight(qreal);
- void resetHeight();
- qreal implicitHeight() const;
-
- void setSize(const QSizeF &size);
-
- TransformOrigin transformOrigin() const;
- void setTransformOrigin(TransformOrigin);
- QPointF transformOriginPoint() const;
- void setTransformOriginPoint(const QPointF &);
-
- qreal z() const;
- void setZ(qreal);
-
- qreal rotation() const;
- void setRotation(qreal);
- qreal scale() const;
- void setScale(qreal);
-
- qreal opacity() const;
- void setOpacity(qreal);
-
- bool isVisible() const;
- void setVisible(bool);
-
- bool isEnabled() const;
- void setEnabled(bool);
-
- bool smooth() const;
- void setSmooth(bool);
-
- Flags flags() const;
- void setFlag(Flag flag, bool enabled = true);
- void setFlags(Flags flags);
-
- virtual QRectF boundingRect() const;
-
- bool hasActiveFocus() const;
- bool hasFocus() const;
- void setFocus(bool);
- bool isFocusScope() const;
- QQuickItem *scopedFocusItem() const;
-
- Qt::MouseButtons acceptedMouseButtons() const;
- void setAcceptedMouseButtons(Qt::MouseButtons buttons);
- bool acceptHoverEvents() const;
- void setAcceptHoverEvents(bool enabled);
-
- bool isUnderMouse() const;
- void grabMouse();
- void ungrabMouse();
- bool keepMouseGrab() const;
- void setKeepMouseGrab(bool);
- bool filtersChildMouseEvents() const;
- void setFiltersChildMouseEvents(bool filter);
-
- void grabTouchPoints(const QList<int> &ids);
- void ungrabTouchPoints();
- bool keepTouchGrab() const;
- void setKeepTouchGrab(bool);
-
- QTransform itemTransform(QQuickItem *, bool *) const;
- QPointF mapToItem(const QQuickItem *item, const QPointF &point) const;
- QPointF mapToScene(const QPointF &point) const;
- QRectF mapRectToItem(const QQuickItem *item, const QRectF &rect) const;
- QRectF mapRectToScene(const QRectF &rect) const;
- QPointF mapFromItem(const QQuickItem *item, const QPointF &point) const;
- QPointF mapFromScene(const QPointF &point) const;
- QRectF mapRectFromItem(const QQuickItem *item, const QRectF &rect) const;
- QRectF mapRectFromScene(const QRectF &rect) const;
-
- void polish();
-
- Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
- Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
- Q_INVOKABLE void forceActiveFocus();
- Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const;
-
- Qt::InputMethodHints inputMethodHints() const;
- void setInputMethodHints(Qt::InputMethodHints hints);
- virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
-
- struct UpdatePaintNodeData {
- QSGTransformNode *transformNode;
- private:
- friend class QQuickCanvasPrivate;
- UpdatePaintNodeData();
- };
-
- virtual bool isTextureProvider() const { return false; }
- virtual QSGTextureProvider *textureProvider() const { return 0; }
-
-public Q_SLOTS:
- void update();
- void updateMicroFocus();
-
-Q_SIGNALS:
- void childrenRectChanged(const QRectF &);
- void baselineOffsetChanged(qreal);
- void stateChanged(const QString &);
- void focusChanged(bool);
- void activeFocusChanged(bool);
- void parentChanged(QQuickItem *);
- void transformOriginChanged(TransformOrigin);
- void smoothChanged(bool);
- void clipChanged(bool);
-
- // XXX todo
- void childrenChanged();
- void opacityChanged();
- void enabledChanged();
- void visibleChanged();
- void rotationChanged();
- void scaleChanged();
-
- void xChanged();
- void yChanged();
- void widthChanged();
- void heightChanged();
- void zChanged();
- void implicitWidthChanged();
- void implicitHeightChanged();
-
-protected:
- virtual bool event(QEvent *);
-
- bool isComponentComplete() const;
- virtual void itemChange(ItemChange, const ItemChangeData &);
-
- void setImplicitWidth(qreal);
- bool widthValid() const; // ### better name?
- void setImplicitHeight(qreal);
- bool heightValid() const; // ### better name?
- void setImplicitSize(qreal, qreal);
-
- virtual void classBegin();
- virtual void componentComplete();
-
- virtual void keyPressEvent(QKeyEvent *event);
- virtual void keyReleaseEvent(QKeyEvent *event);
- virtual void inputMethodEvent(QInputMethodEvent *);
- virtual void focusInEvent(QFocusEvent *);
- virtual void focusOutEvent(QFocusEvent *);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void mouseDoubleClickEvent(QMouseEvent *event);
- virtual void mouseUngrabEvent(); // XXX todo - params?
- virtual void touchUngrabEvent();
- virtual void wheelEvent(QWheelEvent *event);
- virtual void touchEvent(QTouchEvent *event);
- virtual void hoverEnterEvent(QHoverEvent *event);
- virtual void hoverMoveEvent(QHoverEvent *event);
- virtual void hoverLeaveEvent(QHoverEvent *event);
- virtual void dragEnterEvent(QDragEnterEvent *);
- virtual void dragMoveEvent(QDragMoveEvent *);
- virtual void dragLeaveEvent(QDragLeaveEvent *);
- virtual void dropEvent(QDropEvent *);
- virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
- virtual void windowDeactivateEvent();
-
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
-
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual void updatePolish();
-
-protected:
- QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent = 0);
-
-private:
- friend class QQuickCanvas;
- friend class QQuickCanvasPrivate;
- friend class QSGRenderer;
- Q_DISABLE_COPY(QQuickItem)
- Q_DECLARE_PRIVATE(QQuickItem)
-};
-
-// XXX todo
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItem::Flags)
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, QQuickItem *item);
-#endif
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickItem)
-QML_DECLARE_TYPE(QQuickTransform)
-
-QT_END_HEADER
-
-#endif // QQUICKITEM_H
diff --git a/src/declarative/items/qquickitem_p.h b/src/declarative/items/qquickitem_p.h
deleted file mode 100644
index 08ae7fac9b..0000000000
--- a/src/declarative/items/qquickitem_p.h
+++ /dev/null
@@ -1,752 +0,0 @@
-// Commit: 5c783d0a9a912816813945387903857a314040b5
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKITEM_P_H
-#define QQUICKITEM_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qquickitem.h"
-
-#include "qquickanchors_p.h"
-#include "qquickanchors_p_p.h"
-#include "qquickitemchangelistener_p.h"
-
-#include "qquickcanvas_p.h"
-
-#include <qsgnode.h>
-#include "qquickclipnode_p.h"
-
-#include <private/qpodvector_p.h>
-#include <private/qdeclarativestate_p.h>
-#include <private/qdeclarativenullablevalue_p_p.h>
-#include <private/qdeclarativenotifier_p.h>
-#include <private/qdeclarativeglobal_p.h>
-
-#include <qdeclarative.h>
-#include <qdeclarativecontext.h>
-
-#include <QtCore/qlist.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qelapsedtimer.h>
-
-QT_BEGIN_NAMESPACE
-
-class QNetworkReply;
-class QQuickItemKeyFilter;
-class QQuickLayoutMirroringAttached;
-
-class QQuickContents : public QQuickItemChangeListener
-{
-public:
- QQuickContents(QQuickItem *item);
- ~QQuickContents();
-
- QRectF rectF() const { return QRectF(m_x, m_y, m_width, m_height); }
-
- inline void calcGeometry(QQuickItem *changed = 0);
- void complete();
-
-protected:
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- void itemDestroyed(QQuickItem *item);
- void itemChildAdded(QQuickItem *, QQuickItem *);
- void itemChildRemoved(QQuickItem *, QQuickItem *);
- //void itemVisibilityChanged(QQuickItem *item)
-
-private:
- bool calcHeight(QQuickItem *changed = 0);
- bool calcWidth(QQuickItem *changed = 0);
- void updateRect();
-
- QQuickItem *m_item;
- qreal m_x;
- qreal m_y;
- qreal m_width;
- qreal m_height;
-};
-
-void QQuickContents::calcGeometry(QQuickItem *changed)
-{
- bool wChanged = calcWidth(changed);
- bool hChanged = calcHeight(changed);
- if (wChanged || hChanged)
- updateRect();
-}
-
-class QQuickTransformPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQuickTransform);
-public:
- static QQuickTransformPrivate* get(QQuickTransform *transform) { return transform->d_func(); }
-
- QQuickTransformPrivate();
-
- QList<QQuickItem *> items;
-};
-
-class Q_DECLARATIVE_EXPORT QQuickItemPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQuickItem)
-
-public:
- static QQuickItemPrivate* get(QQuickItem *item) { return item->d_func(); }
- static const QQuickItemPrivate* get(const QQuickItem *item) { return item->d_func(); }
-
- QQuickItemPrivate();
- ~QQuickItemPrivate();
- void init(QQuickItem *parent);
-
- QDeclarativeListProperty<QObject> data();
- QDeclarativeListProperty<QObject> resources();
- QDeclarativeListProperty<QQuickItem> children();
-
- QDeclarativeListProperty<QDeclarativeState> states();
- QDeclarativeListProperty<QDeclarativeTransition> transitions();
-
- QString state() const;
- void setState(const QString &);
-
- QQuickAnchorLine left() const;
- QQuickAnchorLine right() const;
- QQuickAnchorLine horizontalCenter() const;
- QQuickAnchorLine top() const;
- QQuickAnchorLine bottom() const;
- QQuickAnchorLine verticalCenter() const;
- QQuickAnchorLine baseline() const;
-
- // data property
- static void data_append(QDeclarativeListProperty<QObject> *, QObject *);
- static int data_count(QDeclarativeListProperty<QObject> *);
- static QObject *data_at(QDeclarativeListProperty<QObject> *, int);
- static void data_clear(QDeclarativeListProperty<QObject> *);
-
- // resources property
- static QObject *resources_at(QDeclarativeListProperty<QObject> *, int);
- static void resources_append(QDeclarativeListProperty<QObject> *, QObject *);
- static int resources_count(QDeclarativeListProperty<QObject> *);
- static void resources_clear(QDeclarativeListProperty<QObject> *);
-
- // children property
- static void children_append(QDeclarativeListProperty<QQuickItem> *, QQuickItem *);
- static int children_count(QDeclarativeListProperty<QQuickItem> *);
- static QQuickItem *children_at(QDeclarativeListProperty<QQuickItem> *, int);
- static void children_clear(QDeclarativeListProperty<QQuickItem> *);
-
- // transform property
- static int transform_count(QDeclarativeListProperty<QQuickTransform> *list);
- static void transform_append(QDeclarativeListProperty<QQuickTransform> *list, QQuickTransform *);
- static QQuickTransform *transform_at(QDeclarativeListProperty<QQuickTransform> *list, int);
- static void transform_clear(QDeclarativeListProperty<QQuickTransform> *list);
-
- QQuickAnchors *anchors() const;
- mutable QQuickAnchors *_anchors;
- QQuickContents *_contents;
-
- QDeclarativeNullableValue<qreal> baselineOffset;
-
- struct AnchorLines {
- AnchorLines(QQuickItem *);
- QQuickAnchorLine left;
- QQuickAnchorLine right;
- QQuickAnchorLine hCenter;
- QQuickAnchorLine top;
- QQuickAnchorLine bottom;
- QQuickAnchorLine vCenter;
- QQuickAnchorLine baseline;
- };
- mutable AnchorLines *_anchorLines;
- AnchorLines *anchorLines() const;
-
- enum ChangeType {
- Geometry = 0x01,
- SiblingOrder = 0x02,
- Visibility = 0x04,
- Opacity = 0x08,
- Destroyed = 0x10,
- Parent = 0x20,
- Children = 0x40,
- Rotation = 0x80,
- };
-
- Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
-
- enum GeometryChangeType {
- NoChange = 0,
- XChange = 0x01,
- YChange = 0x02,
- WidthChange = 0x04,
- HeightChange = 0x08,
- SizeChange = WidthChange | HeightChange,
- GeometryChange = XChange | YChange | SizeChange
- };
-
- Q_DECLARE_FLAGS(GeometryChangeTypes, GeometryChangeType)
-
- struct ChangeListener {
- ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::ChangeTypes t) : listener(l), types(t), gTypes(GeometryChange) {}
- ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::GeometryChangeTypes gt) : listener(l), types(Geometry), gTypes(gt) {}
- QQuickItemChangeListener *listener;
- QQuickItemPrivate::ChangeTypes types;
- QQuickItemPrivate::GeometryChangeTypes gTypes; //NOTE: not used for ==
- bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; }
- };
-
- void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types) {
- changeListeners.append(ChangeListener(listener, types));
- }
- void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types);
- void updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types);
- void updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types);
- QPODVector<ChangeListener,4> changeListeners;
-
- QDeclarativeStateGroup *_states();
- QDeclarativeStateGroup *_stateGroup;
-
- QQuickItem::TransformOrigin origin:5;
- quint32 flags:5;
- bool widthValid:1;
- bool heightValid:1;
- bool componentComplete:1;
- bool keepMouse:1;
- bool keepTouch:1;
- bool hoverEnabled:1;
- bool smooth:1;
- bool focus:1;
- bool activeFocus:1;
- bool notifiedFocus:1;
- bool notifiedActiveFocus:1;
- bool filtersChildMouseEvents:1;
- bool explicitVisible:1;
- bool effectiveVisible:1;
- bool explicitEnable:1;
- bool effectiveEnable:1;
- bool polishScheduled:1;
- bool inheritedLayoutMirror:1;
- bool effectiveLayoutMirror:1;
- bool isMirrorImplicit:1;
- bool inheritMirrorFromParent:1;
- bool inheritMirrorFromItem:1;
- bool childrenDoNotOverlap:1;
-
- QQuickCanvas *canvas;
- QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QQuickCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
-
- QQuickItem *parentItem;
- QList<QQuickItem *> childItems;
- mutable QList<QQuickItem *> *sortedChildItems;
- QList<QQuickItem *> paintOrderChildItems() const;
- void addChild(QQuickItem *);
- void removeChild(QQuickItem *);
- void siblingOrderChanged();
-
- inline void markSortedChildrenDirty(QQuickItem *child) {
- // If sortedChildItems == &childItems then all in childItems have z == 0
- // and we don't need to invalidate if the changed item also has z == 0.
- if (child->z() != 0. || sortedChildItems != &childItems) {
- if (sortedChildItems != &childItems)
- delete sortedChildItems;
- sortedChildItems = 0;
- }
- }
-
- class InitializationState {
- public:
- QQuickItem *getFocusScope(QQuickItem *item);
- void clear();
- void clear(QQuickItem *focusScope);
- private:
- QQuickItem *focusScope;
- };
- void initCanvas(InitializationState *, QQuickCanvas *);
-
- QQuickItem *subFocusItem;
-
- QTransform canvasToItemTransform() const;
- QTransform itemToCanvasTransform() const;
- void itemToParentTransform(QTransform &) const;
-
- qreal x;
- qreal y;
- qreal width;
- qreal height;
- qreal implicitWidth;
- qreal implicitHeight;
-
- qreal z;
- qreal scale;
- qreal rotation;
- qreal opacity;
-
- QQuickLayoutMirroringAttached* attachedLayoutDirection;
-
- Qt::MouseButtons acceptedMouseButtons;
- Qt::InputMethodHints imHints;
-
- QPointF transformOriginPoint;
-
- virtual qreal getImplicitWidth() const;
- virtual qreal getImplicitHeight() const;
- virtual void implicitWidthChanged();
- virtual void implicitHeightChanged();
-
- void resolveLayoutMirror();
- void setImplicitLayoutMirror(bool mirror, bool inherit);
- void setLayoutMirror(bool mirror);
- bool isMirrored() const {
- return effectiveLayoutMirror;
- }
-
- void emitChildrenRectChanged(const QRectF &rect) {
- Q_Q(QQuickItem);
- emit q->childrenRectChanged(rect);
- }
-
- QPointF computeTransformOrigin() const;
- QList<QQuickTransform *> transforms;
- virtual void transformChanged();
-
- QQuickItemKeyFilter *keyHandler;
- void deliverKeyEvent(QKeyEvent *);
- void deliverInputMethodEvent(QInputMethodEvent *);
- void deliverFocusEvent(QFocusEvent *);
- void deliverMouseEvent(QMouseEvent *);
- void deliverWheelEvent(QWheelEvent *);
- void deliverTouchEvent(QTouchEvent *);
- void deliverHoverEvent(QHoverEvent *);
- void deliverDragEvent(QEvent *);
-
- bool calcEffectiveVisible() const;
- void setEffectiveVisibleRecur(bool);
- bool calcEffectiveEnable() const;
- void setEffectiveEnableRecur(bool);
-
- // XXX todo
- enum DirtyType {
- TransformOrigin = 0x00000001,
- Transform = 0x00000002,
- BasicTransform = 0x00000004,
- Position = 0x00000008,
- Size = 0x00000010,
-
- ZValue = 0x00000020,
- Content = 0x00000040,
- Smooth = 0x00000080,
- OpacityValue = 0x00000100,
- ChildrenChanged = 0x00000200,
- ChildrenStackingChanged = 0x00000400,
- ParentChanged = 0x00000800,
-
- Clip = 0x00001000,
- Canvas = 0x00002000,
-
- EffectReference = 0x00008000,
- Visible = 0x00010000,
- HideReference = 0x00020000,
- // When you add an attribute here, don't forget to update
- // dirtyToString()
-
- TransformUpdateMask = TransformOrigin | Transform | BasicTransform | Position | Size | Canvas,
- ComplexTransformUpdateMask = Transform | Canvas,
- ContentUpdateMask = Size | Content | Smooth | Canvas,
- ChildrenUpdateMask = ChildrenChanged | ChildrenStackingChanged | EffectReference | Canvas,
-
- };
- quint32 dirtyAttributes;
- QString dirtyToString() const;
- void dirty(DirtyType);
- void addToDirtyList();
- void removeFromDirtyList();
- QQuickItem *nextDirtyItem;
- QQuickItem**prevDirtyItem;
-
- inline QSGTransformNode *itemNode();
- inline QSGNode *childContainerNode();
-
- /*
- QSGNode order is:
- - itemNode
- - (opacityNode)
- - (clipNode)
- - (effectNode)
- - groupNode
- */
-
- QSGTransformNode *itemNodeInstance;
- QSGOpacityNode *opacityNode;
- QQuickDefaultClipNode *clipNode;
- QSGRootNode *rootNode;
- QSGNode *groupNode;
- QSGNode *paintNode;
- QSGNode *beforePaintNode;
-
- virtual QSGTransformNode *createTransformNode();
-
- // A reference from an effect item means that this item is used by the effect, so
- // it should insert a root node.
- void refFromEffectItem(bool hide);
- void derefFromEffectItem(bool unhide);
- int effectRefCount;
- int hideRefCount;
-
- void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &);
-
- virtual void mirrorChange() {}
-
- static qint64 consistentTime;
- static void setConsistentTime(qint64 t);
- static void start(QElapsedTimer &);
- static qint64 elapsed(QElapsedTimer &);
- static qint64 restart(QElapsedTimer &);
-};
-
-/*
- Key filters can be installed on a QQuickItem, but not removed. Currently they
- are only used by attached objects (which are only destroyed on Item
- destruction), so this isn't a problem. If in future this becomes any form
- of public API, they will have to support removal too.
-*/
-class QQuickItemKeyFilter
-{
-public:
- QQuickItemKeyFilter(QQuickItem * = 0);
- virtual ~QQuickItemKeyFilter();
-
- virtual void keyPressed(QKeyEvent *event, bool post);
- virtual void keyReleased(QKeyEvent *event, bool post);
- virtual void inputMethodEvent(QInputMethodEvent *event, bool post);
- virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
- virtual void componentComplete();
-
- bool m_processPost;
-
-private:
- QQuickItemKeyFilter *m_next;
-};
-
-class QQuickKeyNavigationAttachedPrivate : public QObjectPrivate
-{
-public:
- QQuickKeyNavigationAttachedPrivate()
- : QObjectPrivate(),
- left(0), right(0), up(0), down(0), tab(0), backtab(0),
- leftSet(false), rightSet(false), upSet(false), downSet(false),
- tabSet(false), backtabSet(false) {}
-
- QQuickItem *left;
- QQuickItem *right;
- QQuickItem *up;
- QQuickItem *down;
- QQuickItem *tab;
- QQuickItem *backtab;
- bool leftSet : 1;
- bool rightSet : 1;
- bool upSet : 1;
- bool downSet : 1;
- bool tabSet : 1;
- bool backtabSet : 1;
-};
-
-class QQuickKeyNavigationAttached : public QObject, public QQuickItemKeyFilter
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickKeyNavigationAttached)
-
- Q_PROPERTY(QQuickItem *left READ left WRITE setLeft NOTIFY leftChanged)
- Q_PROPERTY(QQuickItem *right READ right WRITE setRight NOTIFY rightChanged)
- Q_PROPERTY(QQuickItem *up READ up WRITE setUp NOTIFY upChanged)
- Q_PROPERTY(QQuickItem *down READ down WRITE setDown NOTIFY downChanged)
- Q_PROPERTY(QQuickItem *tab READ tab WRITE setTab NOTIFY tabChanged)
- Q_PROPERTY(QQuickItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged)
- Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
-
- Q_ENUMS(Priority)
-
-public:
- QQuickKeyNavigationAttached(QObject * = 0);
-
- QQuickItem *left() const;
- void setLeft(QQuickItem *);
- QQuickItem *right() const;
- void setRight(QQuickItem *);
- QQuickItem *up() const;
- void setUp(QQuickItem *);
- QQuickItem *down() const;
- void setDown(QQuickItem *);
- QQuickItem *tab() const;
- void setTab(QQuickItem *);
- QQuickItem *backtab() const;
- void setBacktab(QQuickItem *);
-
- enum Priority { BeforeItem, AfterItem };
- Priority priority() const;
- void setPriority(Priority);
-
- static QQuickKeyNavigationAttached *qmlAttachedProperties(QObject *);
-
-Q_SIGNALS:
- void leftChanged();
- void rightChanged();
- void upChanged();
- void downChanged();
- void tabChanged();
- void backtabChanged();
- void priorityChanged();
-
-private:
- virtual void keyPressed(QKeyEvent *event, bool post);
- virtual void keyReleased(QKeyEvent *event, bool post);
- void setFocusNavigation(QQuickItem *currentItem, const char *dir);
-};
-
-class QQuickLayoutMirroringAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled RESET resetEnabled NOTIFY enabledChanged)
- Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged)
-
-public:
- explicit QQuickLayoutMirroringAttached(QObject *parent = 0);
-
- bool enabled() const;
- void setEnabled(bool);
- void resetEnabled();
-
- bool childrenInherit() const;
- void setChildrenInherit(bool);
-
- static QQuickLayoutMirroringAttached *qmlAttachedProperties(QObject *);
-Q_SIGNALS:
- void enabledChanged();
- void childrenInheritChanged();
-private:
- friend class QQuickItemPrivate;
- QQuickItemPrivate *itemPrivate;
-};
-
-class QQuickKeysAttachedPrivate : public QObjectPrivate
-{
-public:
- QQuickKeysAttachedPrivate()
- : QObjectPrivate(), inPress(false), inRelease(false)
- , inIM(false), enabled(true), imeItem(0), item(0)
- {}
-
- bool isConnected(const char *signalName);
-
- //loop detection
- bool inPress:1;
- bool inRelease:1;
- bool inIM:1;
-
- bool enabled : 1;
-
- QQuickItem *imeItem;
- QList<QQuickItem *> targets;
- QQuickItem *item;
-};
-
-class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickKeysAttached)
-
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(QDeclarativeListProperty<QQuickItem> forwardTo READ forwardTo)
- Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
-
- Q_ENUMS(Priority)
-
-public:
- QQuickKeysAttached(QObject *parent=0);
- ~QQuickKeysAttached();
-
- bool enabled() const { Q_D(const QQuickKeysAttached); return d->enabled; }
- void setEnabled(bool enabled) {
- Q_D(QQuickKeysAttached);
- if (enabled != d->enabled) {
- d->enabled = enabled;
- emit enabledChanged();
- }
- }
-
- enum Priority { BeforeItem, AfterItem};
- Priority priority() const;
- void setPriority(Priority);
-
- QDeclarativeListProperty<QQuickItem> forwardTo() {
- Q_D(QQuickKeysAttached);
- return QDeclarativeListProperty<QQuickItem>(this, d->targets);
- }
-
- virtual void componentComplete();
-
- static QQuickKeysAttached *qmlAttachedProperties(QObject *);
-
-Q_SIGNALS:
- void enabledChanged();
- void priorityChanged();
- void pressed(QQuickKeyEvent *event);
- void released(QQuickKeyEvent *event);
- void digit0Pressed(QQuickKeyEvent *event);
- void digit1Pressed(QQuickKeyEvent *event);
- void digit2Pressed(QQuickKeyEvent *event);
- void digit3Pressed(QQuickKeyEvent *event);
- void digit4Pressed(QQuickKeyEvent *event);
- void digit5Pressed(QQuickKeyEvent *event);
- void digit6Pressed(QQuickKeyEvent *event);
- void digit7Pressed(QQuickKeyEvent *event);
- void digit8Pressed(QQuickKeyEvent *event);
- void digit9Pressed(QQuickKeyEvent *event);
-
- void leftPressed(QQuickKeyEvent *event);
- void rightPressed(QQuickKeyEvent *event);
- void upPressed(QQuickKeyEvent *event);
- void downPressed(QQuickKeyEvent *event);
- void tabPressed(QQuickKeyEvent *event);
- void backtabPressed(QQuickKeyEvent *event);
-
- void asteriskPressed(QQuickKeyEvent *event);
- void numberSignPressed(QQuickKeyEvent *event);
- void escapePressed(QQuickKeyEvent *event);
- void returnPressed(QQuickKeyEvent *event);
- void enterPressed(QQuickKeyEvent *event);
- void deletePressed(QQuickKeyEvent *event);
- void spacePressed(QQuickKeyEvent *event);
- void backPressed(QQuickKeyEvent *event);
- void cancelPressed(QQuickKeyEvent *event);
- void selectPressed(QQuickKeyEvent *event);
- void yesPressed(QQuickKeyEvent *event);
- void noPressed(QQuickKeyEvent *event);
- void context1Pressed(QQuickKeyEvent *event);
- void context2Pressed(QQuickKeyEvent *event);
- void context3Pressed(QQuickKeyEvent *event);
- void context4Pressed(QQuickKeyEvent *event);
- void callPressed(QQuickKeyEvent *event);
- void hangupPressed(QQuickKeyEvent *event);
- void flipPressed(QQuickKeyEvent *event);
- void menuPressed(QQuickKeyEvent *event);
- void volumeUpPressed(QQuickKeyEvent *event);
- void volumeDownPressed(QQuickKeyEvent *event);
-
-private:
- virtual void keyPressed(QKeyEvent *event, bool post);
- virtual void keyReleased(QKeyEvent *event, bool post);
- virtual void inputMethodEvent(QInputMethodEvent *, bool post);
- virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
-
- const QByteArray keyToSignal(int key) {
- QByteArray keySignal;
- if (key >= Qt::Key_0 && key <= Qt::Key_9) {
- keySignal = "digit0Pressed";
- keySignal[5] = '0' + (key - Qt::Key_0);
- } else {
- int i = 0;
- while (sigMap[i].key && sigMap[i].key != key)
- ++i;
- keySignal = sigMap[i].sig;
- }
- return keySignal;
- }
-
- struct SigMap {
- int key;
- const char *sig;
- };
-
- static const SigMap sigMap[];
-};
-
-QSGTransformNode *QQuickItemPrivate::itemNode()
-{
- if (!itemNodeInstance) {
- itemNodeInstance = createTransformNode();
- itemNodeInstance->setFlag(QSGNode::OwnedByParent, false);
-#ifdef QML_RUNTIME_TESTING
- Q_Q(QQuickItem);
- itemNodeInstance->description = QString::fromLatin1("QQuickItem(%1)").arg(QString::fromLatin1(q->metaObject()->className()));
-#endif
- }
- return itemNodeInstance;
-}
-
-QSGNode *QQuickItemPrivate::childContainerNode()
-{
- if (!groupNode) {
- groupNode = new QSGNode();
- if (rootNode)
- rootNode->appendChildNode(groupNode);
- else if (clipNode)
- clipNode->appendChildNode(groupNode);
- else if (opacityNode)
- opacityNode->appendChildNode(groupNode);
- else
- itemNode()->appendChildNode(groupNode);
- groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, childrenDoNotOverlap);
-#ifdef QML_RUNTIME_TESTING
- groupNode->description = QLatin1String("group");
-#endif
- }
- return groupNode;
-}
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItemPrivate::ChangeTypes);
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickKeysAttached)
-QML_DECLARE_TYPEINFO(QQuickKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickKeyNavigationAttached)
-QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickLayoutMirroringAttached)
-QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
-
-#endif // QQUICKITEM_P_H
diff --git a/src/declarative/items/qquickitemsmodule.cpp b/src/declarative/items/qquickitemsmodule.cpp
deleted file mode 100644
index 060d51e092..0000000000
--- a/src/declarative/items/qquickitemsmodule.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickitemsmodule_p.h"
-
-#include "qquickitem.h"
-#include "qquickitem_p.h"
-#include "qquickevents_p_p.h"
-#include "qquickrectangle_p.h"
-#include "qquickfocusscope_p.h"
-#include "qquicktext_p.h"
-#include "qquicktextinput_p.h"
-#include "qquicktextedit_p.h"
-#include "qquickimage_p.h"
-#include "qquickborderimage_p.h"
-#include "qquickscalegrid_p_p.h"
-#include "qquickmousearea_p.h"
-#include "qquickpincharea_p.h"
-#include "qquickflickable_p.h"
-#include "qquickflickable_p_p.h"
-#include "qquicklistview_p.h"
-#include "qquickvisualitemmodel_p.h"
-#include "qquickvisualdatamodel_p.h"
-#include "qquickgridview_p.h"
-#include "qquickpathview_p.h"
-#include <private/qdeclarativepath_p.h>
-#include <private/qdeclarativepathinterpolator_p.h>
-#include "qquickpositioners_p.h"
-#include "qquickrepeater_p.h"
-#include "qquickloader_p.h"
-#include "qquickanimatedimage_p.h"
-#include "qquickflipable_p.h"
-#include "qquicktranslate_p.h"
-#include "qquickstateoperations_p.h"
-#include "qquickanimation_p.h"
-#include <private/qquickshadereffect_p.h>
-#include <private/qquickshadereffectsource_p.h>
-//#include <private/qquickpincharea_p.h>
-#include <private/qquickcanvasitem_p.h>
-#include <private/qquickcontext2d_p.h>
-#include "qquicksprite_p.h"
-#include "qquickspriteimage_p.h"
-#include "qquickdrag_p.h"
-#include "qquickdroparea_p.h"
-#include "qquickmultipointtoucharea_p.h"
-#include <private/qdeclarativemetatype_p.h>
-
-static QDeclarativePrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject *parent)
-{
- QQuickItem *item = qobject_cast<QQuickItem *>(obj);
- if (!item)
- return QDeclarativePrivate::IncompatibleObject;
-
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent);
- if (!parentItem)
- return QDeclarativePrivate::IncompatibleParent;
-
- item->setParentItem(parentItem);
- return QDeclarativePrivate::Parented;
-}
-
-static bool compareQQuickAnchorLines(const void *p1, const void *p2)
-{
- const QQuickAnchorLine &l1 = *static_cast<const QQuickAnchorLine*>(p1);
- const QQuickAnchorLine &l2 = *static_cast<const QQuickAnchorLine*>(p2);
- return l1 == l2;
-}
-
-static void qt_quickitems_defineModule(const char *uri, int major, int minor)
-{
- QDeclarativePrivate::RegisterAutoParent autoparent = { 0, &qquickitem_autoParent };
- QDeclarativePrivate::qmlregister(QDeclarativePrivate::AutoParentRegistration, &autoparent);
-
-#ifdef QT_NO_MOVIE
- qmlRegisterTypeNotAvailable(uri,major,minor,"AnimatedImage", qApp->translate("QQuickAnimatedImage","Qt was built without support for QMovie"));
-#else
- qmlRegisterType<QQuickAnimatedImage>(uri,major,minor,"AnimatedImage");
-#endif
- qmlRegisterType<QQuickBorderImage>(uri,major,minor,"BorderImage");
- qmlRegisterType<QQuickColumn>(uri,major,minor,"Column");
- qmlRegisterType<QQuickFlickable>(uri,major,minor,"Flickable");
- qmlRegisterType<QQuickFlipable>(uri,major,minor,"Flipable");
- qmlRegisterType<QQuickFlow>(uri,major,minor,"Flow");
-// qmlRegisterType<QDeclarativeFocusPanel>(uri,major,minor,"FocusPanel");
- qmlRegisterType<QQuickFocusScope>(uri,major,minor,"FocusScope");
- qmlRegisterType<QQuickGradient>(uri,major,minor,"Gradient");
- qmlRegisterType<QQuickGradientStop>(uri,major,minor,"GradientStop");
- qmlRegisterType<QQuickGrid>(uri,major,minor,"Grid");
- qmlRegisterType<QQuickGridView>(uri,major,minor,"GridView");
- qmlRegisterType<QQuickImage>(uri,major,minor,"Image");
- qmlRegisterType<QQuickItem>(uri,major,minor,"Item");
- qmlRegisterType<QQuickListView>(uri,major,minor,"ListView");
- qmlRegisterType<QQuickLoader>(uri,major,minor,"Loader");
- qmlRegisterType<QQuickMouseArea>(uri,major,minor,"MouseArea");
- qmlRegisterType<QDeclarativePath>(uri,major,minor,"Path");
- qmlRegisterType<QDeclarativePathAttribute>(uri,major,minor,"PathAttribute");
- qmlRegisterType<QDeclarativePathCubic>(uri,major,minor,"PathCubic");
- qmlRegisterType<QDeclarativePathLine>(uri,major,minor,"PathLine");
- qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
- qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
- qmlRegisterType<QDeclarativePathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
- qmlRegisterType<QDeclarativePathArc>("QtQuick",2,0,"PathArc");
- qmlRegisterType<QDeclarativePathSvg>("QtQuick",2,0,"PathSvg");
- qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
- qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner",
- QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QIntValidator>(uri,major,minor,"IntValidator");
- qmlRegisterType<QDoubleValidator>(uri,major,minor,"DoubleValidator");
- qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator");
-#endif
- qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle");
- qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater");
- qmlRegisterType<QQuickRow>(uri,major,minor,"Row");
- qmlRegisterType<QQuickTranslate>(uri,major,minor,"Translate");
- qmlRegisterType<QQuickRotation>(uri,major,minor,"Rotation");
- qmlRegisterType<QQuickScale>(uri,major,minor,"Scale");
- qmlRegisterType<QQuickText>(uri,major,minor,"Text");
- qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
- qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
- qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
- qmlRegisterType<QQuickVisualDataModel>(uri,major,minor,"VisualDataModel");
- qmlRegisterType<QQuickVisualDataGroup>(uri,major,minor,"VisualDataGroup");
- qmlRegisterType<QQuickVisualItemModel>(uri,major,minor,"VisualItemModel");
-
- qmlRegisterType<QQuickAnchors>();
- qmlRegisterType<QQuickKeyEvent>();
- qmlRegisterType<QQuickMouseEvent>();
- qmlRegisterType<QQuickTransform>();
- qmlRegisterType<QDeclarativePathElement>();
- qmlRegisterType<QDeclarativeCurve>();
- qmlRegisterType<QQuickScaleGrid>();
- qmlRegisterType<QQuickTextLine>();
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QValidator>();
-#endif
- qmlRegisterType<QQuickVisualModel>();
- qmlRegisterType<QQuickPen>();
- qmlRegisterType<QQuickFlickableVisibleArea>();
- qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
- QDeclarativeMetaType::setQQuickAnchorLineCompareFunction(compareQQuickAnchorLines);
-
- qmlRegisterUncreatableType<QQuickKeyNavigationAttached>(uri,major,minor,"KeyNavigation",QQuickKeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
- qmlRegisterUncreatableType<QQuickKeysAttached>(uri,major,minor,"Keys",QQuickKeysAttached::tr("Keys is only available via attached properties"));
- qmlRegisterUncreatableType<QQuickLayoutMirroringAttached>(uri,major,minor,"LayoutMirroring", QQuickLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
-
- qmlRegisterType<QQuickPinchArea>(uri,major,minor,"PinchArea");
- qmlRegisterType<QQuickPinch>(uri,major,minor,"Pinch");
- qmlRegisterType<QQuickPinchEvent>();
-
- qmlRegisterType<QQuickShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
- qmlRegisterType<QQuickShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
- qmlRegisterUncreatableType<QQuickShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QQuickShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
- qmlRegisterType<QQuickGridMesh>("QtQuick", 2, 0, "GridMesh");
-
- qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
-
- qmlRegisterType<QQuickCanvasItem>("QtQuick", 2, 0, "Canvas");
-
- qmlRegisterType<QQuickSprite>("QtQuick", 2, 0, "Sprite");
- qmlRegisterType<QQuickSpriteImage>("QtQuick", 2, 0, "SpriteImage");
-
- qmlRegisterType<QQuickParentChange>(uri, major, minor,"ParentChange");
- qmlRegisterType<QQuickAnchorChanges>(uri, major, minor,"AnchorChanges");
- qmlRegisterType<QQuickAnchorSet>();
- qmlRegisterType<QQuickAnchorAnimation>(uri, major, minor,"AnchorAnimation");
- qmlRegisterType<QQuickParentAnimation>(uri, major, minor,"ParentAnimation");
- qmlRegisterType<QQuickPathAnimation>("QtQuick",2,0,"PathAnimation");
- qmlRegisterType<QDeclarativePathInterpolator>("QtQuick",2,0,"PathInterpolator");
-
- qmlRegisterType<QQuickDropArea>("QtQuick", 2, 0, "DropArea");
- qmlRegisterType<QQuickDropEvent>();
- qmlRegisterType<QQuickDropAreaDrag>();
- qmlRegisterUncreatableType<QQuickDrag>("QtQuick", 2, 0, "Drag", QQuickDragAttached::tr("Drag is only available via attached properties"));
-
- qmlRegisterType<QQuickMultiPointTouchArea>("QtQuick", 2, 0, "MultiPointTouchArea");
- qmlRegisterType<QQuickTouchPoint>("QtQuick", 2, 0, "TouchPoint");
- qmlRegisterType<QQuickGrabGestureEvent>();
-}
-
-void QQuickItemsModule::defineModule()
-{
- static bool initialized = false;
- if (initialized)
- return;
- initialized = true;
-
- // XXX todo - Remove before final integration...
- QByteArray mode = qgetenv("QMLSCENE_IMPORT_NAME");
- QByteArray name = "QtQuick";
- int majorVersion = 2;
- int minorVersion = 0;
- if (mode == "quick1") {
- majorVersion = 1;
- } else if (mode == "qt") {
- name = "Qt";
- majorVersion = 4;
- minorVersion = 7;
- }
-
- qt_quickitems_defineModule(name, majorVersion, minorVersion);
-}
-
diff --git a/src/declarative/items/qquickitemsmodule_p.h b/src/declarative/items/qquickitemsmodule_p.h
deleted file mode 100644
index d3682007d7..0000000000
--- a/src/declarative/items/qquickitemsmodule_p.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKITEMSMODULE_P_H
-#define QQUICKITEMSMODULE_P_H
-
-#include <qdeclarative.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItemsModule
-{
-public:
- static void defineModule();
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKITEMSMODULE_P_H
-
diff --git a/src/declarative/items/qquickitemview_p.h b/src/declarative/items/qquickitemview_p.h
deleted file mode 100644
index b8e27e4741..0000000000
--- a/src/declarative/items/qquickitemview_p.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKITEMVIEW_P_H
-#define QQUICKITEMVIEW_P_H
-
-#include "qquickflickable_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeChangeSet;
-
-class QQuickItemViewPrivate;
-
-class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable
-{
- Q_OBJECT
-
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
- Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
- Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
-
- Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
- Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
-
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-
- Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
- Q_PROPERTY(QQuickItem *headerItem READ headerItem NOTIFY headerItemChanged)
- Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
- Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged)
-
- Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
- Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
- Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
- Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
- Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
- Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
- Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
-
- Q_ENUMS(HighlightRangeMode)
- Q_ENUMS(PositionMode)
-
-public:
- QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent = 0);
- ~QQuickItemView();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int count() const;
-
- int currentIndex() const;
- void setCurrentIndex(int idx);
-
- QQuickItem *currentItem() const;
-
- bool isWrapEnabled() const;
- void setWrapEnabled(bool);
-
- int cacheBuffer() const;
- void setCacheBuffer(int);
-
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection(Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
-
- QDeclarativeComponent *footer() const;
- void setFooter(QDeclarativeComponent *);
- QQuickItem *footerItem() const;
-
- QDeclarativeComponent *header() const;
- void setHeader(QDeclarativeComponent *);
- QQuickItem *headerItem() const;
-
- QDeclarativeComponent *highlight() const;
- void setHighlight(QDeclarativeComponent *);
-
- QQuickItem *highlightItem() const;
-
- bool highlightFollowsCurrentItem() const;
- virtual void setHighlightFollowsCurrentItem(bool);
-
- enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
- HighlightRangeMode highlightRangeMode() const;
- void setHighlightRangeMode(HighlightRangeMode mode);
-
- qreal preferredHighlightBegin() const;
- void setPreferredHighlightBegin(qreal);
- void resetPreferredHighlightBegin();
-
- qreal preferredHighlightEnd() const;
- void setPreferredHighlightEnd(qreal);
- void resetPreferredHighlightEnd();
-
- int highlightMoveDuration() const;
- virtual void setHighlightMoveDuration(int);
-
- enum PositionMode { Beginning, Center, End, Visible, Contain };
-
- Q_INVOKABLE void positionViewAtIndex(int index, int mode);
- Q_INVOKABLE int indexAt(qreal x, qreal y) const;
- Q_INVOKABLE void positionViewAtBeginning();
- Q_INVOKABLE void positionViewAtEnd();
-
- virtual void setContentX(qreal pos);
- virtual void setContentY(qreal pos);
- virtual qreal xOrigin() const;
-
-signals:
- void modelChanged();
- void delegateChanged();
- void countChanged();
- void currentIndexChanged();
- void currentItemChanged();
-
- void keyNavigationWrapsChanged();
- void cacheBufferChanged();
-
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
-
- void headerChanged();
- void footerChanged();
- void headerItemChanged();
- void footerItemChanged();
-
- void highlightChanged();
- void highlightItemChanged();
- void highlightFollowsCurrentItemChanged();
- void highlightRangeModeChanged();
- void preferredHighlightBeginChanged();
- void preferredHighlightEndChanged();
- void highlightMoveDurationChanged();
-
-protected:
- virtual void updatePolish();
- virtual void componentComplete();
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual qreal minYExtent() const;
- virtual qreal maxYExtent() const;
- virtual qreal minXExtent() const;
- virtual qreal maxXExtent() const;
-
-protected slots:
- virtual void updateSections() {}
- void destroyRemoved();
- void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
- void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
- void destroyingItem(QQuickItem *item);
- void animStopped();
- void trackedPositionChanged();
-
-
-
-private:
- Q_DECLARE_PRIVATE(QQuickItemView)
-};
-
-
-class Q_AUTOTEST_EXPORT QQuickItemViewAttached : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
- Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
-
- Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
- Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
- Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
-
-public:
- QQuickItemViewAttached(QObject *parent)
- : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
- ~QQuickItemViewAttached() {}
-
- bool isCurrentItem() const { return m_isCurrent; }
- void setIsCurrentItem(bool c) {
- if (m_isCurrent != c) {
- m_isCurrent = c;
- emit currentItemChanged();
- }
- }
-
- bool delayRemove() const { return m_delayRemove; }
- void setDelayRemove(bool delay) {
- if (m_delayRemove != delay) {
- m_delayRemove = delay;
- emit delayRemoveChanged();
- }
- }
-
- QString section() const { return m_section; }
- void setSection(const QString &sect) {
- if (m_section != sect) {
- m_section = sect;
- emit sectionChanged();
- }
- }
-
- QString prevSection() const { return m_prevSection; }
- void setPrevSection(const QString &sect) {
- if (m_prevSection != sect) {
- m_prevSection = sect;
- emit prevSectionChanged();
- }
- }
-
- QString nextSection() const { return m_nextSection; }
- void setNextSection(const QString &sect) {
- if (m_nextSection != sect) {
- m_nextSection = sect;
- emit nextSectionChanged();
- }
- }
-
- void emitAdd() { emit add(); }
- void emitRemove() { emit remove(); }
-
-signals:
- void currentItemChanged();
- void delayRemoveChanged();
-
- void add();
- void remove();
-
- void sectionChanged();
- void prevSectionChanged();
- void nextSectionChanged();
-
-public:
- bool m_isCurrent : 1;
- bool m_delayRemove : 1;
-
- // current only used by list view
- mutable QString m_section;
- QString m_prevSection;
- QString m_nextSection;
-};
-
-
-QT_END_NAMESPACE
-QT_END_HEADER
-
-#endif // QQUICKITEMVIEW_P_H
-
diff --git a/src/declarative/items/qquickitemview_p_p.h b/src/declarative/items/qquickitemview_p_p.h
deleted file mode 100644
index 4db274e045..0000000000
--- a/src/declarative/items/qquickitemview_p_p.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKITEMVIEW_P_P_H
-#define QQUICKITEMVIEW_P_P_H
-
-#include "qquickitemview_p.h"
-#include "qquickflickable_p_p.h"
-#include "qquickvisualdatamodel_p.h"
-#include <private/qdeclarativechangeset_p.h>
-
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class FxViewItem
-{
-public:
- FxViewItem(QQuickItem *, bool own);
- ~FxViewItem();
-
- // these are positions and sizes along the current direction of scrolling/flicking
- virtual qreal position() const = 0;
- virtual qreal endPosition() const = 0;
- virtual qreal size() const = 0;
- virtual qreal sectionSize() const = 0;
-
- virtual bool contains(qreal x, qreal y) const = 0;
-
- QQuickItem *item;
- bool ownItem;
- int index;
- QQuickItemViewAttached *attached;
-};
-
-class QQuickItemViewChangeSet
-{
-public:
- QQuickItemViewChangeSet();
-
- bool hasPendingChanges() const;
- void prepare(int currentIndex, int count);
- void reset();
-
- void applyChanges(const QDeclarativeChangeSet &changeSet);
-
- int itemCount;
- int newCurrentIndex;
- QDeclarativeChangeSet pendingChanges;
- QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> removedItems;
-
- bool active : 1;
- bool currentChanged : 1;
- bool currentRemoved : 1;
-};
-
-class QQuickItemViewPrivate : public QQuickFlickablePrivate
-{
- Q_DECLARE_PUBLIC(QQuickItemView)
-public:
- QQuickItemViewPrivate();
-
- struct InsertionsResult {
- QList<FxViewItem *> addedItems;
- QList<FxViewItem *> movedBackwards;
- qreal sizeAddedBeforeVisible;
-
- InsertionsResult() : sizeAddedBeforeVisible(0) {}
- };
-
- enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
- enum MovementReason { Other, SetIndex, Mouse };
-
- bool isValid() const;
- qreal position() const;
- qreal size() const;
- qreal startPosition() const;
- qreal endPosition() const;
- qreal contentStartPosition() const;
- int findLastVisibleIndex(int defaultValue = -1) const;
- FxViewItem *visibleItem(int modelIndex) const;
- FxViewItem *firstVisibleItem() const;
- int mapFromModel(int modelIndex) const;
-
- virtual void init();
- virtual void clear();
- virtual void updateViewport();
-
- void regenerate();
- void layout();
- void refill();
- void refill(qreal from, qreal to, bool doBuffer = false);
- void mirrorChange();
-
- FxViewItem *createItem(int modelIndex, bool asynchronous = false);
- virtual void releaseItem(FxViewItem *item);
-
- QQuickItem *createHighlightItem();
- QQuickItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
-
- void updateCurrent(int modelIndex);
- void updateTrackedItem();
- void updateUnrequestedIndexes();
- void updateUnrequestedPositions();
- void updateVisibleIndex();
- void positionViewAtIndex(int index, int mode);
- void applyPendingChanges();
- bool applyModelChanges();
-
- void checkVisible() const;
-
- void markExtentsDirty() {
- if (layoutOrientation() == Qt::Vertical)
- vData.markExtentsDirty();
- else
- hData.markExtentsDirty();
- }
-
- QDeclarativeGuard<QQuickVisualModel> model;
- QVariant modelVariant;
- int itemCount;
- int buffer;
- int bufferMode;
- Qt::LayoutDirection layoutDirection;
-
- MovementReason moveReason;
-
- QList<FxViewItem *> visibleItems;
- int visibleIndex;
- int currentIndex;
- FxViewItem *currentItem;
- FxViewItem *trackedItem;
- QHash<QQuickItem*,int> unrequestedItems;
- int requestedIndex;
- FxViewItem *requestedItem;
- QQuickItemViewChangeSet currentChanges;
-
- // XXX split into struct
- QDeclarativeComponent *highlightComponent;
- FxViewItem *highlight;
- int highlightRange; // enum value
- qreal highlightRangeStart;
- qreal highlightRangeEnd;
- int highlightMoveDuration;
-
- QDeclarativeComponent *headerComponent;
- FxViewItem *header;
- QDeclarativeComponent *footerComponent;
- FxViewItem *footer;
-
- mutable qreal minExtent;
- mutable qreal maxExtent;
-
- bool ownModel : 1;
- bool wrap : 1;
- bool deferredRelease : 1;
- bool inApplyModelChanges : 1;
- bool inViewportMoved : 1;
- bool forceLayout : 1;
- bool currentIndexCleared : 1;
- bool haveHighlightRange : 1;
- bool autoHighlight : 1;
- bool highlightRangeStartValid : 1;
- bool highlightRangeEndValid : 1;
- bool fillCacheBuffer : 1;
- bool inRequest : 1;
- bool requestedAsync : 1;
-
-protected:
- virtual Qt::Orientation layoutOrientation() const = 0;
- virtual bool isContentFlowReversed() const = 0;
-
- virtual qreal positionAt(int index) const = 0;
- virtual qreal endPositionAt(int index) const = 0;
- virtual qreal originPosition() const = 0;
- virtual qreal lastPosition() const = 0;
-
- virtual qreal headerSize() const = 0;
- virtual qreal footerSize() const = 0;
- virtual bool showHeaderForIndex(int index) const = 0;
- virtual bool showFooterForIndex(int index) const = 0;
- virtual void updateHeader() = 0;
- virtual void updateFooter() = 0;
-
- virtual void createHighlight() = 0;
- virtual void updateHighlight() = 0;
- virtual void resetHighlightPosition() = 0;
-
- virtual void setPosition(qreal pos) = 0;
- virtual void fixupPosition() = 0;
-
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) = 0;
- virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
- virtual void visibleItemsChanged() = 0;
-
- virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0;
- virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0;
- virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem) = 0;
- virtual void resetFirstItemPosition() = 0;
- virtual void moveItemBy(FxViewItem *item, qreal forwards, qreal backwards) = 0;
-
- virtual void layoutVisibleItems() = 0;
- virtual void changedVisibleIndex(int newIndex) = 0;
- virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, FxViewItem *, InsertionsResult *) = 0;
- virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; }
-
- virtual void initializeViewItem(FxViewItem *) {}
- virtual void initializeCurrentItem() {}
- virtual void updateSections() {}
-
- virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKITEMVIEW_P_P_H
diff --git a/src/declarative/items/qquicklistview_p.h b/src/declarative/items/qquicklistview_p.h
deleted file mode 100644
index 0266e23cd5..0000000000
--- a/src/declarative/items/qquicklistview_p.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Commit: 95814418f9d6adeba365c795462e8afb00138211
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKLISTVIEW_P_H
-#define QQUICKLISTVIEW_P_H
-
-#include "qquickitemview_p.h"
-
-#include <private/qdeclarativeguard_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickListView;
-class QQuickListViewPrivate;
-class Q_AUTOTEST_EXPORT QQuickViewSection : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
- Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged)
- Q_ENUMS(SectionCriteria)
- Q_ENUMS(LabelPositioning)
-public:
- QQuickViewSection(QQuickListView *parent=0);
-
- QString property() const { return m_property; }
- void setProperty(const QString &);
-
- enum SectionCriteria { FullString, FirstCharacter };
- SectionCriteria criteria() const { return m_criteria; }
- void setCriteria(SectionCriteria);
-
- QDeclarativeComponent *delegate() const { return m_delegate; }
- void setDelegate(QDeclarativeComponent *delegate);
-
- QString sectionString(const QString &value);
-
- enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 };
- int labelPositioning() { return m_labelPositioning; }
- void setLabelPositioning(int pos);
-
-Q_SIGNALS:
- void propertyChanged();
- void criteriaChanged();
- void delegateChanged();
- void labelPositioningChanged();
-
-private:
- QString m_property;
- SectionCriteria m_criteria;
- QDeclarativeComponent *m_delegate;
- int m_labelPositioning;
- QQuickListViewPrivate *m_view;
-};
-
-
-class QQuickVisualModel;
-class QQuickListViewAttached;
-class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickListView)
-
- // XXX deprecate these two properties (only duration should be necessary)
- Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
- Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
-
- Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
-
- Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
- Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
-
- Q_PROPERTY(QQuickViewSection *section READ sectionCriteria CONSTANT)
- Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
-
- Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
-
- Q_ENUMS(Orientation)
- Q_ENUMS(SnapMode)
- Q_CLASSINFO("DefaultProperty", "data")
-
-public:
- QQuickListView(QQuickItem *parent=0);
- ~QQuickListView();
-
- qreal spacing() const;
- void setSpacing(qreal spacing);
-
- enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
- Orientation orientation() const;
- void setOrientation(Orientation);
-
- QQuickViewSection *sectionCriteria();
- QString currentSection() const;
-
- virtual void setHighlightFollowsCurrentItem(bool);
-
- qreal highlightMoveSpeed() const;
- void setHighlightMoveSpeed(qreal);
-
- qreal highlightResizeSpeed() const;
- void setHighlightResizeSpeed(qreal);
-
- int highlightResizeDuration() const;
- void setHighlightResizeDuration(int);
-
- virtual void setHighlightMoveDuration(int);
-
- enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
- SnapMode snapMode() const;
- void setSnapMode(SnapMode mode);
-
- static QQuickListViewAttached *qmlAttachedProperties(QObject *);
-
-public Q_SLOTS:
- void incrementCurrentIndex();
- void decrementCurrentIndex();
-
-Q_SIGNALS:
- void spacingChanged();
- void orientationChanged();
- void currentSectionChanged();
- void highlightMoveSpeedChanged();
- void highlightResizeSpeedChanged();
- void highlightResizeDurationChanged();
- void snapModeChanged();
-
-protected:
- virtual void viewportMoved();
- virtual void keyPressEvent(QKeyEvent *);
- virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
-
-protected Q_SLOTS:
- void updateSections();
-};
-
-class QQuickListViewAttached : public QQuickItemViewAttached
-{
- Q_OBJECT
-
-public:
- QQuickListViewAttached(QObject *parent)
- : QQuickItemViewAttached(parent), m_view(0) {}
- ~QQuickListViewAttached() {}
-
- Q_PROPERTY(QQuickListView *view READ view NOTIFY viewChanged)
- QQuickListView *view() { return m_view; }
- void setView(QQuickListView *view) {
- if (view != m_view) {
- m_view = view;
- emit viewChanged();
- }
- }
-
-Q_SIGNALS:
- void viewChanged();
-
-public:
- QDeclarativeGuard<QQuickListView> m_view;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPEINFO(QQuickListView, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickListView)
-QML_DECLARE_TYPE(QQuickViewSection)
-
-QT_END_HEADER
-
-#endif // QQUICKLISTVIEW_P_H
diff --git a/src/declarative/items/qquickloader_p.h b/src/declarative/items/qquickloader_p.h
deleted file mode 100644
index 3dcab4c654..0000000000
--- a/src/declarative/items/qquickloader_p.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKLOADER_P_H
-#define QQUICKLOADER_P_H
-
-#include "qquickimplicitsizeitem_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickLoaderPrivate;
-class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
-{
- Q_OBJECT
- Q_ENUMS(Status)
-
- Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceComponentChanged)
- Q_PROPERTY(QQuickItem *item READ item NOTIFY itemChanged)
- Q_PROPERTY(Status status READ status NOTIFY statusChanged)
- Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
- Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
-
-public:
- QQuickLoader(QQuickItem *parent = 0);
- virtual ~QQuickLoader();
-
- bool active() const;
- void setActive(bool newVal);
-
- Q_INVOKABLE void setSource(QDeclarativeV8Function *);
-
- QUrl source() const;
- void setSource(const QUrl &);
-
- QDeclarativeComponent *sourceComponent() const;
- void setSourceComponent(QDeclarativeComponent *);
- void resetSourceComponent();
-
- enum Status { Null, Ready, Loading, Error };
- Status status() const;
- qreal progress() const;
-
- bool asynchronous() const;
- void setAsynchronous(bool a);
-
- QQuickItem *item() const;
-
-Q_SIGNALS:
- void itemChanged();
- void activeChanged();
- void sourceChanged();
- void sourceComponentChanged();
- void statusChanged();
- void progressChanged();
- void loaded();
- void asynchronousChanged();
-
-protected:
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- void componentComplete();
-
-private:
- void setSource(const QUrl &sourceUrl, bool needsClear);
- void loadFromSource();
- void loadFromSourceComponent();
- Q_DISABLE_COPY(QQuickLoader)
- Q_DECLARE_PRIVATE(QQuickLoader)
- Q_PRIVATE_SLOT(d_func(), void _q_sourceLoaded())
- Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickLoader)
-
-QT_END_HEADER
-
-#endif // QQUICKLOADER_P_H
diff --git a/src/declarative/items/qquickmousearea_p.h b/src/declarative/items/qquickmousearea_p.h
deleted file mode 100644
index b8fa7d5ce8..0000000000
--- a/src/declarative/items/qquickmousearea_p.h
+++ /dev/null
@@ -1,231 +0,0 @@
-// Commit: c6e6a35aeb8794d68a3ca0c4e27a3a1181c066b5
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKMOUSEAREA_P_H
-#define QQUICKMOUSEAREA_P_H
-
-#include "qquickitem.h"
-
-#include <QtCore/qstringlist.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickDragAttached;
-class QQuickMouseEvent;
-class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
-{
- Q_OBJECT
-
- Q_ENUMS(Axis)
- Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
- Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
- Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
- Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
- Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
- Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
- Q_PROPERTY(bool active READ active NOTIFY activeChanged)
- Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
- //### consider drag and drop
-
-public:
- QQuickDrag(QObject *parent=0);
- ~QQuickDrag();
-
- QQuickItem *target() const;
- void setTarget(QQuickItem *target);
- void resetTarget();
-
- enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
- Axis axis() const;
- void setAxis(Axis);
-
- qreal xmin() const;
- void setXmin(qreal);
- qreal xmax() const;
- void setXmax(qreal);
- qreal ymin() const;
- void setYmin(qreal);
- qreal ymax() const;
- void setYmax(qreal);
-
- bool active() const;
- void setActive(bool);
-
- bool filterChildren() const;
- void setFilterChildren(bool);
-
- static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void targetChanged();
- void axisChanged();
- void minimumXChanged();
- void maximumXChanged();
- void minimumYChanged();
- void maximumYChanged();
- void activeChanged();
- void filterChildrenChanged();
-
-private:
- QQuickItem *_target;
- Axis _axis;
- qreal _xmin;
- qreal _xmax;
- qreal _ymin;
- qreal _ymax;
- bool _active : 1;
- bool _filterChildren: 1;
- Q_DISABLE_COPY(QQuickDrag)
-};
-
-class QQuickMouseAreaPrivate;
-// used in QtLocation
-class Q_DECLARATIVE_EXPORT QQuickMouseArea : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal mouseX READ mouseX NOTIFY mouseXChanged)
- Q_PROPERTY(qreal mouseY READ mouseY NOTIFY mouseYChanged)
- Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
- Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedChanged)
- Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
- Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
- Q_PROPERTY(QQuickDrag *drag READ drag CONSTANT) //### add flicking to QQuickDrag or add a QDeclarativeFlick ???
- Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged)
- Q_PROPERTY(bool propagateComposedEvents READ propagateComposedEvents WRITE setPropagateComposedEvents NOTIFY propagateComposedEventsChanged)
-
-public:
- QQuickMouseArea(QQuickItem *parent=0);
- ~QQuickMouseArea();
-
- qreal mouseX() const;
- qreal mouseY() const;
-
- bool isEnabled() const;
- void setEnabled(bool);
-
- bool hovered() const;
- bool pressed() const;
-
- Qt::MouseButtons pressedButtons() const;
-
- Qt::MouseButtons acceptedButtons() const;
- void setAcceptedButtons(Qt::MouseButtons buttons);
-
- bool hoverEnabled() const;
- void setHoverEnabled(bool h);
-
- QQuickDrag *drag();
-
- bool preventStealing() const;
- void setPreventStealing(bool prevent);
-
- bool propagateComposedEvents() const;
- void setPropagateComposedEvents(bool propagate);
-
-Q_SIGNALS:
- void hoveredChanged();
- void pressedChanged();
- void enabledChanged();
- void acceptedButtonsChanged();
- void hoverEnabledChanged();
- void positionChanged(QQuickMouseEvent *mouse);
- void mouseXChanged(QQuickMouseEvent *mouse);
- void mouseYChanged(QQuickMouseEvent *mouse);
- void preventStealingChanged();
- void propagateComposedEventsChanged();
-
- void pressed(QQuickMouseEvent *mouse);
- void pressAndHold(QQuickMouseEvent *mouse);
- void released(QQuickMouseEvent *mouse);
- void clicked(QQuickMouseEvent *mouse);
- void doubleClicked(QQuickMouseEvent *mouse);
- void entered();
- void exited();
- void canceled();
-
-protected:
- void setHovered(bool);
- bool setPressed(bool);
- bool sendMouseEvent(QMouseEvent *event);
-
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void mouseDoubleClickEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
- virtual void mouseUngrabEvent();
- virtual void hoverEnterEvent(QHoverEvent *event);
- virtual void hoverMoveEvent(QHoverEvent *event);
- virtual void hoverLeaveEvent(QHoverEvent *event);
- virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
- virtual void timerEvent(QTimerEvent *event);
- virtual void windowDeactivateEvent();
-
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual void itemChange(ItemChange change, const ItemChangeData& value);
-
-private:
- void handlePress();
- void handleRelease();
- void ungrabMouse();
-
-private:
- Q_DISABLE_COPY(QQuickMouseArea)
- Q_DECLARE_PRIVATE(QQuickMouseArea)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickDrag)
-QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickMouseArea)
-
-QT_END_HEADER
-
-#endif // QQUICKMOUSEAREA_P_H
diff --git a/src/declarative/items/qquickmultipointtoucharea.cpp b/src/declarative/items/qquickmultipointtoucharea.cpp
deleted file mode 100644
index f7fdf97fb7..0000000000
--- a/src/declarative/items/qquickmultipointtoucharea.cpp
+++ /dev/null
@@ -1,729 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickmultipointtoucharea_p.h"
-#include <qquickcanvas.h>
-#include <QEvent>
-#include <QMouseEvent>
-#include <math.h>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass TouchPoint QQuickTouchPoint
- \inqmlmodule QtQuick 2
- \ingroup qml-event-elements
- \brief The TouchPoint element describes a touch point in a MultiPointTouchArea.
-
- The TouchPoint element contains information about a touch point, such as the current
- position, pressure, and area.
-*/
-
-/*!
- \qmlproperty int QtQuick2::TouchPoint::pointId
-
- This property holds the point id of the touch point.
-
- Each touch point within a MultiPointTouchArea will have a unique id.
-*/
-void QQuickTouchPoint::setPointId(int id)
-{
- if (_id == id)
- return;
- _id = id;
- emit pointIdChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::TouchPoint::x
- \qmlproperty real QtQuick2::TouchPoint::y
-
- These properties hold the current position of the touch point.
-*/
-
-void QQuickTouchPoint::setX(qreal x)
-{
- if (_x == x)
- return;
- _x = x;
- emit xChanged();
-}
-
-void QQuickTouchPoint::setY(qreal y)
-{
- if (_y == y)
- return;
- _y = y;
- emit yChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::TouchPoint::pressure
- \qmlproperty rectangle QtQuick2::TouchPoint::area
-
- These properties hold additional information about the current state of the touch point.
-
- \list
- \i \c pressure is a value in the range of 0.0 to 1.0.
- \i \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point.
- \endlist
-*/
-void QQuickTouchPoint::setPressure(qreal pressure)
-{
- if (_pressure == pressure)
- return;
- _pressure = pressure;
- emit pressureChanged();
-}
-
-void QQuickTouchPoint::setArea(const QRectF &area)
-{
- if (_area == area)
- return;
- _area = area;
- emit areaChanged();
-}
-
-/*!
- \qmlproperty bool QtQuick2::TouchPoint::valid
-
- This property holds whether the touch point is valid.
-
- An invalid touch point is one that has not yet been pressed,
- or has already been released.
-*/
-void QQuickTouchPoint::setValid(bool valid)
-{
- if (_valid == valid)
- return;
- _valid = valid;
- emit validityChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::TouchPoint::startX
- \qmlproperty real QtQuick2::TouchPoint::startY
-
- These properties hold the starting position of the touch point.
-*/
-
-void QQuickTouchPoint::setStartX(qreal startX)
-{
- if (_startX == startX)
- return;
- _startX = startX;
- emit startXChanged();
-}
-
-void QQuickTouchPoint::setStartY(qreal startY)
-{
- if (_startY == startY)
- return;
- _startY = startY;
- emit startYChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::TouchPoint::previousX
- \qmlproperty real QtQuick2::TouchPoint::previousY
-
- These properties hold the previous position of the touch point.
-*/
-void QQuickTouchPoint::setPreviousX(qreal previousX)
-{
- if (_previousX == previousX)
- return;
- _previousX = previousX;
- emit previousXChanged();
-}
-
-void QQuickTouchPoint::setPreviousY(qreal previousY)
-{
- if (_previousY == previousY)
- return;
- _previousY = previousY;
- emit previousYChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::TouchPoint::sceneX
- \qmlproperty real QtQuick2::TouchPoint::sceneY
-
- These properties hold the current position of the touch point in scene coordinates.
-*/
-
-void QQuickTouchPoint::setSceneX(qreal sceneX)
-{
- if (_sceneX == sceneX)
- return;
- _sceneX = sceneX;
- emit sceneXChanged();
-}
-
-void QQuickTouchPoint::setSceneY(qreal sceneY)
-{
- if (_sceneY == sceneY)
- return;
- _sceneY = sceneY;
- emit sceneYChanged();
-}
-
-/*!
- \qmlclass MultiPointTouchArea QQuickMultiPointTouchArea
- \inqmlmodule QtQuick 2
- \brief The MultiPointTouchArea item enables handling of multiple touch points.
- \inherits Item
-
- A MultiPointTouchArea is an invisible item that is used to track multiple touch points.
-
- The \l enabled property is used to enable and disable touch handling. When disabled,
- the touch area becomes transparent to mouse/touch events.
-
- MultiPointTouchArea can be used in two ways:
-
- \list
- \o setting \c touchPoints to provide touch point objects with properties that can be bound to
- \o using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers
- \endlist
-
- While a MultiPointTouchArea \i can take exclusive ownership of certain touch points, it is also possible to have
- multiple MultiPointTouchAreas active at the same time, each operating on a different set of touch points.
-
- \sa TouchPoint
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsPressed(list<TouchPoint> touchPoints)
-
- This handler is called when new touch points are added. \a touchPoints is a list of these new points.
-
- If minimumTouchPoints is set to a value greater than one, this handler will not be called until the minimum number
- of required touch points has been reached. At that point, touchPointsPressed will be called with all the current touch points.
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsUpdated(list<TouchPoint> touchPoints)
-
- This handler is called when existing touch points are updated. \a touchPoints is a list of these updated points.
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsReleased(list<TouchPoint> touchPoints)
-
- This handler is called when existing touch points are removed. \a touchPoints is a list of these removed points.
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsCanceled(list<TouchPoint> touchPoints)
-
- This handler is called when new touch events have been canceled because another element stole the touch event handling.
-
- This signal is for advanced use: it is useful when there is more than one MultiPointTouchArea
- that is handling input, or when there is a MultiPointTouchArea inside a \l Flickable. In the latter
- case, if you execute some logic on the touchPointsPressed signal and then start dragging, the
- \l Flickable may steal the touch handling from the MultiPointTouchArea. In these cases, to reset
- the logic when the MultiPointTouchArea has lost the touch handling to the \l Flickable,
- \c onTouchPointsCanceled should be used in addition to onTouchPointsReleased.
-
- \a touchPoints is the list of canceled points.
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::gestureStarted(GestureEvent gesture)
-
- This handler is called when the global drag threshold has been reached.
-
- This function is typically used when a MultiPointTouchAreas has been nested in a Flickable or another MultiPointTouchArea.
- Wnen the threshold has been reached, and the handler called, you can determine whether or not the touch
- area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
- gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
-
- The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
-*/
-
-/*!
- \qmlsignal QtQuick2::MultiPointTouchArea::touchUpdated(list<TouchPoint> touchPoints)
-
- This handler is called when the touch points handled by the MultiPointTouchArea change. This includes adding new touch points,
- removing previous touch points, as well as updating current touch point data. \a touchPoints is the list of all current touch
- points.
-*/
-
-/*!
- \qmlproperty list<TouchPoint> QtQuick2::MultiPointTouchArea::touchPoints
-
- This property holds a set of user-defined touch point objects that can be bound to.
-
- In the following example, we have two small rectangles that follow our touch points.
-
- \snippet doc/src/snippets/declarative/multipointtoucharea/multipointtoucharea.qml 0
-
- By default this property holds an empty list.
-
- \sa TouchPoint
-*/
-
-QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
- : QQuickItem(parent),
- _minimumTouchPoints(0),
- _maximumTouchPoints(INT_MAX),
- _stealMouse(false)
-{
- setAcceptedMouseButtons(Qt::LeftButton);
- setFiltersChildMouseEvents(true);
-}
-
-QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
-{
- clearTouchLists();
- foreach (QObject *obj, _touchPoints) {
- QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
- if (!dtp->isQmlDefined())
- delete dtp;
- }
-}
-
-/*!
- \qmlproperty int QtQuick2::MultiPointTouchArea::minimumTouchPoints
- \qmlproperty int QtQuick2::MultiPointTouchArea::maximumTouchPoints
-
- These properties hold the range of touch points to be handled by the touch area.
-
- These are convenience that allow you to, for example, have nested MultiPointTouchAreas,
- one handling two finger touches, and another handling three finger touches.
-
- By default, all touch points within the touch area are handled.
-*/
-
-int QQuickMultiPointTouchArea::minimumTouchPoints() const
-{
- return _minimumTouchPoints;
-}
-
-void QQuickMultiPointTouchArea::setMinimumTouchPoints(int num)
-{
- if (_minimumTouchPoints == num)
- return;
- _minimumTouchPoints = num;
- emit minimumTouchPointsChanged();
-}
-
-int QQuickMultiPointTouchArea::maximumTouchPoints() const
-{
- return _maximumTouchPoints;
-}
-
-void QQuickMultiPointTouchArea::setMaximumTouchPoints(int num)
-{
- if (_maximumTouchPoints == num)
- return;
- _maximumTouchPoints = num;
- emit maximumTouchPointsChanged();
-}
-
-void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
-{
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd: {
- //if e.g. a parent Flickable has the mouse grab, don't process the touch events
- QQuickCanvas *c = canvas();
- QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
- if (grabber && grabber != this && grabber->keepMouseGrab() && grabber->isEnabled()) {
- QQuickItem *item = this;
- while ((item = item->parentItem())) {
- if (item == grabber)
- return;
- }
- }
- updateTouchData(event);
- if (event->type() == QEvent::TouchEnd) {
- //TODO: move to canvas
- _stealMouse = false;
- setKeepMouseGrab(false);
- QQuickCanvas *c = canvas();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepTouchGrab(false);
- ungrabTouchPoints();
- }
- break;
- }
- default:
- QQuickItem::touchEvent(event);
- break;
- }
-}
-
-void QQuickMultiPointTouchArea::grabGesture()
-{
- _stealMouse = true;
-
- grabMouse();
- setKeepMouseGrab(true);
-
- grabTouchPoints(_touchPoints.keys());
- setKeepTouchGrab(true);
-}
-
-void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
-{
- bool ended = false;
- bool moved = false;
- bool started = false;
-
- clearTouchLists();
- QTouchEvent *e = static_cast<QTouchEvent*>(event);
- QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints();
- int numTouchPoints = touchPoints.count();
- //always remove released touches, and make sure we handle all releases before adds.
- foreach (QTouchEvent::TouchPoint p, touchPoints) {
- Qt::TouchPointState touchPointState = p.state();
- int id = p.id();
- if (touchPointState & Qt::TouchPointReleased) {
- QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
- if (!dtp)
- continue;
- _releasedTouchPoints.append(dtp);
- _touchPoints.remove(id);
- ended = true;
- }
- }
- if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
- foreach (QTouchEvent::TouchPoint p, touchPoints) {
- Qt::TouchPointState touchPointState = p.state();
- int id = p.id();
- if (touchPointState & Qt::TouchPointReleased) {
- //handled above
- } else if (!_touchPoints.contains(id)) { //could be pressed, moved, or stationary
- addTouchPoint(&p);
- started = true;
- } else if (touchPointState & Qt::TouchPointMoved) {
- QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
- Q_ASSERT(dtp);
- _movedTouchPoints.append(dtp);
- updateTouchPoint(dtp,&p);
- moved = true;
- } else {
- QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
- Q_ASSERT(dtp);
- updateTouchPoint(dtp,&p);
- }
- }
-
- //see if we should be grabbing the gesture
- if (!_stealMouse /* !ignoring gesture*/) {
- bool offerGrab = false;
- const int dragThreshold = qApp->styleHints()->startDragDistance();
- foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
- if (p.state() == Qt::TouchPointReleased)
- continue;
- const QPointF &currentPos = p.scenePos();
- const QPointF &startPos = p.startScenePos();
- if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
- offerGrab = true;
- else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
- offerGrab = true;
- if (offerGrab)
- break;
- }
-
- if (offerGrab) {
- QQuickGrabGestureEvent event;
- event._touchPoints = _touchPoints.values();
- emit gestureStarted(&event);
- if (event.wantsGrab())
- grabGesture();
- }
- }
-
- if (ended) emit(touchPointsReleased(_releasedTouchPoints));
- if (moved) emit(touchPointsUpdated(_movedTouchPoints));
- if (started) emit(touchPointsPressed(_pressedTouchPoints));
- if (!_touchPoints.isEmpty()) emit touchUpdated(_touchPoints.values());
- }
-}
-
-void QQuickMultiPointTouchArea::clearTouchLists()
-{
- foreach (QObject *obj, _releasedTouchPoints) {
- QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
- if (!dtp->isQmlDefined())
- delete dtp;
- else
- dtp->setValid(false);
- }
- _releasedTouchPoints.clear();
- _pressedTouchPoints.clear();
- _movedTouchPoints.clear();
-}
-
-void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
-{
- QQuickTouchPoint *dtp = 0;
- foreach (QQuickTouchPoint* tp, _touchPrototypes) {
- if (!tp->isValid()) {
- tp->setValid(true);
- dtp = tp;
- break;
- }
- }
-
- if (dtp == 0)
- dtp = new QQuickTouchPoint(false);
- dtp->setPointId(p->id());
- updateTouchPoint(dtp,p);
- _touchPoints.insert(p->id(),dtp);
- //we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed
- if (p->state() & Qt::TouchPointPressed || p->state() & Qt::TouchPointMoved || p->state() & Qt::TouchPointStationary)
- _pressedTouchPoints.append(dtp);
-}
-
-void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
-{
- int id = _touchPrototypes.count();
- prototype->setPointId(id);
- _touchPrototypes.insert(id, prototype);
-}
-
-void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QTouchEvent::TouchPoint *p)
-{
- //TODO: if !qmlDefined, could bypass setters.
- // also, should only emit signals after all values have been set
- dtp->setX(p->pos().x());
- dtp->setY(p->pos().y());
- dtp->setPressure(p->pressure());
- dtp->setArea(p->rect());
- dtp->setStartX(p->startPos().x());
- dtp->setStartY(p->startPos().y());
- dtp->setPreviousX(p->lastPos().x());
- dtp->setPreviousY(p->lastPos().y());
- dtp->setSceneX(p->scenePos().x());
- dtp->setSceneY(p->scenePos().y());
-}
-
-void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
-{
- if (!isEnabled()) {
- QQuickItem::mousePressEvent(event);
- return;
- }
-
- _stealMouse = false;
- setKeepMouseGrab(false);
- event->setAccepted(true);
-}
-
-void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
-{
- if (!isEnabled()) {
- QQuickItem::mouseMoveEvent(event);
- return;
- }
-
- //do nothing
-}
-
-void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
-{
- _stealMouse = false;
- if (!isEnabled()) {
- QQuickItem::mouseReleaseEvent(event);
- return;
- }
- QQuickCanvas *c = canvas();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
-}
-
-void QQuickMultiPointTouchArea::ungrab()
-{
- if (_touchPoints.count()) {
- QQuickCanvas *c = canvas();
- if (c && c->mouseGrabberItem() == this) {
- _stealMouse = false;
- setKeepMouseGrab(false);
- }
- setKeepTouchGrab(false);
- emit touchPointsCanceled(_touchPoints.values());
- clearTouchLists();
- foreach (QObject *obj, _touchPoints) {
- QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
- if (!dtp->isQmlDefined())
- delete dtp;
- else
- dtp->setValid(false);
- }
- _touchPoints.clear();
- }
-}
-
-void QQuickMultiPointTouchArea::mouseUngrabEvent()
-{
- ungrab();
-}
-
-void QQuickMultiPointTouchArea::touchUngrabEvent()
-{
- ungrab();
-}
-
-bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
-{
- QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
-
- QQuickCanvas *c = canvas();
- QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
- bool stealThisEvent = _stealMouse;
- if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
- QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers());
- mouseEvent.setAccepted(false);
-
- switch (mouseEvent.type()) {
- case QEvent::MouseMove:
- mouseMoveEvent(&mouseEvent);
- break;
- case QEvent::MouseButtonPress:
- mousePressEvent(&mouseEvent);
- break;
- case QEvent::MouseButtonRelease:
- mouseReleaseEvent(&mouseEvent);
- break;
- default:
- break;
- }
- grabber = c->mouseGrabberItem();
- if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
- grabMouse();
-
- return stealThisEvent;
- }
- if (event->type() == QEvent::MouseButtonRelease) {
- _stealMouse = false;
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
- }
- return false;
-}
-
-bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *i, QEvent *event)
-{
- if (!isEnabled() || !isVisible())
- return QQuickItem::childMouseEventFilter(i, event);
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- return sendMouseEvent(static_cast<QMouseEvent *>(event));
- break;
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- if (!shouldFilter(event))
- return false;
- updateTouchData(event);
- return _stealMouse;
- case QEvent::TouchEnd: {
- if (!shouldFilter(event))
- return false;
- updateTouchData(event);
- //TODO: verify this behavior
- _stealMouse = false;
- setKeepMouseGrab(false);
- QQuickCanvas *c = canvas();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepTouchGrab(false);
- ungrabTouchPoints();
- }
- break;
- default:
- break;
- }
- return QQuickItem::childMouseEventFilter(i, event);
-}
-
-bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
-{
- QQuickCanvas *c = canvas();
- QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
- bool disabledItem = grabber && !grabber->isEnabled();
- bool stealThisEvent = _stealMouse;
- bool contains = false;
- if (!stealThisEvent) {
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease: {
- QMouseEvent *me = static_cast<QMouseEvent*>(event);
- QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
- contains = myRect.contains(me->windowPos());
- }
- break;
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd: {
- QTouchEvent *te = static_cast<QTouchEvent*>(event);
- QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
- foreach (const QTouchEvent::TouchPoint &point, te->touchPoints()) {
- if (myRect.contains(point.scenePos())) {
- contains = true;
- break;
- }
- }
- }
- break;
- default:
- break;
- }
- }
- if ((stealThisEvent || contains) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
- return true;
- }
- ungrab();
- return false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickmultipointtoucharea_p.h b/src/declarative/items/qquickmultipointtoucharea_p.h
deleted file mode 100644
index dac70453c5..0000000000
--- a/src/declarative/items/qquickmultipointtoucharea_p.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKMULTIPOINTTOUCHAREA_H
-#define QQUICKMULTIPOINTTOUCHAREA_H
-
-#include "qquickitem.h"
-#include "qevent.h"
-
-#include <QMap>
-#include <QList>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qstylehints.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickMultiPointTouchArea;
-class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged)
- Q_PROPERTY(int pointId READ pointId NOTIFY pointIdChanged)
- Q_PROPERTY(qreal x READ x NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y NOTIFY yChanged)
- Q_PROPERTY(qreal pressure READ pressure NOTIFY pressureChanged)
- Q_PROPERTY(QRectF area READ area NOTIFY areaChanged)
-
- Q_PROPERTY(qreal startX READ startX NOTIFY startXChanged)
- Q_PROPERTY(qreal startY READ startY NOTIFY startYChanged)
- Q_PROPERTY(qreal previousX READ previousX NOTIFY previousXChanged)
- Q_PROPERTY(qreal previousY READ previousY NOTIFY previousYChanged)
- Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged)
- Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged)
-
-public:
- QQuickTouchPoint(bool qmlDefined = true)
- : _id(0),
- _x(0.0), _y(0.0),
- _pressure(0.0),
- _qmlDefined(qmlDefined),
- _valid(!qmlDefined),
- _previousX(0.0), _previousY(0.0),
- _sceneX(0.0), _sceneY(0.0)
- {}
-
- int pointId() const { return _id; }
- void setPointId(int id);
-
- qreal x() const { return _x; }
- void setX(qreal x);
-
- qreal y() const { return _y; }
- void setY(qreal y);
-
- qreal pressure() const { return _pressure; }
- void setPressure(qreal pressure);
-
- QRectF area() const { return _area; }
- void setArea(const QRectF &area);
-
- bool isQmlDefined() { return _qmlDefined; }
-
- bool isValid() { return _valid; }
- void setValid(bool valid);
-
- qreal startX() const { return _startX; }
- void setStartX(qreal startX);
-
- qreal startY() const { return _startY; }
- void setStartY(qreal startY);
-
- qreal previousX() const { return _previousX; }
- void setPreviousX(qreal previousX);
-
- qreal previousY() const { return _previousY; }
- void setPreviousY(qreal previousY);
-
- qreal sceneX() const { return _sceneX; }
- void setSceneX(qreal sceneX);
-
- qreal sceneY() const { return _sceneY; }
- void setSceneY(qreal sceneY);
-
-
-Q_SIGNALS:
- void pointIdChanged();
- void xChanged();
- void yChanged();
- void pressureChanged();
- void areaChanged();
- void validityChanged();
- void startXChanged();
- void startYChanged();
- void previousXChanged();
- void previousYChanged();
- void sceneXChanged();
- void sceneYChanged();
-
-private:
- friend class QQuickMultiPointTouchArea;
- int _id;
- qreal _x;
- qreal _y;
- qreal _pressure;
- QRectF _area;
- bool _qmlDefined;
- bool _valid;
- qreal _startX;
- qreal _startY;
- qreal _previousX;
- qreal _previousY;
- qreal _sceneX;
- qreal _sceneY;
-};
-
-class QQuickGrabGestureEvent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QDeclarativeListProperty<QObject> touchPoints READ touchPoints)
- Q_PROPERTY(qreal dragThreshold READ dragThreshold)
-public:
- QQuickGrabGestureEvent() : _grab(false), _dragThreshold(qApp->styleHints()->startDragDistance()) {}
-
- Q_INVOKABLE void grab() { _grab = true; }
- bool wantsGrab() const { return _grab; }
-
- QDeclarativeListProperty<QObject> touchPoints() {
- return QDeclarativeListProperty<QObject>(this, _touchPoints);
- }
- qreal dragThreshold() const { return _dragThreshold; }
-
-private:
- friend class QQuickMultiPointTouchArea;
- bool _grab;
- qreal _dragThreshold;
- QList<QObject*> _touchPoints;
-};
-
-class Q_AUTOTEST_EXPORT QQuickMultiPointTouchArea : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(QDeclarativeListProperty<QQuickTouchPoint> touchPoints READ touchPoints)
- Q_PROPERTY(int minimumTouchPoints READ minimumTouchPoints WRITE setMinimumTouchPoints NOTIFY minimumTouchPointsChanged)
- Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints WRITE setMaximumTouchPoints NOTIFY maximumTouchPointsChanged)
-
-public:
- QQuickMultiPointTouchArea(QQuickItem *parent=0);
- ~QQuickMultiPointTouchArea();
-
- int minimumTouchPoints() const;
- void setMinimumTouchPoints(int num);
- int maximumTouchPoints() const;
- void setMaximumTouchPoints(int num);
-
- QDeclarativeListProperty<QQuickTouchPoint> touchPoints() {
- return QDeclarativeListProperty<QQuickTouchPoint>(this, 0, QQuickMultiPointTouchArea::touchPoint_append, QQuickMultiPointTouchArea::touchPoint_count, QQuickMultiPointTouchArea::touchPoint_at, 0);
- }
-
- static void touchPoint_append(QDeclarativeListProperty<QQuickTouchPoint> *list, QQuickTouchPoint* touch) {
- QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
- q->addTouchPrototype(touch);
- }
-
- static int touchPoint_count(QDeclarativeListProperty<QQuickTouchPoint> *list) {
- QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
- return q->_touchPrototypes.count();
- }
-
- static QQuickTouchPoint* touchPoint_at(QDeclarativeListProperty<QQuickTouchPoint> *list, int index) {
- QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
- return q->_touchPrototypes[index];
- }
-
-Q_SIGNALS:
- void touchPointsPressed(const QList<QObject*> &touchPoints);
- void touchPointsUpdated(const QList<QObject*> &touchPoints);
- void touchPointsReleased(const QList<QObject*> &touchPoints);
- void touchPointsCanceled(const QList<QObject*> &touchPoints);
- void gestureStarted(QQuickGrabGestureEvent *gesture);
- void touchUpdated(const QList<QObject*> &touchPoints);
- void minimumTouchPointsChanged();
- void maximumTouchPointsChanged();
-
-protected:
- void touchEvent(QTouchEvent *);
- bool childMouseEventFilter(QQuickItem *i, QEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseUngrabEvent();
- void touchUngrabEvent();
-
- void addTouchPrototype(QQuickTouchPoint* prototype);
- void addTouchPoint(const QTouchEvent::TouchPoint *p);
- void clearTouchLists();
-
- void updateTouchPoint(QQuickTouchPoint*, const QTouchEvent::TouchPoint*);
- void updateTouchData(QEvent*);
-
- bool sendMouseEvent(QMouseEvent *event);
- bool shouldFilter(QEvent *event);
- void grabGesture();
-
-private:
- void ungrab();
- QMap<int,QQuickTouchPoint*> _touchPrototypes; //TouchPoints defined in QML
- QMap<int,QObject*> _touchPoints; //All current touch points
- QList<QObject*> _releasedTouchPoints;
- QList<QObject*> _pressedTouchPoints;
- QList<QObject*> _movedTouchPoints;
- int _minimumTouchPoints;
- int _maximumTouchPoints;
- bool _stealMouse;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickTouchPoint)
-QML_DECLARE_TYPE(QQuickGrabGestureEvent)
-QML_DECLARE_TYPE(QQuickMultiPointTouchArea)
-
-QT_END_HEADER
-
-#endif // QQUICKMULTIPOINTTOUCHAREA_H
diff --git a/src/declarative/items/qquickninepatchnode_p.h b/src/declarative/items/qquickninepatchnode_p.h
deleted file mode 100644
index cdb0fd8e70..0000000000
--- a/src/declarative/items/qquickninepatchnode_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKNINEPATCHNODE_H
-#define QQUICKNINEPATCHNODE_H
-
-#include "qsgnode.h"
-#include "qsgtexturematerial.h"
-#include "qquickborderimage_p.h"
-
-class TextureReference;
-
-class QQuickNinePatchNode : public QSGGeometryNode
-{
-public:
- QQuickNinePatchNode();
-
- void setTexture(QSGTexture *texture);
- QSGTexture *texture() const;
-
- void setRect(const QRectF &rect);
- QRectF rect() const { return m_targetRect; }
-
- void setInnerRect(const QRectF &rect);
- QRectF innerRect() const { return m_innerRect; }
-
- void setFiltering(QSGTexture::Filtering filtering);
- QSGTexture::Filtering filtering() const;
-
- void setHorzontalTileMode(QQuickBorderImage::TileMode mode);
- QQuickBorderImage::TileMode horizontalTileMode() const {
- return (QQuickBorderImage::TileMode) m_horizontalTileMode;
- }
-
- void setVerticalTileMode(QQuickBorderImage::TileMode mode);
- QQuickBorderImage::TileMode verticalTileMode() const {
- return (QQuickBorderImage::TileMode) m_verticalTileMode;
- }
-
- void setMirror(bool m);
- bool mirror() const { return m_mirror; }
-
- void update();
-
-private:
- void fillRow(QSGGeometry::TexturedPoint2D *&v, float y, float ty, int xChunkCount, float xChunkSize, const QRectF &tsr, const QSize &ts);
- QRectF m_targetRect;
- QRectF m_innerRect;
- QSGOpaqueTextureMaterial m_material;
- QSGTextureMaterial m_materialO;
- QSGGeometry m_geometry;
-
- uint m_horizontalTileMode : 2;
- uint m_verticalTileMode : 2;
-
- uint m_dirtyGeometry : 1;
- uint m_mirror : 1;
-};
-
-#endif // QQUICKNINEPATCHNODE_H
diff --git a/src/declarative/items/qquickpainteditem.cpp b/src/declarative/items/qquickpainteditem.cpp
deleted file mode 100644
index 4d96da2e1a..0000000000
--- a/src/declarative/items/qquickpainteditem.cpp
+++ /dev/null
@@ -1,528 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickpainteditem.h"
-#include <private/qquickpainteditem_p.h>
-
-#include <private/qsgpainternode_p.h>
-#include <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-#include <qmath.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QQuickPaintedItem
- \brief The QQuickPaintedItem class provides a way to use the QPainter API in the
- QML Scene Graph.
-
- \inmodule QtDeclarative
-
- The QQuickPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
- It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
- onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
- When the render target is a QImage, QPainter first renders into the image then
- the content is uploaded to the texture.
- When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
- Call update() to trigger a repaint.
-
- To enable QPainter to do anti-aliased rendering, use setAntialiasing().
-
- QQuickPaintedItem is meant to make it easier to port old code that is using the
- QPainter API to the QML Scene Graph API and it should be used only for that purpose.
-
- To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
- start by implementing its only pure virtual public function: paint(), which implements
- the actual painting. To get the size of the area painted by the item, use
- contentsBoundingRect().
-*/
-
-/*!
- \enum QQuickPaintedItem::RenderTarget
-
- This enum describes QQuickPaintedItem's render targets. The render target is the
- surface QPainter paints onto before the item is rendered on screen.
-
- \value Image The default; QPainter paints into a QImage using the raster paint engine.
- The image's content needs to be uploaded to graphics memory afterward, this operation
- can potentially be slow if the item is large. This render target allows high quality
- anti-aliasing and fast item resizing.
-
- \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
- paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
- quality is not as good as if using an image. This render target allows faster rendering
- in some cases, but you should avoid using it if the item is resized often.
-
- \value InvertedYFramebufferObject Exactly as for FramebufferObject above, except once
- the painting is done, prior to rendering the painted image is flipped about the
- x-axis so that the top-most pixels are now at the bottom. Since this is done with the
- OpenGL texture coordinates it is a much faster way to achieve this effect than using a
- painter transform.
-
- \sa setRenderTarget()
-*/
-
-/*!
- \enum QQuickPaintedItem::PerformanceHint
-
- This enum describes flags that you can enable to improve rendering
- performance in QQuickPaintedItem. By default, none of these flags are set.
-
- \value FastFBOResizing If your item gets resized often and you are using the
- QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
- item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
- is a costly operation, by enabling this property the Framebuffer Object will use a texture
- larger than the actual size of the item to avoid as much as possible resizing it.
-*/
-
-/*!
- \internal
-*/
-QQuickPaintedItemPrivate::QQuickPaintedItemPrivate()
- : QQuickItemPrivate()
- , contentsScale(1.0)
- , fillColor(Qt::transparent)
- , renderTarget(QQuickPaintedItem::Image)
- , performanceHints(0)
- , opaquePainting(false)
- , antialiasing(false)
- , mipmap(false)
-{
-}
-
-/*!
- Constructs a QQuickPaintedItem with the given \a parent item.
- */
-QQuickPaintedItem::QQuickPaintedItem(QQuickItem *parent)
- : QQuickItem(*(new QQuickPaintedItemPrivate), parent)
-{
- setFlag(ItemHasContents);
-}
-
-/*!
- \internal
-*/
-QQuickPaintedItem::QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent)
- : QQuickItem(dd, parent)
-{
- setFlag(ItemHasContents);
-}
-
-/*!
- Destroys the QQuickPaintedItem.
-*/
-QQuickPaintedItem::~QQuickPaintedItem()
-{
-}
-
-/*!
- Schedules a redraw of the area covered by \a rect in this item. You can call this function
- whenever your item needs to be redrawn, such as if it changes appearance or size.
-
- This function does not cause an immediate paint; instead it schedules a paint request that
- is processed by the QML Scene Graph when the next frame is rendered. The item will only be
- redrawn if it is visible.
-
- Note that calling this function will trigger a repaint of the whole scene.
-
- \sa paint()
-*/
-void QQuickPaintedItem::update(const QRect &rect)
-{
- Q_D(QQuickPaintedItem);
-
- if (rect.isNull() && !d->dirtyRect.isNull())
- d->dirtyRect = contentsBoundingRect().toAlignedRect();
- else
- d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
- QQuickItem::update();
-}
-
-/*!
- Returns true if this item is opaque; otherwise, false is returned.
-
- By default, painted items are not opaque.
-
- \sa setOpaquePainting()
-*/
-bool QQuickPaintedItem::opaquePainting() const
-{
- Q_D(const QQuickPaintedItem);
- return d->opaquePainting;
-}
-
-/*!
- If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
-
- Opaque items are not blended with the rest of the scene, you should set this to true
- if the content of the item is opaque to speed up rendering.
-
- By default, painted items are not opaque.
-
- \sa opaquePainting()
-*/
-void QQuickPaintedItem::setOpaquePainting(bool opaque)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->opaquePainting == opaque)
- return;
-
- d->opaquePainting = opaque;
- QQuickItem::update();
-}
-
-/*!
- Returns true if antialiased painting is enabled; otherwise, false is returned.
-
- By default, antialiasing is not enabled.
-
- \sa setAntialiasing()
-*/
-bool QQuickPaintedItem::antialiasing() const
-{
- Q_D(const QQuickPaintedItem);
- return d->antialiasing;
-}
-
-/*!
- If \a enable is true, antialiased painting is enabled.
-
- By default, antialiasing is not enabled.
-
- \sa antialiasing()
-*/
-void QQuickPaintedItem::setAntialiasing(bool enable)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->antialiasing == enable)
- return;
-
- d->antialiasing = enable;
- update();
-}
-
-/*!
- Returns true if mipmaps are enabled; otherwise, false is returned.
-
- By default, mipmapping is not enabled.
-
- \sa setMipmap()
-*/
-bool QQuickPaintedItem::mipmap() const
-{
- Q_D(const QQuickPaintedItem);
- return d->mipmap;
-}
-
-/*!
- If \a enable is true, mipmapping is enabled on the associated texture.
-
- Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
- scaled down.
-
- By default, mipmapping is not enabled.
-
- \sa mipmap()
-*/
-void QQuickPaintedItem::setMipmap(bool enable)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->mipmap == enable)
- return;
-
- d->mipmap = enable;
- update();
-}
-
-/*!
- Returns the performance hints.
-
- By default, no performance hint is enabled/
-
- \sa setPerformanceHint(), setPerformanceHints()
-*/
-QQuickPaintedItem::PerformanceHints QQuickPaintedItem::performanceHints() const
-{
- Q_D(const QQuickPaintedItem);
- return d->performanceHints;
-}
-
-/*!
- Sets the given performance \a hint on the item if \a enabled is true;
- otherwise clears the performance hint.
-
- By default, no performance hint is enabled/
-
- \sa setPerformanceHints(), performanceHints()
-*/
-void QQuickPaintedItem::setPerformanceHint(QQuickPaintedItem::PerformanceHint hint, bool enabled)
-{
- Q_D(QQuickPaintedItem);
- PerformanceHints oldHints = d->performanceHints;
- if (enabled)
- d->performanceHints |= hint;
- else
- d->performanceHints &= ~hint;
- if (oldHints != d->performanceHints)
- update();
-}
-
-/*!
- Sets the performance hints to \a hints
-
- By default, no performance hint is enabled/
-
- \sa setPerformanceHint(), performanceHints()
-*/
-void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints hints)
-{
- Q_D(QQuickPaintedItem);
- if (d->performanceHints == hints)
- return;
- d->performanceHints = hints;
- update();
-}
-
-/*!
- This function returns the outer bounds of the item as a rectangle; all painting must be
- restricted to inside an item's bounding rect.
-
- If the contents size has not been set it reflects the size of the item; otherwise
- it reflects the contents size scaled by the contents scale.
-
- Use this function to know the area painted by the item.
-
- \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
-*/
-QRectF QQuickPaintedItem::contentsBoundingRect() const
-{
- Q_D(const QQuickPaintedItem);
-
- qreal w = d->width;
- QSizeF sz = d->contentsSize * d->contentsScale;
- if (w < sz.width())
- w = sz.width();
- qreal h = d->height;
- if (h < sz.height())
- h = sz.height();
-
- return QRectF(0, 0, w, h);
-}
-
-/*!
- \property QQuickPaintedItem::contentsSize
- \brief The size of the contents
-
- The contents size is the size of the item in regards to how it is painted
- using the paint() function. This is distinct from the size of the
- item in regards to height() and width().
-*/
-QSize QQuickPaintedItem::contentsSize() const
-{
- Q_D(const QQuickPaintedItem);
- return d->contentsSize;
-}
-
-void QQuickPaintedItem::setContentsSize(const QSize &size)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->contentsSize == size)
- return;
-
- d->contentsSize = size;
- update();
-}
-
-/*!
- This convenience function is equivalent to calling setContentsSize(QSize()).
-*/
-void QQuickPaintedItem::resetContentsSize()
-{
- setContentsSize(QSize());
-}
-
-/*!
- \property QQuickPaintedItem::contentsScale
- \brief The scale of the contents
-
- All painting happening in paint() is scaled by the contents scale. This is distinct
- from the scale of the item in regards to scale().
-
- The default value is 1.
-*/
-qreal QQuickPaintedItem::contentsScale() const
-{
- Q_D(const QQuickPaintedItem);
- return d->contentsScale;
-}
-
-void QQuickPaintedItem::setContentsScale(qreal scale)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->contentsScale == scale)
- return;
-
- d->contentsScale = scale;
- update();
-}
-
-/*!
- \property QQuickPaintedItem::fillColor
- \brief The item's background fill color.
-
- By default, the fill color is set to Qt::transparent.
-*/
-QColor QQuickPaintedItem::fillColor() const
-{
- Q_D(const QQuickPaintedItem);
- return d->fillColor;
-}
-
-void QQuickPaintedItem::setFillColor(const QColor &c)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->fillColor == c)
- return;
-
- d->fillColor = c;
- update();
-
- emit fillColorChanged();
-}
-
-/*!
- \property QQuickPaintedItem::renderTarget
- \brief The item's render target.
-
- This property defines which render target the QPainter renders into, it can be either
- QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject.
-
- Each has certain benefits, typically performance versus quality. Using a framebuffer
- object avoids a costly upload of the image contents to the texture in graphics memory,
- while using an image enables high quality anti-aliasing.
-
- \warning Resizing a framebuffer object is a costly operation, avoid using
- the QQuickPaintedItem::FramebufferObject render target if the item gets resized often.
-
- By default, the render target is QQuickPaintedItem::Image.
-*/
-QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const
-{
- Q_D(const QQuickPaintedItem);
- return d->renderTarget;
-}
-
-void QQuickPaintedItem::setRenderTarget(RenderTarget target)
-{
- Q_D(QQuickPaintedItem);
-
- if (d->renderTarget == target)
- return;
-
- d->renderTarget = target;
- update();
-
- emit renderTargetChanged();
-}
-
-/*!
- \fn virtual void QQuickPaintedItem::paint(QPainter *painter) = 0
-
- This function, which is usually called by the QML Scene Graph, paints the
- contents of an item in local coordinates.
-
- The function is called after the item has been filled with the fillColor.
-
- Reimplement this function in a QQuickPaintedItem subclass to provide the
- item's painting implementation, using \a painter.
-
- \note The QML Scene Graph uses two separate threads, the main thread does things such as
- processing events or updating animations while a second thread does the actual OpenGL rendering.
- As a consequence, paint() is not called from the main GUI thread but from the GL enabled
- renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
- therefore thread-safe.
-*/
-
-/*!
- This function is called when the Scene Graph node associated to the item needs to
- be updated.
-*/
-QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
-{
- Q_UNUSED(data);
- Q_D(QQuickPaintedItem);
-
- if (width() <= 0 || height() <= 0) {
- delete oldNode;
- return 0;
- }
-
- QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
- if (!node)
- node = new QSGPainterNode(this);
-
- QRectF br = contentsBoundingRect();
-
- node->setPreferredRenderTarget(d->renderTarget);
- node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
- node->setSize(QSize(qRound(br.width()), qRound(br.height())));
- node->setSmoothPainting(d->antialiasing);
- node->setLinearFiltering(d->smooth);
- node->setMipmapping(d->mipmap);
- node->setOpaquePainting(d->opaquePainting);
- node->setFillColor(d->fillColor);
- node->setContentsScale(d->contentsScale);
- node->setDirty(d->dirtyRect);
- node->update();
-
- d->dirtyRect = QRect();
-
- return node;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickpainteditem.h b/src/declarative/items/qquickpainteditem.h
deleted file mode 100644
index b2da9e6c7a..0000000000
--- a/src/declarative/items/qquickpainteditem.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKPAINTEDITEM_P_H
-#define QQUICKPAINTEDITEM_P_H
-
-#include <qquickitem.h>
-#include <QtGui/qcolor.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QQuickPaintedItemPrivate;
-class Q_DECLARATIVE_EXPORT QQuickPaintedItem : public QQuickItem
-{
- Q_OBJECT
- Q_ENUMS(RenderTarget)
-
- Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
- Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
- Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
- Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
-public:
- QQuickPaintedItem(QQuickItem *parent = 0);
- virtual ~QQuickPaintedItem();
-
- enum RenderTarget {
- Image,
- FramebufferObject,
- InvertedYFramebufferObject
- };
-
- enum PerformanceHint {
- FastFBOResizing = 0x1
- };
- Q_DECLARE_FLAGS(PerformanceHints, PerformanceHint)
-
- void update(const QRect &rect = QRect());
-
- bool opaquePainting() const;
- void setOpaquePainting(bool opaque);
-
- bool antialiasing() const;
- void setAntialiasing(bool enable);
-
- bool mipmap() const;
- void setMipmap(bool enable);
-
- PerformanceHints performanceHints() const;
- void setPerformanceHint(PerformanceHint hint, bool enabled = true);
- void setPerformanceHints(PerformanceHints hints);
-
- QRectF contentsBoundingRect() const;
-
- QSize contentsSize() const;
- void setContentsSize(const QSize &);
- void resetContentsSize();
-
- qreal contentsScale() const;
- void setContentsScale(qreal);
-
- QColor fillColor() const;
- void setFillColor(const QColor&);
-
- RenderTarget renderTarget() const;
- void setRenderTarget(RenderTarget target);
-
- virtual void paint(QPainter *painter) = 0;
-
-Q_SIGNALS:
- void fillColorChanged();
- void contentsSizeChanged();
- void contentsScaleChanged();
- void renderTargetChanged();
-
-protected:
- QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-private:
- Q_DISABLE_COPY(QQuickPaintedItem)
- Q_DECLARE_PRIVATE(QQuickPaintedItem)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPaintedItem::PerformanceHints)
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKPAINTEDITEM_P_H
diff --git a/src/declarative/items/qquickpathview.cpp b/src/declarative/items/qquickpathview.cpp
deleted file mode 100644
index f262562edf..0000000000
--- a/src/declarative/items/qquickpathview.cpp
+++ /dev/null
@@ -1,1781 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickpathview_p.h"
-#include "qquickpathview_p_p.h"
-#include "qquickcanvas.h"
-
-#include <private/qdeclarativestate_p.h>
-#include <private/qdeclarativeopenmetaobject_p.h>
-#include <private/qlistmodelinterface_p.h>
-#include <private/qdeclarativechangeset_p.h>
-
-#include <QtGui/qevent.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qstylehints.h>
-#include <QtCore/qmath.h>
-#include <math.h>
-
-QT_BEGIN_NAMESPACE
-
-inline qreal qmlMod(qreal x, qreal y)
-{
-#ifdef QT_USE_MATH_H_FLOATS
- if (sizeof(qreal) == sizeof(float))
- return fmodf(float(x), float(y));
- else
-#endif
- return fmod(x, y);
-}
-
-static QDeclarativeOpenMetaObjectType *qPathViewAttachedType = 0;
-
-QQuickPathViewAttached::QQuickPathViewAttached(QObject *parent)
-: QObject(parent), m_percent(-1), m_view(0), m_onPath(false), m_isCurrent(false)
-{
- if (qPathViewAttachedType) {
- m_metaobject = new QDeclarativeOpenMetaObject(this, qPathViewAttachedType);
- m_metaobject->setCached(true);
- } else {
- m_metaobject = new QDeclarativeOpenMetaObject(this);
- }
-}
-
-QQuickPathViewAttached::~QQuickPathViewAttached()
-{
-}
-
-QVariant QQuickPathViewAttached::value(const QByteArray &name) const
-{
- return m_metaobject->value(name);
-}
-void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &val)
-{
- m_metaobject->setValue(name, val);
-}
-
-
-void QQuickPathViewPrivate::init()
-{
- Q_Q(QQuickPathView);
- offset = 0;
- q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setFlag(QQuickItem::ItemIsFocusScope);
- q->setFiltersChildMouseEvents(true);
- FAST_CONNECT(&tl, SIGNAL(updated()), q, SLOT(ticked()))
- lastPosTime.invalidate();
- FAST_CONNECT(&tl, SIGNAL(completed()), q, SLOT(movementEnding()))
-}
-
-QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool onPath)
-{
- Q_Q(QQuickPathView);
- requestedIndex = modelIndex;
- requestedOnPath = onPath;
- requestedZ = z;
- inRequest = true;
- QQuickItem *item = model->item(modelIndex, false);
- if (item) {
- QDeclarative_setParent_noEvent(item, q);
- item->setParentItem(q);
- requestedIndex = -1;
- qPathViewAttachedType = attType;
- QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
- qPathViewAttachedType = 0;
- if (att)
- att->setOnPath(onPath);
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- }
- inRequest = false;
- return item;
-}
-
-void QQuickPathView::createdItem(int index, QQuickItem *item)
-{
- Q_D(QQuickPathView);
- if (d->requestedIndex != index) {
- qPathViewAttachedType = d->attachedType();
- QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
- qPathViewAttachedType = 0;
- if (att) {
- att->m_view = this;
- att->setOnPath(false);
- }
- item->setParentItem(this);
- QDeclarative_setParent_noEvent(item, this);
- d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
- } else {
- d->requestedIndex = -1;
- if (!d->inRequest)
- refill();
- }
-}
-
-void QQuickPathView::initItem(int index, QQuickItem *item)
-{
- Q_D(QQuickPathView);
- if (d->requestedIndex == index) {
- item->setParentItem(this);
- qPathViewAttachedType = d->attachedType();
- QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
- qPathViewAttachedType = 0;
- if (att) {
- att->m_view = this;
- qreal percent = d->positionOfIndex(index);
- foreach (const QString &attr, d->path->attributes())
- att->setValue(attr.toUtf8(), d->path->attributeAt(attr, percent));
- item->setZ(d->requestedZ);
- if (att)
- att->setOnPath(d->requestedOnPath);
- }
- }
-}
-
-void QQuickPathViewPrivate::releaseItem(QQuickItem *item)
-{
- if (!item || !model)
- return;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
- if (model->release(item) == 0) {
- // item was not destroyed, and we no longer reference it.
- if (QQuickPathViewAttached *att = attached(item))
- att->setOnPath(false);
- }
-}
-
-QQuickPathViewAttached *QQuickPathViewPrivate::attached(QQuickItem *item)
-{
- return static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item, false));
-}
-
-QDeclarativeOpenMetaObjectType *QQuickPathViewPrivate::attachedType()
-{
- Q_Q(QQuickPathView);
- if (!attType) {
- // pre-create one metatype to share with all attached objects
- attType = new QDeclarativeOpenMetaObjectType(&QQuickPathViewAttached::staticMetaObject, qmlEngine(q));
- foreach (const QString &attr, path->attributes())
- attType->createProperty(attr.toUtf8());
- }
-
- return attType;
-}
-
-void QQuickPathViewPrivate::clear()
-{
- if (currentItem) {
- releaseItem(currentItem);
- currentItem = 0;
- }
- for (int i=0; i<items.count(); i++){
- QQuickItem *p = items[i];
- releaseItem(p);
- }
- items.clear();
-}
-
-void QQuickPathViewPrivate::updateMappedRange()
-{
- if (model && pathItems != -1 && pathItems < modelCount)
- mappedRange = qreal(pathItems)/modelCount;
- else
- mappedRange = 1.0;
-}
-
-qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
-{
- qreal pos = -1.0;
-
- if (model && index >= 0 && index < modelCount) {
- qreal start = 0.0;
- if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange)
- start = highlightRangeStart;
- qreal globalPos = index + offset;
- globalPos = qmlMod(globalPos, qreal(modelCount)) / modelCount;
- if (pathItems != -1 && pathItems < modelCount) {
- globalPos += start * mappedRange;
- globalPos = qmlMod(globalPos, 1.0);
- if (globalPos < mappedRange)
- pos = globalPos / mappedRange;
- } else {
- pos = qmlMod(globalPos + start, 1.0);
- }
- }
-
- return pos;
-}
-
-void QQuickPathViewPrivate::createHighlight()
-{
- Q_Q(QQuickPathView);
- if (!q->isComponentComplete())
- return;
-
- bool changed = false;
- if (highlightItem) {
- highlightItem->setParentItem(0);
- highlightItem->deleteLater();
- highlightItem = 0;
- changed = true;
- }
-
- QQuickItem *item = 0;
- if (highlightComponent) {
- QDeclarativeContext *creationContext = highlightComponent->creationContext();
- QDeclarativeContext *highlightContext = new QDeclarativeContext(
- creationContext ? creationContext : qmlContext(q));
- QObject *nobj = highlightComponent->create(highlightContext);
- if (nobj) {
- QDeclarative_setParent_noEvent(highlightContext, nobj);
- item = qobject_cast<QQuickItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete highlightContext;
- }
- } else {
- item = new QQuickItem;
- }
- if (item) {
- QDeclarative_setParent_noEvent(item, q);
- item->setParentItem(q);
- highlightItem = item;
- changed = true;
- }
- if (changed)
- emit q->highlightItemChanged();
-}
-
-void QQuickPathViewPrivate::updateHighlight()
-{
- Q_Q(QQuickPathView);
- if (!q->isComponentComplete() || !isValid())
- return;
- if (highlightItem) {
- if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- updateItem(highlightItem, highlightRangeStart);
- } else {
- qreal target = currentIndex;
-
- offsetAdj = 0.0;
- tl.reset(moveHighlight);
- moveHighlight.setValue(highlightPosition);
-
- const int duration = highlightMoveDuration;
-
- if (target - highlightPosition > modelCount/2) {
- highlightUp = false;
- qreal distance = modelCount - target + highlightPosition;
- tl.move(moveHighlight, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
- tl.set(moveHighlight, modelCount-0.01);
- tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * (modelCount-target) / distance));
- } else if (target - highlightPosition <= -modelCount/2) {
- highlightUp = true;
- qreal distance = modelCount - highlightPosition + target;
- tl.move(moveHighlight, modelCount-0.01, QEasingCurve(QEasingCurve::InQuad), int(duration * (modelCount-highlightPosition) / distance));
- tl.set(moveHighlight, 0.0);
- tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * target / distance));
- } else {
- highlightUp = highlightPosition - target < 0;
- tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::InOutQuad), duration);
- }
- }
- }
-}
-
-void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
-{
- if (pos != highlightPosition) {
- qreal start = 0.0;
- qreal end = 1.0;
- if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange) {
- start = highlightRangeStart;
- end = highlightRangeEnd;
- }
-
- qreal range = qreal(modelCount);
- // calc normalized position of highlight relative to offset
- qreal relativeHighlight = qmlMod(pos + offset, range) / range;
-
- if (!highlightUp && relativeHighlight > end * mappedRange) {
- qreal diff = 1.0 - relativeHighlight;
- setOffset(offset + diff * range);
- } else if (highlightUp && relativeHighlight >= (end - start) * mappedRange) {
- qreal diff = relativeHighlight - (end - start) * mappedRange;
- setOffset(offset - diff * range - 0.00001);
- }
-
- highlightPosition = pos;
- qreal pathPos = positionOfIndex(pos);
- updateItem(highlightItem, pathPos);
- if (QQuickPathViewAttached *att = attached(highlightItem))
- att->setOnPath(pathPos != -1.0);
- }
-}
-
-void QQuickPathView::pathUpdated()
-{
- Q_D(QQuickPathView);
- QList<QQuickItem*>::iterator it = d->items.begin();
- while (it != d->items.end()) {
- QQuickItem *item = *it;
- if (QQuickPathViewAttached *att = d->attached(item))
- att->m_percent = -1;
- ++it;
- }
- refill();
-}
-
-void QQuickPathViewPrivate::updateItem(QQuickItem *item, qreal percent)
-{
- if (QQuickPathViewAttached *att = attached(item)) {
- if (qFuzzyCompare(att->m_percent, percent))
- return;
- att->m_percent = percent;
- foreach (const QString &attr, path->attributes())
- att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
- }
- QPointF pf = path->pointAt(percent);
- item->setX(qRound(pf.x() - item->width()/2));
- item->setY(qRound(pf.y() - item->height()/2));
-}
-
-void QQuickPathViewPrivate::regenerate()
-{
- Q_Q(QQuickPathView);
- if (!q->isComponentComplete())
- return;
-
- clear();
-
- if (!isValid())
- return;
-
- firstIndex = -1;
- updateMappedRange();
- q->refill();
-}
-
-/*!
- \qmlclass PathView QQuickPathView
- \inqmlmodule QtQuick 2
- \ingroup qml-view-elements
- \brief The PathView element lays out model-provided items on a path.
- \inherits Item
-
- A PathView displays data from models created from built-in QML elements like ListModel
- and XmlListModel, or custom model classes defined in C++ that inherit from
- QAbstractListModel.
-
- The view has a \l model, which defines the data to be displayed, and
- a \l delegate, which defines how the data should be displayed.
- The \l delegate is instantiated for each item on the \l path.
- The items may be flicked to move them along the path.
-
- For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
-
- \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
-
- This data can be represented as a PathView, like this:
-
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
-
- \image pathview.gif
-
- (Note the above example uses PathAttribute to scale and modify the
- opacity of the items as they rotate. This additional code can be seen in the
- PathAttribute documentation.)
-
- PathView does not automatically handle keyboard navigation. This is because
- the keys to use for navigation will depend upon the shape of the path. Navigation
- can be added quite simply by setting \c focus to \c true and calling
- \l decrementCurrentIndex() or \l incrementCurrentIndex(), for example to navigate
- using the left and right arrow keys:
-
- \qml
- PathView {
- // ...
- focus: true
- Keys.onLeftPressed: decrementCurrentIndex()
- Keys.onRightPressed: incrementCurrentIndex()
- }
- \endqml
-
- The path view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
-
- Delegates are instantiated as needed and may be destroyed at any time.
- State should \e never be stored in a delegate.
-
- PathView attaches a number of properties to the root item of the delegate, for example
- \c {PathView.isCurrentItem}. In the following example, the root delegate item can access
- this attached property directly as \c PathView.isCurrentItem, while the child
- \c nameText object must refer to this property as \c wrapper.PathView.isCurrentItem.
-
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
-
- \bold Note that views do not enable \e clip automatically. If the view
- is not clipped by another item or the screen, it will be necessary
- to set \e {clip: true} in order to have the out of view items clipped
- nicely.
-
- \sa Path, {declarative/modelviews/pathview}{PathView example}
-*/
-
-QQuickPathView::QQuickPathView(QQuickItem *parent)
- : QQuickItem(*(new QQuickPathViewPrivate), parent)
-{
- Q_D(QQuickPathView);
- d->init();
-}
-
-QQuickPathView::~QQuickPathView()
-{
- Q_D(QQuickPathView);
- d->clear();
- if (d->attType)
- d->attType->release();
- if (d->ownModel)
- delete d->model;
-}
-
-/*!
- \qmlattachedproperty PathView QtQuick2::PathView::view
- This attached property holds the view that manages this delegate instance.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty bool QtQuick2::PathView::onPath
- This attached property holds whether the item is currently on the path.
-
- If a pathItemCount has been set, it is possible that some items may
- be instantiated, but not considered to be currently on the path.
- Usually, these items would be set invisible, for example:
-
- \qml
- Component {
- Rectangle {
- visible: PathView.onPath
- // ...
- }
- }
- \endqml
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty bool QtQuick2::PathView::isCurrentItem
- This attached property is true if this delegate is the current item; otherwise false.
-
- It is attached to each instance of the delegate.
-
- This property may be used to adjust the appearance of the current item.
-
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
-*/
-
-/*!
- \qmlproperty model QtQuick2::PathView::model
- This property holds the model providing data for the view.
-
- The model provides a set of data that is used to create the items for the view.
- For large or dynamic datasets the model is usually provided by a C++ model object.
- Models can also be created directly in QML, using the ListModel element.
-
- \sa {qmlmodels}{Data Models}
-*/
-QVariant QQuickPathView::model() const
-{
- Q_D(const QQuickPathView);
- return d->modelVariant;
-}
-
-void QQuickPathView::setModel(const QVariant &model)
-{
- Q_D(QQuickPathView);
- if (d->modelVariant == model)
- return;
-
- if (d->model) {
- disconnect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
- this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
- disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
- for (int i=0; i<d->items.count(); i++){
- QQuickItem *p = d->items[i];
- d->releaseItem(p);
- }
- d->items.clear();
- }
-
- d->modelVariant = model;
- QObject *object = qvariant_cast<QObject*>(model);
- QQuickVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
- if (d->ownModel) {
- delete d->model;
- d->ownModel = false;
- }
- d->model = vim;
- } else {
- if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
- d->ownModel = true;
- if (isComponentComplete())
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
- }
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
- dataModel->setModel(model);
- }
- d->modelCount = 0;
- if (d->model) {
- connect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
- this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
- connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
- d->modelCount = d->model->count();
- if (d->model->count())
- d->offset = qmlMod(d->offset, qreal(d->model->count()));
- if (d->offset < 0)
- d->offset = d->model->count() + d->offset;
-}
- d->regenerate();
- if (d->currentIndex < d->modelCount)
- setOffset(qmlMod(d->modelCount - d->currentIndex, d->modelCount));
- else
- d->fixOffset();
- emit countChanged();
- emit modelChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::PathView::count
- This property holds the number of items in the model.
-*/
-int QQuickPathView::count() const
-{
- Q_D(const QQuickPathView);
- return d->model ? d->modelCount : 0;
-}
-
-/*!
- \qmlproperty Path QtQuick2::PathView::path
- This property holds the path used to lay out the items.
- For more information see the \l Path documentation.
-*/
-QDeclarativePath *QQuickPathView::path() const
-{
- Q_D(const QQuickPathView);
- return d->path;
-}
-
-void QQuickPathView::setPath(QDeclarativePath *path)
-{
- Q_D(QQuickPathView);
- if (d->path == path)
- return;
- if (d->path)
- disconnect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
- d->path = path;
- connect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
- if (d->isValid() && isComponentComplete()) {
- d->clear();
- if (d->attType) {
- d->attType->release();
- d->attType = 0;
- }
- d->regenerate();
- }
- emit pathChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::PathView::currentIndex
- This property holds the index of the current item.
-*/
-int QQuickPathView::currentIndex() const
-{
- Q_D(const QQuickPathView);
- return d->currentIndex;
-}
-
-void QQuickPathView::setCurrentIndex(int idx)
-{
- Q_D(QQuickPathView);
- if (d->model && d->modelCount)
- idx = qAbs(idx % d->modelCount);
- if (d->model && (idx != d->currentIndex || !d->currentItem)) {
- if (d->currentItem) {
- if (QQuickPathViewAttached *att = d->attached(d->currentItem))
- att->setIsCurrentItem(false);
- d->releaseItem(d->currentItem);
- }
- int oldCurrentIdx = d->currentIndex;
- QQuickItem *oldCurrentItem = d->currentItem;
- d->currentItem = 0;
- d->moveReason = QQuickPathViewPrivate::SetIndex;
- d->currentIndex = idx;
- if (d->modelCount) {
- d->createCurrentItem();
- if (d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
- d->snapToCurrent();
- d->currentItemOffset = d->positionOfIndex(d->currentIndex);
- d->updateHighlight();
- }
- if (oldCurrentIdx != d->currentIndex)
- emit currentIndexChanged();
- if (oldCurrentItem != d->currentItem)
- emit currentItemChanged();
- }
-}
-
-QQuickItem *QQuickPathView::currentItem() const
-{
- Q_D(const QQuickPathView);
- return d->currentItem;
-}
-
-/*!
- \qmlmethod QtQuick2::PathView::incrementCurrentIndex()
-
- Increments the current index.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-void QQuickPathView::incrementCurrentIndex()
-{
- Q_D(QQuickPathView);
- d->moveDirection = QQuickPathViewPrivate::Positive;
- setCurrentIndex(currentIndex()+1);
-}
-
-/*!
- \qmlmethod QtQuick2::PathView::decrementCurrentIndex()
-
- Decrements the current index.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-void QQuickPathView::decrementCurrentIndex()
-{
- Q_D(QQuickPathView);
- if (d->model && d->modelCount) {
- int idx = currentIndex()-1;
- if (idx < 0)
- idx = d->modelCount - 1;
- d->moveDirection = QQuickPathViewPrivate::Negative;
- setCurrentIndex(idx);
- }
-}
-
-/*!
- \qmlproperty real QtQuick2::PathView::offset
-
- The offset specifies how far along the path the items are from their initial positions.
- This is a real number that ranges from 0.0 to the count of items in the model.
-*/
-qreal QQuickPathView::offset() const
-{
- Q_D(const QQuickPathView);
- return d->offset;
-}
-
-void QQuickPathView::setOffset(qreal offset)
-{
- Q_D(QQuickPathView);
- d->setOffset(offset);
- d->updateCurrent();
-}
-
-void QQuickPathViewPrivate::setOffset(qreal o)
-{
- Q_Q(QQuickPathView);
- if (offset != o) {
- if (isValid() && q->isComponentComplete()) {
- offset = qmlMod(o, qreal(modelCount));
- if (offset < 0)
- offset += qreal(modelCount);
- q->refill();
- } else {
- offset = o;
- }
- emit q->offsetChanged();
- }
-}
-
-void QQuickPathViewPrivate::setAdjustedOffset(qreal o)
-{
- setOffset(o+offsetAdj);
-}
-
-/*!
- \qmlproperty Component QtQuick2::PathView::highlight
- This property holds the component to use as the highlight.
-
- An instance of the highlight component will be created for each view.
- The geometry of the resultant component instance will be managed by the view
- so as to stay with the current item.
-
- The below example demonstrates how to make a simple highlight. Note the use
- of the \l{PathView::onPath}{PathView.onPath} attached property to ensure that
- the highlight is hidden when flicked away from the path.
-
- \qml
- Component {
- Rectangle {
- visible: PathView.onPath
- // ...
- }
- }
- \endqml
-
- \sa highlightItem, highlightRangeMode
-*/
-
-QDeclarativeComponent *QQuickPathView::highlight() const
-{
- Q_D(const QQuickPathView);
- return d->highlightComponent;
-}
-
-void QQuickPathView::setHighlight(QDeclarativeComponent *highlight)
-{
- Q_D(QQuickPathView);
- if (highlight != d->highlightComponent) {
- d->highlightComponent = highlight;
- d->createHighlight();
- d->updateHighlight();
- emit highlightChanged();
- }
-}
-
-/*!
- \qmlproperty Item QtQuick2::PathView::highlightItem
-
- \c highlightItem holds the highlight item, which was created
- from the \l highlight component.
-
- \sa highlight
-*/
-QQuickItem *QQuickPathView::highlightItem()
-{
- Q_D(const QQuickPathView);
- return d->highlightItem;
-}
-/*!
- \qmlproperty real QtQuick2::PathView::preferredHighlightBegin
- \qmlproperty real QtQuick2::PathView::preferredHighlightEnd
- \qmlproperty enumeration QtQuick2::PathView::highlightRangeMode
-
- These properties set the preferred range of the highlight (current item)
- within the view. The preferred values must be in the range 0.0-1.0.
-
- If highlightRangeMode is set to \e PathView.NoHighlightRange
-
- If highlightRangeMode is set to \e PathView.ApplyRange the view will
- attempt to maintain the highlight within the range, however
- the highlight can move outside of the range at the ends of the path
- or due to a mouse interaction.
-
- If highlightRangeMode is set to \e PathView.StrictlyEnforceRange the highlight will never
- move outside of the range. This means that the current item will change
- if a keyboard or mouse action would cause the highlight to move
- outside of the range.
-
- Note that this is the correct way to influence where the
- current item ends up when the view moves. For example, if you want the
- currently selected item to be in the middle of the path, then set the
- highlight range to be 0.5,0.5 and highlightRangeMode to PathView.StrictlyEnforceRange.
- Then, when the path scrolls,
- the currently selected item will be the item at that position. This also applies to
- when the currently selected item changes - it will scroll to within the preferred
- highlight range. Furthermore, the behaviour of the current item index will occur
- whether or not a highlight exists.
-
- The default value is \e PathView.StrictlyEnforceRange.
-
- Note that a valid range requires preferredHighlightEnd to be greater
- than or equal to preferredHighlightBegin.
-*/
-qreal QQuickPathView::preferredHighlightBegin() const
-{
- Q_D(const QQuickPathView);
- return d->highlightRangeStart;
-}
-
-void QQuickPathView::setPreferredHighlightBegin(qreal start)
-{
- Q_D(QQuickPathView);
- if (d->highlightRangeStart == start || start < 0 || start > 1.0)
- return;
- d->highlightRangeStart = start;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- refill();
- emit preferredHighlightBeginChanged();
-}
-
-qreal QQuickPathView::preferredHighlightEnd() const
-{
- Q_D(const QQuickPathView);
- return d->highlightRangeEnd;
-}
-
-void QQuickPathView::setPreferredHighlightEnd(qreal end)
-{
- Q_D(QQuickPathView);
- if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
- return;
- d->highlightRangeEnd = end;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- refill();
- emit preferredHighlightEndChanged();
-}
-
-QQuickPathView::HighlightRangeMode QQuickPathView::highlightRangeMode() const
-{
- Q_D(const QQuickPathView);
- return d->highlightRangeMode;
-}
-
-void QQuickPathView::setHighlightRangeMode(HighlightRangeMode mode)
-{
- Q_D(QQuickPathView);
- if (d->highlightRangeMode == mode)
- return;
- d->highlightRangeMode = mode;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- if (d->haveHighlightRange) {
- d->regenerate();
- d->snapToCurrent();
- }
- emit highlightRangeModeChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::PathView::highlightMoveDuration
- This property holds the move animation duration of the highlight delegate.
-
- If the highlightRangeMode is StrictlyEnforceRange then this property
- determines the speed that the items move along the path.
-
- The default value for the duration is 300ms.
-*/
-int QQuickPathView::highlightMoveDuration() const
-{
- Q_D(const QQuickPathView);
- return d->highlightMoveDuration;
-}
-
-void QQuickPathView::setHighlightMoveDuration(int duration)
-{
- Q_D(QQuickPathView);
- if (d->highlightMoveDuration == duration)
- return;
- d->highlightMoveDuration = duration;
- emit highlightMoveDurationChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::PathView::dragMargin
- This property holds the maximum distance from the path that initiate mouse dragging.
-
- By default the path can only be dragged by clicking on an item. If
- dragMargin is greater than zero, a drag can be initiated by clicking
- within dragMargin pixels of the path.
-*/
-qreal QQuickPathView::dragMargin() const
-{
- Q_D(const QQuickPathView);
- return d->dragMargin;
-}
-
-void QQuickPathView::setDragMargin(qreal dragMargin)
-{
- Q_D(QQuickPathView);
- if (d->dragMargin == dragMargin)
- return;
- d->dragMargin = dragMargin;
- emit dragMarginChanged();
-}
-
-/*!
- \qmlproperty real QtQuick2::PathView::flickDeceleration
- This property holds the rate at which a flick will decelerate.
-
- The default is 100.
-*/
-qreal QQuickPathView::flickDeceleration() const
-{
- Q_D(const QQuickPathView);
- return d->deceleration;
-}
-
-void QQuickPathView::setFlickDeceleration(qreal dec)
-{
- Q_D(QQuickPathView);
- if (d->deceleration == dec)
- return;
- d->deceleration = dec;
- emit flickDecelerationChanged();
-}
-
-/*!
- \qmlproperty bool QtQuick2::PathView::interactive
-
- A user cannot drag or flick a PathView that is not interactive.
-
- This property is useful for temporarily disabling flicking. This allows
- special interaction with PathView's children.
-*/
-bool QQuickPathView::isInteractive() const
-{
- Q_D(const QQuickPathView);
- return d->interactive;
-}
-
-void QQuickPathView::setInteractive(bool interactive)
-{
- Q_D(QQuickPathView);
- if (interactive != d->interactive) {
- d->interactive = interactive;
- if (!interactive)
- d->tl.clear();
- emit interactiveChanged();
- }
-}
-
-/*!
- \qmlproperty bool QtQuick2::PathView::moving
-
- This property holds whether the view is currently moving
- due to the user either dragging or flicking the view.
-*/
-bool QQuickPathView::isMoving() const
-{
- Q_D(const QQuickPathView);
- return d->moving;
-}
-
-/*!
- \qmlproperty bool QtQuick2::PathView::flicking
-
- This property holds whether the view is currently moving
- due to the user flicking the view.
-*/
-bool QQuickPathView::isFlicking() const
-{
- Q_D(const QQuickPathView);
- return d->flicking;
-}
-
-/*!
- \qmlsignal QtQuick2::PathView::onMovementStarted()
-
- This handler is called when the view begins moving due to user
- interaction.
-*/
-
-/*!
- \qmlsignal QtQuick2::PathView::onMovementEnded()
-
- This handler is called when the view stops moving due to user
- interaction. If a flick was generated, this handler will
- be triggered once the flick stops. If a flick was not
- generated, the handler will be triggered when the
- user stops dragging - i.e. a mouse or touch release.
-*/
-
-/*!
- \qmlsignal QtQuick2::PathView::onFlickStarted()
-
- This handler is called when the view is flicked. A flick
- starts from the point that the mouse or touch is released,
- while still in motion.
-*/
-
-/*!
- \qmlsignal QtQuick2::PathView::onFlickEnded()
-
- This handler is called when the view stops moving due to a flick.
-*/
-
-/*!
- \qmlproperty Component QtQuick2::PathView::delegate
-
- The delegate provides a template defining each item instantiated by the view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qmlmodels}{Data Model}.
-
- The number of elements in the delegate has a direct effect on the
- flicking performance of the view when pathItemCount is specified. If at all possible, place functionality
- that is not needed for the normal display of the delegate in a \l Loader which
- can load additional elements when needed.
-
- Note that the PathView will layout the items based on the size of the root
- item in the delegate.
-
- Here is an example delegate:
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
-*/
-QDeclarativeComponent *QQuickPathView::delegate() const
-{
- Q_D(const QQuickPathView);
- if (d->model) {
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
- return dataModel->delegate();
- }
-
- return 0;
-}
-
-void QQuickPathView::setDelegate(QDeclarativeComponent *delegate)
-{
- Q_D(QQuickPathView);
- if (delegate == this->delegate())
- return;
- if (!d->ownModel) {
- d->model = new QQuickVisualDataModel(qmlContext(this));
- d->ownModel = true;
- }
- if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
- int oldCount = dataModel->count();
- dataModel->setDelegate(delegate);
- d->modelCount = dataModel->count();
- d->regenerate();
- if (oldCount != dataModel->count())
- emit countChanged();
- emit delegateChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQuick2::PathView::pathItemCount
- This property holds the number of items visible on the path at any one time.
-*/
-int QQuickPathView::pathItemCount() const
-{
- Q_D(const QQuickPathView);
- return d->pathItems;
-}
-
-void QQuickPathView::setPathItemCount(int i)
-{
- Q_D(QQuickPathView);
- if (i == d->pathItems)
- return;
- if (i < 1)
- i = 1;
- d->pathItems = i;
- d->updateMappedRange();
- if (d->isValid() && isComponentComplete()) {
- d->regenerate();
- }
- emit pathItemCountChanged();
-}
-
-QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
-{
- //XXX maybe do recursively at increasing resolution.
- qreal mindist = 1e10; // big number
- QPointF nearPoint = path->pointAt(0);
- qreal nearPc = 0;
- for (qreal i=1; i < 1000; i++) {
- QPointF pt = path->pointAt(i/1000.0);
- QPointF diff = pt - point;
- qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
- if (dist < mindist) {
- nearPoint = pt;
- nearPc = i;
- mindist = dist;
- }
- }
-
- if (nearPercent)
- *nearPercent = nearPc / 1000.0;
-
- return nearPoint;
-}
-
-void QQuickPathView::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickPathView);
- if (d->interactive) {
- d->handleMousePressEvent(event);
- event->accept();
- } else {
- QQuickItem::mousePressEvent(event);
- }
-}
-
-void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
-{
- Q_Q(QQuickPathView);
- if (!interactive || !items.count())
- return;
- QPointF scenePoint = q->mapToScene(event->localPos());
- int idx = 0;
- for (; idx < items.count(); ++idx) {
- QRectF rect = items.at(idx)->boundingRect();
- rect = items.at(idx)->mapRectToScene(rect);
- if (rect.contains(scenePoint))
- break;
- }
- if (idx == items.count() && dragMargin == 0.) // didn't click on an item
- return;
-
- startPoint = pointNear(event->localPos(), &startPc);
- if (idx == items.count()) {
- qreal distance = qAbs(event->localPos().x() - startPoint.x()) + qAbs(event->localPos().y() - startPoint.y());
- if (distance > dragMargin)
- return;
- }
-
- if (tl.isActive() && flicking)
- stealMouse = true; // If we've been flicked then steal the click.
- else
- stealMouse = false;
-
- lastElapsed = 0;
- lastDist = 0;
- QQuickItemPrivate::start(lastPosTime);
- tl.clear();
-}
-
-void QQuickPathView::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickPathView);
- if (d->interactive) {
- d->handleMouseMoveEvent(event);
- if (d->stealMouse)
- setKeepMouseGrab(true);
- event->accept();
- } else {
- QQuickItem::mouseMoveEvent(event);
- }
-}
-
-void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
-{
- Q_Q(QQuickPathView);
- if (!interactive || !lastPosTime.isValid())
- return;
-
- qreal newPc;
- QPointF pathPoint = pointNear(event->localPos(), &newPc);
- if (!stealMouse) {
- QPointF delta = pathPoint - startPoint;
- if (qAbs(delta.x()) > qApp->styleHints()->startDragDistance() || qAbs(delta.y()) > qApp->styleHints()->startDragDistance()) {
- stealMouse = true;
- startPc = newPc;
- }
- }
-
- if (stealMouse) {
- moveReason = QQuickPathViewPrivate::Mouse;
- qreal diff = (newPc - startPc)*modelCount*mappedRange;
- if (diff) {
- q->setOffset(offset + diff);
-
- if (diff > modelCount/2)
- diff -= modelCount;
- else if (diff < -modelCount/2)
- diff += modelCount;
-
- lastElapsed = QQuickItemPrivate::restart(lastPosTime);
- lastDist = diff;
- startPc = newPc;
- }
- if (!moving) {
- moving = true;
- emit q->movingChanged();
- emit q->movementStarted();
- }
- }
-}
-
-void QQuickPathView::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPathView);
- if (d->interactive) {
- d->handleMouseReleaseEvent(event);
- event->accept();
- ungrabMouse();
- } else {
- QQuickItem::mouseReleaseEvent(event);
- }
-}
-
-void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
-{
- Q_Q(QQuickPathView);
- stealMouse = false;
- q->setKeepMouseGrab(false);
- if (!interactive || !lastPosTime.isValid())
- return;
-
- qreal elapsed = qreal(lastElapsed + QQuickItemPrivate::elapsed(lastPosTime)) / 1000.;
- qreal velocity = elapsed > 0. ? lastDist / elapsed : 0;
- if (model && modelCount && qAbs(velocity) > 1.) {
- qreal count = pathItems == -1 ? modelCount : pathItems;
- if (qAbs(velocity) > count * 2) // limit velocity
- velocity = (velocity > 0 ? count : -count) * 2;
- // Calculate the distance to be travelled
- qreal v2 = velocity*velocity;
- qreal accel = deceleration/10;
- // + 0.25 to encourage moving at least one item in the flick direction
- qreal dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
- if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- // round to nearest item.
- if (velocity > 0.)
- dist = qRound(dist + offset) - offset;
- else
- dist = qRound(dist - offset) + offset;
- // Calculate accel required to stop on item boundary
- if (dist <= 0.) {
- dist = 0.;
- accel = 0.;
- } else {
- accel = v2 / (2.0f * qAbs(dist));
- }
- }
- offsetAdj = 0.0;
- moveOffset.setValue(offset);
- tl.accel(moveOffset, velocity, accel, dist);
- tl.callback(QDeclarativeTimeLineCallback(&moveOffset, fixOffsetCallback, this));
- if (!flicking) {
- flicking = true;
- emit q->flickingChanged();
- emit q->flickStarted();
- }
- } else {
- fixOffset();
- }
-
- lastPosTime.invalidate();
- if (!tl.isActive())
- q->movementEnding();
-}
-
-bool QQuickPathView::sendMouseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPathView);
- QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
- QQuickCanvas *c = canvas();
- QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
- bool stealThisEvent = d->stealMouse;
- if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
- QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers());
- mouseEvent.setAccepted(false);
-
- switch (mouseEvent.type()) {
- case QEvent::MouseMove:
- d->handleMouseMoveEvent(&mouseEvent);
- break;
- case QEvent::MouseButtonPress:
- d->handleMousePressEvent(&mouseEvent);
- stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
- break;
- case QEvent::MouseButtonRelease:
- d->handleMouseReleaseEvent(&mouseEvent);
- break;
- default:
- break;
- }
- grabber = c->mouseGrabberItem();
- if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
- grabMouse();
-
- return d->stealMouse;
- } else if (d->lastPosTime.isValid()) {
- d->lastPosTime.invalidate();
- d->fixOffset();
- }
- if (event->type() == QEvent::MouseButtonRelease)
- d->stealMouse = false;
- return false;
-}
-
-bool QQuickPathView::childMouseEventFilter(QQuickItem *i, QEvent *e)
-{
- Q_D(QQuickPathView);
- if (!isVisible() || !d->interactive)
- return QQuickItem::childMouseEventFilter(i, e);
-
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- return sendMouseEvent(static_cast<QMouseEvent *>(e));
- default:
- break;
- }
-
- return QQuickItem::childMouseEventFilter(i, e);
-}
-
-void QQuickPathView::mouseUngrabEvent()
-{
- Q_D(QQuickPathView);
- if (d->stealMouse) {
- // if our mouse grab has been removed (probably by a Flickable),
- // fix our state
- d->stealMouse = false;
- setKeepMouseGrab(false);
- d->lastPosTime.invalidate();
- }
-}
-
-void QQuickPathView::updatePolish()
-{
- QQuickItem::updatePolish();
- refill();
-}
-
-void QQuickPathView::componentComplete()
-{
- Q_D(QQuickPathView);
- if (d->model && d->ownModel)
- static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
-
- QQuickItem::componentComplete();
-
- d->createHighlight();
- // It is possible that a refill has already happended to to Path
- // bindings being handled in the componentComplete(). If so
- // don't do it again.
- if (d->items.count() == 0 && d->model) {
- d->modelCount = d->model->count();
- d->regenerate();
- }
- d->updateHighlight();
-
- if (d->modelCount)
- emit countChanged();
-}
-
-void QQuickPathView::refill()
-{
- Q_D(QQuickPathView);
- if (!d->isValid() || !isComponentComplete())
- return;
-
- d->layoutScheduled = false;
- bool currentVisible = false;
-
- // first move existing items and remove items off path
- int idx = d->firstIndex;
- QList<QQuickItem*>::iterator it = d->items.begin();
- while (it != d->items.end()) {
- qreal pos = d->positionOfIndex(idx);
- QQuickItem *item = *it;
- if (pos >= 0.0) {
- d->updateItem(item, pos);
- if (idx == d->currentIndex) {
- currentVisible = true;
- d->currentItemOffset = pos;
- }
- ++it;
- } else {
- // qDebug() << "release";
- d->updateItem(item, 1.0);
- d->releaseItem(item);
- if (it == d->items.begin()) {
- if (++d->firstIndex >= d->modelCount)
- d->firstIndex = 0;
- }
- it = d->items.erase(it);
- }
- ++idx;
- if (idx >= d->modelCount)
- idx = 0;
- }
- if (!d->items.count())
- d->firstIndex = -1;
-
- bool waiting = false;
- if (d->modelCount) {
- // add items to beginning and end
- int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount);
- if (d->items.count() < count) {
- int idx = qRound(d->modelCount - d->offset) % d->modelCount;
- qreal startPos = 0.0;
- if (d->haveHighlightRange && d->highlightRangeMode != QQuickPathView::NoHighlightRange)
- startPos = d->highlightRangeStart;
- if (d->firstIndex >= 0) {
- startPos = d->positionOfIndex(d->firstIndex);
- idx = (d->firstIndex + d->items.count()) % d->modelCount;
- }
- qreal pos = d->positionOfIndex(idx);
- while ((pos > startPos || !d->items.count()) && d->items.count() < count) {
-// qDebug() << "append" << idx;
- QQuickItem *item = d->getItem(idx, idx+1);
- if (!item) {
- waiting = true;
- break;
- }
- if (d->currentIndex == idx) {
- currentVisible = true;
- d->currentItemOffset = pos;
- }
- if (d->items.count() == 0)
- d->firstIndex = idx;
- d->items.append(item);
- d->updateItem(item, pos);
- ++idx;
- if (idx >= d->modelCount)
- idx = 0;
- pos = d->positionOfIndex(idx);
- }
-
- idx = d->firstIndex - 1;
- if (idx < 0)
- idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
- while (!waiting && (pos >= 0.0 && pos < startPos) && d->items.count() < count) {
-// qDebug() << "prepend" << idx;
- QQuickItem *item = d->getItem(idx, idx+1);
- if (!item) {
- waiting = true;
- break;
- }
- if (d->currentIndex == idx) {
- currentVisible = true;
- d->currentItemOffset = pos;
- }
- d->items.prepend(item);
- d->updateItem(item, pos);
- d->firstIndex = idx;
- idx = d->firstIndex - 1;
- if (idx < 0)
- idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
- }
- }
- }
-
- if (!currentVisible) {
- d->currentItemOffset = 1.0;
- if (d->currentItem) {
- if (QQuickPathViewAttached *att = d->attached(d->currentItem))
- att->setOnPath(false);
- } else if (!waiting && d->currentIndex >= 0 && d->currentIndex < d->modelCount) {
- if (d->currentItem = d->getItem(d->currentIndex, d->currentIndex, false)) {
- d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
- if (QQuickPathViewAttached *att = d->attached(d->currentItem))
- att->setIsCurrentItem(true);
- }
- }
- } else if (!waiting && !d->currentItem) {
- if (d->currentItem = d->getItem(d->currentIndex, d->currentIndex, true)) {
- d->currentItem->setFocus(true);
- if (QQuickPathViewAttached *att = d->attached(d->currentItem))
- att->setIsCurrentItem(true);
- }
- }
-
- if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- d->updateItem(d->highlightItem, d->highlightRangeStart);
- if (QQuickPathViewAttached *att = d->attached(d->highlightItem))
- att->setOnPath(true);
- } else if (d->highlightItem && d->moveReason != QQuickPathViewPrivate::SetIndex) {
- d->updateItem(d->highlightItem, d->currentItemOffset);
- if (QQuickPathViewAttached *att = d->attached(d->highlightItem))
- att->setOnPath(currentVisible);
- }
- while (d->itemCache.count())
- d->releaseItem(d->itemCache.takeLast());
-}
-
-void QQuickPathView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
-{
- Q_D(QQuickPathView);
- if (!d->model || !d->model->isValid() || !d->path || !isComponentComplete())
- return;
-
- if (reset) {
- d->modelCount = d->model->count();
- d->regenerate();
- emit countChanged();
- return;
- }
-
- if (changeSet.removes().isEmpty() && changeSet.inserts().isEmpty())
- return;
-
- const int modelCount = d->modelCount;
- int moveId = -1;
- int moveOffset;
- bool currentChanged = false;
- bool changedOffset = false;
- foreach (const QDeclarativeChangeSet::Remove &r, changeSet.removes()) {
- if (moveId == -1 && d->currentIndex >= r.index + r.count) {
- d->currentIndex -= r.count;
- currentChanged = true;
- } else if (moveId == -1 && d->currentIndex >= r.index && d->currentIndex < r.index + r.count) {
- // current item has been removed.
- d->currentIndex = qMin(r.index, d->modelCount - r.count - 1);
- if (r.isMove()) {
- moveId = r.moveId;
- moveOffset = d->currentIndex - r.index;
- } else if (d->currentItem) {
- if (QQuickPathViewAttached *att = d->attached(d->currentItem))
- att->setIsCurrentItem(true);
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
- }
- currentChanged = true;
- }
-
- if (r.index > d->currentIndex) {
- changedOffset = true;
- d->offset -= r.count;
- d->offsetAdj -= r.count;
- }
- d->modelCount -= r.count;
- }
- foreach (const QDeclarativeChangeSet::Insert &i, changeSet.inserts()) {
- if (d->modelCount) {
- if (moveId == -1 && i.index <= d->currentIndex) {
- d->currentIndex += i.count;
- currentChanged = true;
- } else {
- if (moveId != -1 && moveId == i.moveId) {
- d->currentIndex = i.index + moveOffset;
- currentChanged = true;
- }
- if (i.index > d->currentIndex) {
- d->offset += i.count;
- d->offsetAdj += i.count;
- changedOffset = true;
- }
- }
- }
- d->modelCount += i.count;
- }
-
- d->offset = qmlMod(d->offset, d->modelCount);
- if (d->offset < 0)
- d->offset += d->modelCount;
-
- d->itemCache += d->items;
- d->items.clear();
-
- if (!d->modelCount) {
- while (d->itemCache.count())
- d->releaseItem(d->itemCache.takeLast());
- d->offset = 0;
- changedOffset = true;
- d->tl.reset(d->moveOffset);
- } else {
- if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
- changedOffset = true;
- }
- d->firstIndex = -1;
- d->updateMappedRange();
- d->scheduleLayout();
- }
- if (changedOffset)
- emit offsetChanged();
- if (currentChanged)
- emit currentIndexChanged();
- if (d->modelCount != modelCount)
- emit countChanged();
-}
-
-void QQuickPathView::destroyingItem(QQuickItem *item)
-{
- Q_UNUSED(item);
-}
-
-void QQuickPathView::ticked()
-{
- Q_D(QQuickPathView);
- d->updateCurrent();
-}
-
-void QQuickPathView::movementEnding()
-{
- Q_D(QQuickPathView);
- if (d->flicking) {
- d->flicking = false;
- emit flickingChanged();
- emit flickEnded();
- }
- if (d->moving && !d->stealMouse) {
- d->moving = false;
- emit movingChanged();
- emit movementEnded();
- }
-}
-
-// find the item closest to the snap position
-int QQuickPathViewPrivate::calcCurrentIndex()
-{
- int current = -1;
- if (modelCount && model && items.count()) {
- offset = qmlMod(offset, modelCount);
- if (offset < 0)
- offset += modelCount;
- current = qRound(qAbs(qmlMod(modelCount - offset, modelCount)));
- current = current % modelCount;
- }
-
- return current;
-}
-
-void QQuickPathViewPrivate::createCurrentItem()
-{
- if (requestedIndex != -1)
- return;
- int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
- if (itemIndex < items.count()) {
- if (currentItem = getItem(currentIndex, currentIndex, true)) {
- currentItem->setFocus(true);
- if (QQuickPathViewAttached *att = attached(currentItem))
- att->setIsCurrentItem(true);
- }
- } else if (currentIndex >= 0 && currentIndex < modelCount) {
- if (currentItem = getItem(currentIndex, currentIndex, false)) {
- updateItem(currentItem, currentIndex < firstIndex ? 0.0 : 1.0);
- if (QQuickPathViewAttached *att = attached(currentItem))
- att->setIsCurrentItem(true);
- }
- }
-}
-
-void QQuickPathViewPrivate::updateCurrent()
-{
- Q_Q(QQuickPathView);
- if (moveReason != Mouse)
- return;
- if (!modelCount || !haveHighlightRange || highlightRangeMode != QQuickPathView::StrictlyEnforceRange)
- return;
-
- int idx = calcCurrentIndex();
- if (model && idx != currentIndex) {
- if (currentItem) {
- if (QQuickPathViewAttached *att = attached(currentItem))
- att->setIsCurrentItem(false);
- releaseItem(currentItem);
- }
- currentIndex = idx;
- currentItem = 0;
- createCurrentItem();
- emit q->currentIndexChanged();
- }
-}
-
-void QQuickPathViewPrivate::fixOffsetCallback(void *d)
-{
- ((QQuickPathViewPrivate *)d)->fixOffset();
-}
-
-void QQuickPathViewPrivate::fixOffset()
-{
- Q_Q(QQuickPathView);
- if (model && items.count()) {
- if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- int curr = calcCurrentIndex();
- if (curr != currentIndex)
- q->setCurrentIndex(curr);
- else
- snapToCurrent();
- }
- }
-}
-
-void QQuickPathViewPrivate::snapToCurrent()
-{
- if (!model || modelCount <= 0)
- return;
-
- qreal targetOffset = qmlMod(modelCount - currentIndex, modelCount);
-
- if (offset == targetOffset)
- return;
-
- moveReason = Other;
- offsetAdj = 0.0;
- tl.reset(moveOffset);
- moveOffset.setValue(offset);
-
- const int duration = highlightMoveDuration;
-
- if (!duration) {
- tl.set(moveOffset, targetOffset);
- } else if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2)) {
- qreal distance = modelCount - targetOffset + offset;
- if (targetOffset > moveOffset) {
- tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
- tl.set(moveOffset, modelCount);
- tl.move(moveOffset, targetOffset, QEasingCurve(offset == 0.0 ? QEasingCurve::InOutQuad : QEasingCurve::OutQuad), int(duration * (modelCount-targetOffset) / distance));
- } else {
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
- }
- } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2) {
- qreal distance = modelCount - offset + targetOffset;
- if (targetOffset < moveOffset) {
- tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
- tl.set(moveOffset, 0.0);
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * targetOffset / distance));
- } else {
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
- }
- } else {
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
- }
- moveDirection = Shortest;
-}
-
-QQuickPathViewAttached *QQuickPathView::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickPathViewAttached(obj);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/items/qquickpathview_p.h b/src/declarative/items/qquickpathview_p.h
deleted file mode 100644
index ebc1587b09..0000000000
--- a/src/declarative/items/qquickpathview_p.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKPATHVIEW_P_H
-#define QQUICKPATHVIEW_P_H
-
-#include "qquickitem.h"
-
-#include <private/qdeclarativepath_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeChangeSet;
-
-class QQuickPathViewPrivate;
-class QQuickPathViewAttached;
-class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
- Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
- Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
- Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
-
- Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
- Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
-
- Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged)
- Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged)
- Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
- Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
-
- Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged)
- Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
- Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
-
- Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
- Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
-
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount NOTIFY pathItemCountChanged)
-
- Q_ENUMS(HighlightRangeMode)
-
-public:
- QQuickPathView(QQuickItem *parent=0);
- virtual ~QQuickPathView();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativePath *path() const;
- void setPath(QDeclarativePath *);
-
- int currentIndex() const;
- void setCurrentIndex(int idx);
-
- QQuickItem *currentItem() const;
-
- qreal offset() const;
- void setOffset(qreal offset);
-
- QDeclarativeComponent *highlight() const;
- void setHighlight(QDeclarativeComponent *highlight);
- QQuickItem *highlightItem();
-
- enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
- HighlightRangeMode highlightRangeMode() const;
- void setHighlightRangeMode(HighlightRangeMode mode);
-
- qreal preferredHighlightBegin() const;
- void setPreferredHighlightBegin(qreal);
-
- qreal preferredHighlightEnd() const;
- void setPreferredHighlightEnd(qreal);
-
- int highlightMoveDuration() const;
- void setHighlightMoveDuration(int);
-
- qreal dragMargin() const;
- void setDragMargin(qreal margin);
-
- qreal flickDeceleration() const;
- void setFlickDeceleration(qreal dec);
-
- bool isInteractive() const;
- void setInteractive(bool);
-
- bool isMoving() const;
- bool isFlicking() const;
-
- int count() const;
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int pathItemCount() const;
- void setPathItemCount(int);
-
- static QQuickPathViewAttached *qmlAttachedProperties(QObject *);
-
-public Q_SLOTS:
- void incrementCurrentIndex();
- void decrementCurrentIndex();
-
-Q_SIGNALS:
- void currentIndexChanged();
- void currentItemChanged();
- void offsetChanged();
- void modelChanged();
- void countChanged();
- void pathChanged();
- void preferredHighlightBeginChanged();
- void preferredHighlightEndChanged();
- void highlightRangeModeChanged();
- void dragMarginChanged();
- void snapPositionChanged();
- void delegateChanged();
- void pathItemCountChanged();
- void flickDecelerationChanged();
- void interactiveChanged();
- void movingChanged();
- void flickingChanged();
- void highlightChanged();
- void highlightItemChanged();
- void highlightMoveDurationChanged();
- void movementStarted();
- void movementEnded();
- void flickStarted();
- void flickEnded();
-
-protected:
- virtual void updatePolish();
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *);
- bool sendMouseEvent(QMouseEvent *event);
- bool childMouseEventFilter(QQuickItem *, QEvent *);
- void mouseUngrabEvent();
- void componentComplete();
-
-private Q_SLOTS:
- void refill();
- void ticked();
- void movementEnding();
- void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
- void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
- void destroyingItem(QQuickItem *item);
- void pathUpdated();
-
-private:
- friend class QQuickPathViewAttached;
- Q_DISABLE_COPY(QQuickPathView)
- Q_DECLARE_PRIVATE(QQuickPathView)
-};
-
-class QDeclarativeOpenMetaObject;
-class QQuickPathViewAttached : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QQuickPathView *view READ view CONSTANT)
- Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
- Q_PROPERTY(bool onPath READ isOnPath NOTIFY pathChanged)
-
-public:
- QQuickPathViewAttached(QObject *parent);
- ~QQuickPathViewAttached();
-
- QQuickPathView *view() { return m_view; }
-
- bool isCurrentItem() const { return m_isCurrent; }
- void setIsCurrentItem(bool c) {
- if (m_isCurrent != c) {
- m_isCurrent = c;
- emit currentItemChanged();
- }
- }
-
- QVariant value(const QByteArray &name) const;
- void setValue(const QByteArray &name, const QVariant &val);
-
- bool isOnPath() const { return m_onPath; }
- void setOnPath(bool on) {
- if (on != m_onPath) {
- m_onPath = on;
- emit pathChanged();
- }
- }
- qreal m_percent;
-
-Q_SIGNALS:
- void currentItemChanged();
- void pathChanged();
-
-private:
- friend class QQuickPathViewPrivate;
- friend class QQuickPathView;
- QQuickPathView *m_view;
- QDeclarativeOpenMetaObject *m_metaobject;
- bool m_onPath : 1;
- bool m_isCurrent : 1;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPathView)
-QML_DECLARE_TYPEINFO(QQuickPathView, QML_HAS_ATTACHED_PROPERTIES)
-QT_END_HEADER
-
-#endif // QQUICKPATHVIEW_P_H
diff --git a/src/declarative/items/qquickpincharea_p.h b/src/declarative/items/qquickpincharea_p.h
deleted file mode 100644
index c98a1fdd9e..0000000000
--- a/src/declarative/items/qquickpincharea_p.h
+++ /dev/null
@@ -1,315 +0,0 @@
-// Commit: f707672eb4c51ea82fbd98e1da16ece61a74c690
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtSG 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 QQUICKPINCHAREA_H
-#define QQUICKPINCHAREA_H
-
-#include "qquickitem.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
-{
- Q_OBJECT
-
- Q_ENUMS(Axis)
- Q_PROPERTY(QQuickItem *target READ target WRITE setTarget RESET resetTarget)
- Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged)
- Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged)
- Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged)
- Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged)
- Q_PROPERTY(Axis dragAxis READ axis WRITE setAxis NOTIFY dragAxisChanged)
- Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
- Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
- Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
- Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
- Q_PROPERTY(bool active READ active NOTIFY activeChanged)
-
-public:
- QQuickPinch();
-
- QQuickItem *target() const { return m_target; }
- void setTarget(QQuickItem *target) {
- if (target == m_target)
- return;
- m_target = target;
- emit targetChanged();
- }
- void resetTarget() {
- if (!m_target)
- return;
- m_target = 0;
- emit targetChanged();
- }
-
- qreal minimumScale() const { return m_minScale; }
- void setMinimumScale(qreal s) {
- if (s == m_minScale)
- return;
- m_minScale = s;
- emit minimumScaleChanged();
- }
- qreal maximumScale() const { return m_maxScale; }
- void setMaximumScale(qreal s) {
- if (s == m_maxScale)
- return;
- m_maxScale = s;
- emit maximumScaleChanged();
- }
-
- qreal minimumRotation() const { return m_minRotation; }
- void setMinimumRotation(qreal r) {
- if (r == m_minRotation)
- return;
- m_minRotation = r;
- emit minimumRotationChanged();
- }
- qreal maximumRotation() const { return m_maxRotation; }
- void setMaximumRotation(qreal r) {
- if (r == m_maxRotation)
- return;
- m_maxRotation = r;
- emit maximumRotationChanged();
- }
-
- enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
- Axis axis() const { return m_axis; }
- void setAxis(Axis a) {
- if (a == m_axis)
- return;
- m_axis = a;
- emit dragAxisChanged();
- }
-
- qreal xmin() const { return m_xmin; }
- void setXmin(qreal x) {
- if (x == m_xmin)
- return;
- m_xmin = x;
- emit minimumXChanged();
- }
- qreal xmax() const { return m_xmax; }
- void setXmax(qreal x) {
- if (x == m_xmax)
- return;
- m_xmax = x;
- emit maximumXChanged();
- }
- qreal ymin() const { return m_ymin; }
- void setYmin(qreal y) {
- if (y == m_ymin)
- return;
- m_ymin = y;
- emit minimumYChanged();
- }
- qreal ymax() const { return m_ymax; }
- void setYmax(qreal y) {
- if (y == m_ymax)
- return;
- m_ymax = y;
- emit maximumYChanged();
- }
-
- bool active() const { return m_active; }
- void setActive(bool a) {
- if (a == m_active)
- return;
- m_active = a;
- emit activeChanged();
- }
-
-signals:
- void targetChanged();
- void minimumScaleChanged();
- void maximumScaleChanged();
- void minimumRotationChanged();
- void maximumRotationChanged();
- void dragAxisChanged();
- void minimumXChanged();
- void maximumXChanged();
- void minimumYChanged();
- void maximumYChanged();
- void activeChanged();
-
-private:
- QQuickItem *m_target;
- qreal m_minScale;
- qreal m_maxScale;
- qreal m_minRotation;
- qreal m_maxRotation;
- Axis m_axis;
- qreal m_xmin;
- qreal m_xmax;
- qreal m_ymin;
- qreal m_ymax;
- bool m_active;
-};
-
-class Q_AUTOTEST_EXPORT QQuickPinchEvent : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QPointF center READ center)
- Q_PROPERTY(QPointF startCenter READ startCenter)
- Q_PROPERTY(QPointF previousCenter READ previousCenter)
- Q_PROPERTY(qreal scale READ scale)
- Q_PROPERTY(qreal previousScale READ previousScale)
- Q_PROPERTY(qreal angle READ angle)
- Q_PROPERTY(qreal previousAngle READ previousAngle)
- Q_PROPERTY(qreal rotation READ rotation)
- Q_PROPERTY(QPointF point1 READ point1)
- Q_PROPERTY(QPointF startPoint1 READ startPoint1)
- Q_PROPERTY(QPointF point2 READ point2)
- Q_PROPERTY(QPointF startPoint2 READ startPoint2)
- Q_PROPERTY(int pointCount READ pointCount)
- Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
-
-public:
- QQuickPinchEvent(QPointF c, qreal s, qreal a, qreal r)
- : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r)
- , m_pointCount(0), m_accepted(true) {}
-
- QPointF center() const { return m_center; }
- QPointF startCenter() const { return m_startCenter; }
- void setStartCenter(QPointF c) { m_startCenter = c; }
- QPointF previousCenter() const { return m_lastCenter; }
- void setPreviousCenter(QPointF c) { m_lastCenter = c; }
- qreal scale() const { return m_scale; }
- qreal previousScale() const { return m_lastScale; }
- void setPreviousScale(qreal s) { m_lastScale = s; }
- qreal angle() const { return m_angle; }
- qreal previousAngle() const { return m_lastAngle; }
- void setPreviousAngle(qreal a) { m_lastAngle = a; }
- qreal rotation() const { return m_rotation; }
- QPointF point1() const { return m_point1; }
- void setPoint1(QPointF p) { m_point1 = p; }
- QPointF startPoint1() const { return m_startPoint1; }
- void setStartPoint1(QPointF p) { m_startPoint1 = p; }
- QPointF point2() const { return m_point2; }
- void setPoint2(QPointF p) { m_point2 = p; }
- QPointF startPoint2() const { return m_startPoint2; }
- void setStartPoint2(QPointF p) { m_startPoint2 = p; }
- int pointCount() const { return m_pointCount; }
- void setPointCount(int count) { m_pointCount = count; }
-
- bool accepted() const { return m_accepted; }
- void setAccepted(bool a) { m_accepted = a; }
-
-private:
- QPointF m_center;
- QPointF m_startCenter;
- QPointF m_lastCenter;
- qreal m_scale;
- qreal m_lastScale;
- qreal m_angle;
- qreal m_lastAngle;
- qreal m_rotation;
- QPointF m_point1;
- QPointF m_point2;
- QPointF m_startPoint1;
- QPointF m_startPoint2;
- int m_pointCount;
- bool m_accepted;
-};
-
-
-class QQuickMouseEvent;
-class QQuickPinchAreaPrivate;
-class Q_AUTOTEST_EXPORT QQuickPinchArea : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(QQuickPinch *pinch READ pinch CONSTANT)
-
-public:
- QQuickPinchArea(QQuickItem *parent=0);
- ~QQuickPinchArea();
-
- bool isEnabled() const;
- void setEnabled(bool);
-
- QQuickPinch *pinch();
-
-Q_SIGNALS:
- void enabledChanged();
- void pinchStarted(QQuickPinchEvent *pinch);
- void pinchUpdated(QQuickPinchEvent *pinch);
- void pinchFinished(QQuickPinchEvent *pinch);
-
-protected:
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
- virtual void mouseUngrabEvent();
- virtual bool sendMouseEvent(QMouseEvent *event);
- virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
- virtual void touchEvent(QTouchEvent *event);
-
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual void itemChange(ItemChange change, const ItemChangeData& value);
-
-private:
- void updatePinch();
- void handlePress();
- void handleRelease();
-
-private:
- Q_DISABLE_COPY(QQuickPinchArea)
- Q_DECLARE_PRIVATE(QQuickPinchArea)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPinch)
-QML_DECLARE_TYPE(QQuickPinchEvent)
-QML_DECLARE_TYPE(QQuickPinchArea)
-
-QT_END_HEADER
-
-#endif // QQUICKPINCHAREA_H
-
diff --git a/src/declarative/items/qquickpositioners.cpp b/src/declarative/items/qquickpositioners.cpp
deleted file mode 100644
index 08fa4b1724..0000000000
--- a/src/declarative/items/qquickpositioners.cpp
+++ /dev/null
@@ -1,1532 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickpositioners_p.h"
-#include "qquickpositioners_p_p.h"
-
-#include <QtDeclarative/qdeclarative.h>
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtCore/qmath.h>
-#include <QtCore/qcoreapplication.h>
-
-#include <private/qdeclarativestate_p.h>
-#include <private/qdeclarativestategroup_p.h>
-#include <private/qdeclarativestateoperations_p.h>
-#include <private/qdeclarativetransition_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static const QQuickItemPrivate::ChangeTypes watchedChanges
- = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::SiblingOrder
- | QQuickItemPrivate::Visibility
- | QQuickItemPrivate::Destroyed;
-
-void QQuickBasePositionerPrivate::watchChanges(QQuickItem *other)
-{
- QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other);
- otherPrivate->addItemChangeListener(this, watchedChanges);
-}
-
-void QQuickBasePositionerPrivate::unwatchChanges(QQuickItem* other)
-{
- QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other);
- otherPrivate->removeItemChangeListener(this, watchedChanges);
-}
-
-QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent)
- : QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent)
-{
- Q_D(QQuickBasePositioner);
- d->init(at);
-}
-/*!
- \internal
- \class QQuickBasePositioner
- \brief The QQuickBasePositioner class provides a base for QQuickGraphics layouts.
-
- To create a QQuickGraphics Positioner, simply subclass QQuickBasePositioner and implement
- doLayout(), which is automatically called when the layout might need
- updating. In doLayout() use the setX and setY functions from QQuickBasePositioner, and the
- base class will apply the positions along with the appropriate transitions. The items to
- position are provided in order as the protected member positionedItems.
-
- You also need to set a PositionerType, to declare whether you are positioning the x, y or both
- for the child items. Depending on the chosen type, only x or y changes will be applied.
-
- Note that the subclass is responsible for adding the spacing in between items.
-
- Positioning is usually delayed until before a frame is rendered, to batch multiple repositioning
- changes into one calculation.
-*/
-
-QQuickBasePositioner::QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent)
- : QQuickImplicitSizeItem(dd, parent)
-{
- Q_D(QQuickBasePositioner);
- d->init(at);
-}
-
-QQuickBasePositioner::~QQuickBasePositioner()
-{
- Q_D(QQuickBasePositioner);
- for (int i = 0; i < positionedItems.count(); ++i)
- d->unwatchChanges(positionedItems.at(i).item);
- positionedItems.clear();
-}
-
-void QQuickBasePositioner::updatePolish()
-{
- Q_D(QQuickBasePositioner);
- if (d->positioningDirty)
- prePositioning();
-}
-
-int QQuickBasePositioner::spacing() const
-{
- Q_D(const QQuickBasePositioner);
- return d->spacing;
-}
-
-void QQuickBasePositioner::setSpacing(int s)
-{
- Q_D(QQuickBasePositioner);
- if (s==d->spacing)
- return;
- d->spacing = s;
- d->setPositioningDirty();
- emit spacingChanged();
-}
-
-QDeclarativeTransition *QQuickBasePositioner::move() const
-{
- Q_D(const QQuickBasePositioner);
- return d->moveTransition;
-}
-
-void QQuickBasePositioner::setMove(QDeclarativeTransition *mt)
-{
- Q_D(QQuickBasePositioner);
- if (mt == d->moveTransition)
- return;
- d->moveTransition = mt;
- emit moveChanged();
-}
-
-QDeclarativeTransition *QQuickBasePositioner::add() const
-{
- Q_D(const QQuickBasePositioner);
- return d->addTransition;
-}
-
-void QQuickBasePositioner::setAdd(QDeclarativeTransition *add)
-{
- Q_D(QQuickBasePositioner);
- if (add == d->addTransition)
- return;
-
- d->addTransition = add;
- emit addChanged();
-}
-
-void QQuickBasePositioner::componentComplete()
-{
- QQuickItem::componentComplete();
- positionedItems.reserve(childItems().count());
- prePositioning();
- reportConflictingAnchors();
-}
-
-void QQuickBasePositioner::itemChange(ItemChange change, const ItemChangeData &value)
-{
- Q_D(QQuickBasePositioner);
- if (change == ItemChildAddedChange){
- d->setPositioningDirty();
- } else if (change == ItemChildRemovedChange) {
- QQuickItem *child = value.item;
- QQuickBasePositioner::PositionedItem posItem(child);
- int idx = positionedItems.find(posItem);
- if (idx >= 0) {
- d->unwatchChanges(child);
- positionedItems.remove(idx);
- }
- d->setPositioningDirty();
- }
-
- QQuickItem::itemChange(change, value);
-}
-
-void QQuickBasePositioner::prePositioning()
-{
- Q_D(QQuickBasePositioner);
- if (!isComponentComplete())
- return;
-
- if (d->doingPositioning)
- return;
-
- d->positioningDirty = false;
- d->doingPositioning = true;
- //Need to order children by creation order modified by stacking order
- QList<QQuickItem *> children = childItems();
-
- QPODVector<PositionedItem,8> oldItems;
- positionedItems.copyAndClear(oldItems);
- for (int ii = 0; ii < children.count(); ++ii) {
- QQuickItem *child = children.at(ii);
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
- PositionedItem *item = 0;
- PositionedItem posItem(child);
- int wIdx = oldItems.find(posItem);
- if (wIdx < 0) {
- d->watchChanges(child);
- positionedItems.append(posItem);
- item = &positionedItems[positionedItems.count()-1];
- item->isNew = true;
- if (!childPrivate->explicitVisible || !child->width() || !child->height())
- item->isVisible = false;
- } else {
- item = &oldItems[wIdx];
- // Items are only omitted from positioning if they are explicitly hidden
- // i.e. their positioning is not affected if an ancestor is hidden.
- if (!childPrivate->explicitVisible || !child->width() || !child->height()) {
- item->isVisible = false;
- } else if (!item->isVisible) {
- item->isVisible = true;
- item->isNew = true;
- } else {
- item->isNew = false;
- }
- positionedItems.append(*item);
- }
- }
- QSizeF contentSize(0,0);
- doPositioning(&contentSize);
- updateAttachedProperties();
- if (!d->addActions.isEmpty() || !d->moveActions.isEmpty())
- finishApplyTransitions();
- d->doingPositioning = false;
- //Set implicit size to the size of its children
- setImplicitSize(contentSize.width(), contentSize.height());
-}
-
-void QQuickBasePositioner::positionX(int x, const PositionedItem &target)
-{
- Q_D(QQuickBasePositioner);
- if (d->type == Horizontal || d->type == Both) {
- if (target.isNew) {
- if (!d->addTransition || !d->addTransition->enabled())
- target.item->setX(x);
- else
- d->addActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
- } else if (x != target.item->x()) {
- if (!d->moveTransition || !d->moveTransition->enabled())
- target.item->setX(x);
- else
- d->moveActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
- }
- }
-}
-
-void QQuickBasePositioner::positionY(int y, const PositionedItem &target)
-{
- Q_D(QQuickBasePositioner);
- if (d->type == Vertical || d->type == Both) {
- if (target.isNew) {
- if (!d->addTransition || !d->addTransition->enabled())
- target.item->setY(y);
- else
- d->addActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
- } else if (y != target.item->y()) {
- if (!d->moveTransition || !d->moveTransition->enabled())
- target.item->setY(y);
- else
- d->moveActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
- }
- }
-}
-
-void QQuickBasePositioner::finishApplyTransitions()
-{
- Q_D(QQuickBasePositioner);
- // Note that if a transition is not set the transition manager will
- // apply the changes directly, in the case add/move aren't set
- d->addTransitionManager.transition(d->addActions, d->addTransition);
- d->moveTransitionManager.transition(d->moveActions, d->moveTransition);
- d->addActions.clear();
- d->moveActions.clear();
-}
-
-QQuickPositionerAttached *QQuickBasePositioner::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickPositionerAttached(obj);
-}
-
-void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *specificProperty, QQuickItem *specificPropertyOwner) const
-{
- // If this function is deemed too expensive or shows up in profiles, it could
- // be changed to run only when there are attached properties present. This
- // could be a flag in the positioner that is set by the attached property
- // constructor.
- QQuickPositionerAttached *prevLastProperty = 0;
- QQuickPositionerAttached *lastProperty = 0;
-
- int visibleItemIndex = 0;
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (!child.item)
- continue;
-
- QQuickPositionerAttached *property = 0;
-
- if (specificProperty) {
- if (specificPropertyOwner == child.item) {
- property = specificProperty;
- }
- } else {
- property = static_cast<QQuickPositionerAttached *>(qmlAttachedPropertiesObject<QQuickBasePositioner>(child.item, false));
- }
-
- if (child.isVisible) {
- if (property) {
- property->setIndex(visibleItemIndex);
- property->setIsFirstItem(visibleItemIndex == 0);
-
- if (property->isLastItem())
- prevLastProperty = property;
- }
-
- lastProperty = property;
- ++visibleItemIndex;
- } else if (property) {
- property->setIndex(-1);
- property->setIsFirstItem(false);
- property->setIsLastItem(false);
- }
- }
-
- if (prevLastProperty && prevLastProperty != lastProperty)
- prevLastProperty->setIsLastItem(false);
- if (lastProperty)
- lastProperty->setIsLastItem(true);
-}
-
-/*!
- \qmlclass Positioner QQuickPositionerAttached
- \inqmlmodule QtQuick 2
- \ingroup qml-positioning-elements
- \brief The Positioner type provides attached properties that contain details on where an item exists in a positioner.
-
- Positioner items (such as Column, Row, Flow and Grid) provide automatic layout
- for child items. Attaching this property allows a child item to determine
- where it exists within the positioner.
-*/
-
-QQuickPositionerAttached::QQuickPositionerAttached(QObject *parent) : QObject(parent), m_index(-1), m_isFirstItem(false), m_isLastItem(false)
-{
- QQuickItem *attachedItem = qobject_cast<QQuickItem *>(parent);
- if (attachedItem) {
- QQuickBasePositioner *positioner = qobject_cast<QQuickBasePositioner *>(attachedItem->parent());
- if (positioner) {
- positioner->updateAttachedProperties(this, attachedItem);
- }
- }
-}
-
-/*!
- \qmlattachedproperty Item QtQuick2::Positioner::index
-
- This property allows the item to determine
- its index within the positioner.
-*/
-void QQuickPositionerAttached::setIndex(int index)
-{
- if (m_index == index)
- return;
- m_index = index;
- emit indexChanged();
-}
-
-/*!
- \qmlattachedproperty Item QtQuick2::Positioner::isFirstItem
- \qmlattachedproperty Item QtQuick2::Positioner::isLastItem
-
- These properties allow the item to determine if it
- is the first or last item in the positioner, respectively.
-*/
-void QQuickPositionerAttached::setIsFirstItem(bool isFirstItem)
-{
- if (m_isFirstItem == isFirstItem)
- return;
- m_isFirstItem = isFirstItem;
- emit isFirstItemChanged();
-}
-
-void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
-{
- if (m_isLastItem == isLastItem)
- return;
- m_isLastItem = isLastItem;
- emit isLastItemChanged();
-}
-
-/*!
- \qmlclass Column QQuickColumn
- \inqmlmodule QtQuick 2
- \ingroup qml-positioning-elements
- \brief The Column item arranges its children vertically.
- \inherits Item
-
- The Column item positions its child items so that they are vertically
- aligned and not overlapping.
-
- Spacing between items can be added using the \l spacing property.
- Transitions can be used for cases where items managed by a Column are
- added or moved. These are stored in the \l add and \l move properties
- respectively.
-
- See \l{Using QML Positioner and Repeater Items} for more details about this item and other
- related items.
-
- \section1 Example Usage
-
- The following example positions differently shaped rectangles using a Column
- item.
-
- \image verticalpositioner_example.png
-
- \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
-
- \section1 Using Transitions
-
- Transitions can be used to animate items that are added to, moved within,
- or removed from a Column item. The \l add and \l move properties can be set to
- the transitions that will be applied when items are added to, removed from,
- or re-positioned within a Column item.
-
- The use of transitions with positioners is described in more detail in the
- \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
- Positioner and Repeater Items} document.
-
- \image verticalpositioner_transition.gif
-
- \qml
- Column {
- spacing: 2
- add: Transition {
- // Define an animation for adding a new item...
- }
- move: Transition {
- // Define an animation for moving items within the column...
- }
- // ...
- }
- \endqml
-
- \section1 Limitations
-
- Note that the positioner assumes that the x and y positions of its children
- will not change. If you manually change the x or y properties in script, bind
- the x or y properties, use anchors on a child of a positioner, or have the
- height of a child depend on the position of a child, then the
- positioner may exhibit strange behavior. If you need to perform any of these
- actions, consider positioning the items without the use of a Column.
-
- Items with a width or height of 0 will not be positioned.
-
- Positioning is batched and syncronized with painting to reduce the number of
- calculations needed. This means that positioners may not reposition items immediately
- when changes occur, but it will have moved by the next frame.
-
- \sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty Transition QtQuick2::Column::add
-
- This property holds the transition to be applied when adding an
- item to the positioner. The transition will only be applied to the
- added item(s). Positioner transitions will only affect the
- position (x, y) of items.
-
- For a positioner, adding an item can mean that either the object
- has been created or reparented, and thus is now a child or the
- positioner, or that the object has had its opacity increased from
- zero, and thus is now visible.
-
- \sa move
-*/
-/*!
- \qmlproperty Transition QtQuick2::Column::move
-
- This property holds the transition to apply when moving an item
- within the positioner. Positioner transitions will only affect
- the position (x, y) of items.
-
- This transition can be performed when other items are added or removed
- from the positioner, or when items resize themselves.
-
- \image positioner-move.gif
-
- \qml
- Column {
- move: Transition {
- NumberAnimation {
- properties: "y"
- duration: 1000
- }
- }
- }
- \endqml
-
- \sa add, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty int QtQuick2::Column::spacing
-
- The spacing is the amount in pixels left empty between adjacent
- items. The default spacing is 0.
-
- \sa Grid::spacing
-*/
-QQuickColumn::QQuickColumn(QQuickItem *parent)
-: QQuickBasePositioner(Vertical, parent)
-{
-}
-
-void QQuickColumn::doPositioning(QSizeF *contentSize)
-{
- int voffset = 0;
-
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (!child.item || !child.isVisible)
- continue;
-
- if (child.item->y() != voffset)
- positionY(voffset, child);
-
- contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
-
- voffset += child.item->height();
- voffset += spacing();
- }
-
- if (voffset != 0)//If we positioned any items, undo the spacing from the last item
- voffset -= spacing();
- contentSize->setHeight(voffset);
-}
-
-void QQuickColumn::reportConflictingAnchors()
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (child.item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
- if (anchors) {
- QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
- if (usedAnchors & QQuickAnchors::TopAnchor ||
- usedAnchors & QQuickAnchors::BottomAnchor ||
- usedAnchors & QQuickAnchors::VCenterAnchor ||
- anchors->fill() || anchors->centerIn()) {
- d->anchorConflict = true;
- break;
- }
- }
- }
- }
- if (d->anchorConflict) {
- qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
- }
-}
-/*!
- \qmlclass Row QQuickRow
- \inqmlmodule QtQuick 2
- \ingroup qml-positioning-elements
- \brief The Row item arranges its children horizontally.
- \inherits Item
-
- The Row item positions its child items so that they are horizontally
- aligned and not overlapping.
-
- Use \l spacing to set the spacing between items in a Row, and use the
- \l add and \l move properties to set the transitions that should be applied
- when items are added to, removed from, or re-positioned within the Row.
-
- See \l{Using QML Positioner and Repeater Items} for more details about this item and other
- related items.
-
- \section1 Example Usage
-
- The following example lays out differently shaped rectangles using a Row.
-
- \image horizontalpositioner_example.png
-
- \snippet doc/src/snippets/declarative/row/row.qml document
-
- \section1 Using Transitions
-
- Transitions can be used to animate items that are added to, moved within,
- or removed from a Grid item. The \l add and \l move properties can be set to
- the transitions that will be applied when items are added to, removed from,
- or re-positioned within a Row item.
-
- \section1 Limitations
-
- Note that the positioner assumes that the x and y positions of its children
- will not change. If you manually change the x or y properties in script, bind
- the x or y properties, use anchors on a child of a positioner, or have the
- width of a child depend on the position of a child, then the
- positioner may exhibit strange behavior. If you need to perform any of these
- actions, consider positioning the items without the use of a Row.
-
- Items with a width or height of 0 will not be positioned.
-
- Positioning is batched and syncronized with painting to reduce the number of
- calculations needed. This means that positioners may not reposition items immediately
- when changes occur, but it will have moved by the next frame.
-
- \sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty Transition QtQuick2::Row::add
-
- This property holds the transition to be applied when adding an
- item to the positioner. The transition will only be applied to the
- added item(s). Positioner transitions will only affect the
- position (x, y) of items.
-
- For a positioner, adding an item can mean that either the object
- has been created or reparented, and thus is now a child or the
- positioner, or that the object has had its opacity increased from
- zero, and thus is now visible.
-
- \sa move
-*/
-/*!
- \qmlproperty Transition QtQuick2::Row::move
-
- This property holds the transition to be applied when moving an
- item within the positioner. Positioner transitions will only affect
- the position (x, y) of items.
-
- This transition can be performed when other items are added or removed
- from the positioner, or when items resize themselves.
-
- \qml
- Row {
- id: positioner
- move: Transition {
- NumberAnimation {
- properties: "x"
- duration: 1000
- }
- }
- }
- \endqml
-
- \sa add, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty int QtQuick2::Row::spacing
-
- The spacing is the amount in pixels left empty between adjacent
- items. The default spacing is 0.
-
- \sa Grid::spacing
-*/
-
-QQuickRow::QQuickRow(QQuickItem *parent)
-: QQuickBasePositioner(Horizontal, parent)
-{
-}
-/*!
- \qmlproperty enumeration QtQuick2::Row::layoutDirection
-
- This property holds the layoutDirection of the row.
-
- Possible values:
-
- \list
- \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set,
- the left anchor remains to the left of the row.
- \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set,
- the right anchor remains to the right of the row.
- \endlist
-
- \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
-*/
-
-Qt::LayoutDirection QQuickRow::layoutDirection() const
-{
- return QQuickBasePositionerPrivate::getLayoutDirection(this);
-}
-
-void QQuickRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
- if (d->layoutDirection != layoutDirection) {
- d->layoutDirection = layoutDirection;
- // For RTL layout the positioning changes when the width changes.
- if (d->layoutDirection == Qt::RightToLeft)
- d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
- else
- d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
- prePositioning();
- emit layoutDirectionChanged();
- emit effectiveLayoutDirectionChanged();
- }
-}
-/*!
- \qmlproperty enumeration QtQuick2::Row::effectiveLayoutDirection
- This property holds the effective layout direction of the row positioner.
-
- When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
- the visual layout direction of the row positioner will be mirrored. However, the
- property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
-
- \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
-*/
-
-Qt::LayoutDirection QQuickRow::effectiveLayoutDirection() const
-{
- return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
-}
-
-void QQuickRow::doPositioning(QSizeF *contentSize)
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
- int hoffset = 0;
-
- QList<int> hoffsets;
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (!child.item || !child.isVisible)
- continue;
-
- if (d->isLeftToRight()) {
- if (child.item->x() != hoffset)
- positionX(hoffset, child);
- } else {
- hoffsets << hoffset;
- }
-
- contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
-
- hoffset += child.item->width();
- hoffset += spacing();
- }
-
- if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item
- hoffset -= spacing();
- contentSize->setWidth(hoffset);
-
- if (d->isLeftToRight())
- return;
-
- //Right to Left layout
- int end = 0;
- if (!widthValid())
- end = contentSize->width();
- else
- end = width();
-
- int acc = 0;
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (!child.item || !child.isVisible)
- continue;
- hoffset = end - hoffsets[acc++] - child.item->width();
- if (child.item->x() != hoffset)
- positionX(hoffset, child);
- }
-}
-
-void QQuickRow::reportConflictingAnchors()
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (child.item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
- if (anchors) {
- QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
- if (usedAnchors & QQuickAnchors::LeftAnchor ||
- usedAnchors & QQuickAnchors::RightAnchor ||
- usedAnchors & QQuickAnchors::HCenterAnchor ||
- anchors->fill() || anchors->centerIn()) {
- d->anchorConflict = true;
- break;
- }
- }
- }
- }
- if (d->anchorConflict)
- qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row";
-}
-
-/*!
- \qmlclass Grid QQuickGrid
- \inqmlmodule QtQuick 2
- \ingroup qml-positioning-elements
- \brief The Grid item positions its children in a grid.
- \inherits Item
-
- The Grid item positions its child items so that they are
- aligned in a grid and are not overlapping.
-
- The grid positioner calculates a grid of rectangular cells of sufficient
- size to hold all items, placing the items in the cells, from left to right
- and top to bottom. Each item is positioned in the top-left corner of its
- cell with position (0, 0).
-
- A Grid defaults to four columns, and as many rows as are necessary to
- fit all child items. The number of rows and columns can be constrained
- by setting the \l rows and \l columns properties.
-
- Spacing can be added between child items by setting the \l spacing
- property. The amount of spacing applied will be the same in the
- horizontal and vertical directions.
-
- See \l{Using QML Positioner and Repeater Items} for more details about this item and other
- related items.
-
- \section1 Example Usage
-
- The following example demonstrates this.
-
- \image gridLayout_example.png
-
- \snippet doc/src/snippets/declarative/grid/grid.qml document
-
- \section1 Using Transitions
-
- Transitions can be used to animate items that are added to, moved within,
- or removed from a Grid item. The \l add and \l move properties can be set to
- the transitions that will be applied when items are added to, removed from,
- or re-positioned within a Grid item.
-
- \section1 Limitations
-
- Note that the positioner assumes that the x and y positions of its children
- will not change. If you manually change the x or y properties in script, bind
- the x or y properties, use anchors on a child of a positioner, or have the
- width or height of a child depend on the position of a child, then the
- positioner may exhibit strange behavior. If you need to perform any of these
- actions, consider positioning the items without the use of a Grid.
-
- Items with a width or height of 0 will not be positioned.
-
- Positioning is batched and syncronized with painting to reduce the number of
- calculations needed. This means that positioners may not reposition items immediately
- when changes occur, but it will have moved by the next frame.
-
- \sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty Transition QtQuick2::Grid::add
-
- This property holds the transition to be applied when adding an
- item to the positioner. The transition will only be applied to the
- added item(s). Positioner transitions will only affect the
- position (x, y) of items.
-
- For a positioner, adding an item can mean that either the object
- has been created or reparented, and thus is now a child or the
- positioner, or that the object has had its opacity increased from
- zero, and thus is now visible.
-
- \sa move
-*/
-/*!
- \qmlproperty Transition QtQuick2::Grid::move
-
- This property holds the transition to be applied when moving an
- item within the positioner. Positioner transitions will only affect
- the position (x, y) of items.
-
- This transition can be performed when other items are added or removed
- from the positioner, or when items resize themselves.
-
- \qml
- Grid {
- move: Transition {
- NumberAnimation {
- properties: "x,y"
- duration: 1000
- }
- }
- }
- \endqml
-
- \sa add, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty int QtQuick2::Grid::spacing
-
- The spacing is the amount in pixels left empty between adjacent
- items. The default spacing is 0.
-
- The below example places a Grid containing a red, a blue and a
- green rectangle on a gray background. The area the grid positioner
- occupies is colored white. The positioner on the left has the
- no spacing (the default), and the positioner on the right has
- a spacing of 6.
-
- \inlineimage qml-grid-no-spacing.png
- \inlineimage qml-grid-spacing.png
-
- \sa rows, columns
-*/
-QQuickGrid::QQuickGrid(QQuickItem *parent) :
- QQuickBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_rowSpacing(-1), m_columnSpacing(-1), m_flow(LeftToRight)
-{
-}
-
-/*!
- \qmlproperty int QtQuick2::Grid::columns
-
- This property holds the number of columns in the grid. The default
- number of columns is 4.
-
- If the grid does not have enough items to fill the specified
- number of columns, some columns will be of zero width.
-*/
-
-/*!
- \qmlproperty int QtQuick2::Grid::rows
- This property holds the number of rows in the grid.
-
- If the grid does not have enough items to fill the specified
- number of rows, some rows will be of zero width.
-*/
-
-void QQuickGrid::setColumns(const int columns)
-{
- if (columns == m_columns)
- return;
- m_columns = columns;
- prePositioning();
- emit columnsChanged();
-}
-
-void QQuickGrid::setRows(const int rows)
-{
- if (rows == m_rows)
- return;
- m_rows = rows;
- prePositioning();
- emit rowsChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Grid::flow
- This property holds the flow of the layout.
-
- Possible values are:
-
- \list
- \o Grid.LeftToRight (default) - Items are positioned next to
- each other in the \l layoutDirection, then wrapped to the next line.
- \o Grid.TopToBottom - Items are positioned next to each
- other from top to bottom, then wrapped to the next column.
- \endlist
-*/
-QQuickGrid::Flow QQuickGrid::flow() const
-{
- return m_flow;
-}
-
-void QQuickGrid::setFlow(Flow flow)
-{
- if (m_flow != flow) {
- m_flow = flow;
- prePositioning();
- emit flowChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQuick2::Grid::rowSpacing
-
- This property holds the spacing in pixels between rows.
-
- \sa columnSpacing
- \since QtQuick2.0
-*/
-void QQuickGrid::setRowSpacing(const int rowSpacing)
-{
- if (rowSpacing == m_rowSpacing)
- return;
- m_rowSpacing = rowSpacing;
- prePositioning();
- emit rowSpacingChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::Grid::columnSpacing
-
- This property holds the spacing in pixels between columns.
-
- \sa rowSpacing
- \since QtQuick2.0
-*/
-void QQuickGrid::setColumnSpacing(const int columnSpacing)
-{
- if (columnSpacing == m_columnSpacing)
- return;
- m_columnSpacing = columnSpacing;
- prePositioning();
- emit columnSpacingChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Grid::layoutDirection
-
- This property holds the layout direction of the layout.
-
- Possible values are:
-
- \list
- \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
- and left to right. The flow direction is dependent on the
- \l Grid::flow property.
- \o Qt.RightToLeft - Items are positioned from the top to bottom,
- and right to left. The flow direction is dependent on the
- \l Grid::flow property.
- \endlist
-
- \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
-*/
-Qt::LayoutDirection QQuickGrid::layoutDirection() const
-{
- return QQuickBasePositionerPrivate::getLayoutDirection(this);
-}
-
-void QQuickGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
- if (d->layoutDirection != layoutDirection) {
- d->layoutDirection = layoutDirection;
- // For RTL layout the positioning changes when the width changes.
- if (d->layoutDirection == Qt::RightToLeft)
- d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
- else
- d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
- prePositioning();
- emit layoutDirectionChanged();
- emit effectiveLayoutDirectionChanged();
- }
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Grid::effectiveLayoutDirection
- This property holds the effective layout direction of the grid positioner.
-
- When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
- the visual layout direction of the grid positioner will be mirrored. However, the
- property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
-
- \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
-*/
-Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const
-{
- return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
-}
-
-void QQuickGrid::doPositioning(QSizeF *contentSize)
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
- int c = m_columns;
- int r = m_rows;
- //Is allocating the extra QPODVector too much overhead?
- QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items
- visibleItems.reserve(positionedItems.count());
- for (int i=0; i<positionedItems.count(); i++)
- if (positionedItems[i].item && positionedItems[i].isVisible)
- visibleItems.append(positionedItems[i]);
-
- int numVisible = visibleItems.count();
- if (m_columns <= 0 && m_rows <= 0){
- c = 4;
- r = (numVisible+3)/4;
- } else if (m_rows <= 0){
- r = (numVisible+(m_columns-1))/m_columns;
- } else if (m_columns <= 0){
- c = (numVisible+(m_rows-1))/m_rows;
- }
-
- if (r==0 || c==0)
- return; //Nothing to do
-
- QList<int> maxColWidth;
- QList<int> maxRowHeight;
- int childIndex =0;
- if (m_flow == LeftToRight) {
- for (int i=0; i < r; i++){
- for (int j=0; j < c; j++){
- if (j==0)
- maxRowHeight << 0;
- if (i==0)
- maxColWidth << 0;
-
- if (childIndex == visibleItems.count())
- break;
-
- const PositionedItem &child = visibleItems.at(childIndex++);
- if (child.item->width() > maxColWidth[j])
- maxColWidth[j] = child.item->width();
- if (child.item->height() > maxRowHeight[i])
- maxRowHeight[i] = child.item->height();
- }
- }
- } else {
- for (int j=0; j < c; j++){
- for (int i=0; i < r; i++){
- if (j==0)
- maxRowHeight << 0;
- if (i==0)
- maxColWidth << 0;
-
- if (childIndex == visibleItems.count())
- break;
-
- const PositionedItem &child = visibleItems.at(childIndex++);
- if (child.item->width() > maxColWidth[j])
- maxColWidth[j] = child.item->width();
- if (child.item->height() > maxRowHeight[i])
- maxRowHeight[i] = child.item->height();
- }
- }
- }
-
- int columnSpacing = m_columnSpacing;
- if (columnSpacing == -1)
- columnSpacing = spacing();
-
- int rowSpacing = m_rowSpacing;
- if (rowSpacing == -1)
- rowSpacing = spacing();
-
- int widthSum = 0;
- for (int j=0; j < maxColWidth.size(); j++){
- if (j)
- widthSum += columnSpacing;
- widthSum += maxColWidth[j];
- }
-
- int heightSum = 0;
- for (int i=0; i < maxRowHeight.size(); i++){
- if (i)
- heightSum += rowSpacing;
- heightSum += maxRowHeight[i];
- }
-
- contentSize->setHeight(heightSum);
- contentSize->setWidth(widthSum);
-
- int end = 0;
- if (widthValid())
- end = width();
- else
- end = widthSum;
-
- int xoffset=0;
- if (!d->isLeftToRight())
- xoffset = end;
- int yoffset=0;
- int curRow =0;
- int curCol =0;
- for (int i = 0; i < visibleItems.count(); ++i) {
- const PositionedItem &child = visibleItems.at(i);
- int childXOffset = xoffset;
- if (!d->isLeftToRight())
- childXOffset -= child.item->width();
- if ((child.item->x() != childXOffset) || (child.item->y() != yoffset)){
- positionX(childXOffset, child);
- positionY(yoffset, child);
- }
-
- if (m_flow == LeftToRight) {
- if (d->isLeftToRight())
- xoffset += maxColWidth[curCol]+columnSpacing;
- else
- xoffset -= maxColWidth[curCol]+columnSpacing;
- curCol++;
- curCol%=c;
- if (!curCol){
- yoffset += maxRowHeight[curRow]+rowSpacing;
- if (d->isLeftToRight())
- xoffset = 0;
- else
- xoffset = end;
- curRow++;
- if (curRow>=r)
- break;
- }
- } else {
- yoffset+=maxRowHeight[curRow]+rowSpacing;
- curRow++;
- curRow%=r;
- if (!curRow){
- if (d->isLeftToRight())
- xoffset += maxColWidth[curCol]+columnSpacing;
- else
- xoffset -= maxColWidth[curCol]+columnSpacing;
- yoffset=0;
- curCol++;
- if (curCol>=c)
- break;
- }
- }
- }
-}
-
-void QQuickGrid::reportConflictingAnchors()
-{
- QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (child.item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
- if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
- d->anchorConflict = true;
- break;
- }
- }
- }
- if (d->anchorConflict)
- qmlInfo(this) << "Cannot specify anchors for items inside Grid";
-}
-
-/*!
- \qmlclass Flow QQuickFlow
- \inqmlmodule QtQuick 2
- \ingroup qml-positioning-elements
- \brief The Flow item arranges its children side by side, wrapping as necessary.
- \inherits Item
-
- The Flow item positions its child items like words on a page, wrapping them
- to create rows or columns of items that do not overlap.
-
- Spacing between items can be added using the \l spacing property.
- Transitions can be used for cases where items managed by a Column are
- added or moved. These are stored in the \l add and \l move properties
- respectively.
-
- See \l{Using QML Positioner and Repeater Items} for more details about this item and other
- related items.
-
- \section1 Example Usage
-
- The following example positions \l Text items within a parent item using
- a Flow item.
-
- \image qml-flow-snippet.png
-
- \snippet doc/src/snippets/declarative/flow.qml flow item
-
- \section1 Using Transitions
-
- Transitions can be used to animate items that are added to, moved within,
- or removed from a Flow item. The \l add and \l move properties can be set to
- the transitions that will be applied when items are added to, removed from,
- or re-positioned within a Flow item.
-
- The use of transitions with positioners is described in more detail in the
- \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
- Positioner and Repeater Items} document.
-
- \section1 Limitations
-
- Note that the positioner assumes that the x and y positions of its children
- will not change. If you manually change the x or y properties in script, bind
- the x or y properties, use anchors on a child of a positioner, or have the
- width or height of a child depend on the position of a child, then the
- positioner may exhibit strange behavior. If you need to perform any of these
- actions, consider positioning the items without the use of a Flow.
-
- Items with a width or height of 0 will not be positioned.
-
- Positioning is batched and syncronized with painting to reduce the number of
- calculations needed. This means that positioners may not reposition items immediately
- when changes occur, but it will have moved by the next frame.
-
- \sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty Transition QtQuick2::Flow::add
-
- This property holds the transition to be applied when adding an
- item to the positioner. The transition will only be applied to the
- added item(s). Positioner transitions will only affect the
- position (x, y) of items.
-
- For a positioner, adding an item can mean that either the object
- has been created or reparented, and thus is now a child or the
- positioner, or that the object has had its opacity increased from
- zero, and thus is now visible.
-
- \sa move
-*/
-/*!
- \qmlproperty Transition QtQuick2::Flow::move
-
- This property holds the transition to be applied when moving an
- item within the positioner. Positioner transitions will only affect
- the position (x, y) of items.
-
- This transition can be performed when other items are added or removed
- from the positioner, or when items resize themselves.
-
- \qml
- Flow {
- id: positioner
- move: Transition {
- NumberAnimation {
- properties: "x,y"
- ease: "easeOutBounce"
- }
- }
- }
- \endqml
-
- \sa add, {declarative/positioners}{Positioners example}
-*/
-/*!
- \qmlproperty int QtQuick2::Flow::spacing
-
- spacing is the amount in pixels left empty between each adjacent
- item, and defaults to 0.
-
- \sa Grid::spacing
-*/
-
-class QQuickFlowPrivate : public QQuickBasePositionerPrivate
-{
- Q_DECLARE_PUBLIC(QQuickFlow)
-
-public:
- QQuickFlowPrivate()
- : QQuickBasePositionerPrivate(), flow(QQuickFlow::LeftToRight)
- {}
-
- QQuickFlow::Flow flow;
-};
-
-QQuickFlow::QQuickFlow(QQuickItem *parent)
-: QQuickBasePositioner(*(new QQuickFlowPrivate), Both, parent)
-{
- Q_D(QQuickFlow);
- // Flow layout requires relayout if its own size changes too.
- d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Flow::flow
- This property holds the flow of the layout.
-
- Possible values are:
-
- \list
- \o Flow.LeftToRight (default) - Items are positioned next to
- to each other according to the \l layoutDirection until the width of the Flow
- is exceeded, then wrapped to the next line.
- \o Flow.TopToBottom - Items are positioned next to each
- other from top to bottom until the height of the Flow is exceeded,
- then wrapped to the next column.
- \endlist
-*/
-QQuickFlow::Flow QQuickFlow::flow() const
-{
- Q_D(const QQuickFlow);
- return d->flow;
-}
-
-void QQuickFlow::setFlow(Flow flow)
-{
- Q_D(QQuickFlow);
- if (d->flow != flow) {
- d->flow = flow;
- prePositioning();
- emit flowChanged();
- }
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Flow::layoutDirection
-
- This property holds the layout direction of the layout.
-
- Possible values are:
-
- \list
- \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
- and left to right. The flow direction is dependent on the
- \l Flow::flow property.
- \o Qt.RightToLeft - Items are positioned from the top to bottom,
- and right to left. The flow direction is dependent on the
- \l Flow::flow property.
- \endlist
-
- \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
-*/
-
-Qt::LayoutDirection QQuickFlow::layoutDirection() const
-{
- Q_D(const QQuickFlow);
- return d->layoutDirection;
-}
-
-void QQuickFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
- Q_D(QQuickFlow);
- if (d->layoutDirection != layoutDirection) {
- d->layoutDirection = layoutDirection;
- prePositioning();
- emit layoutDirectionChanged();
- emit effectiveLayoutDirectionChanged();
- }
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Flow::effectiveLayoutDirection
- This property holds the effective layout direction of the flow positioner.
-
- When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
- the visual layout direction of the grid positioner will be mirrored. However, the
- property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
-
- \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
-*/
-
-Qt::LayoutDirection QQuickFlow::effectiveLayoutDirection() const
-{
- return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
-}
-
-void QQuickFlow::doPositioning(QSizeF *contentSize)
-{
- Q_D(QQuickFlow);
-
- int hoffset = 0;
- int voffset = 0;
- int linemax = 0;
- QList<int> hoffsets;
-
- for (int i = 0; i < positionedItems.count(); ++i) {
- const PositionedItem &child = positionedItems.at(i);
- if (!child.item || !child.isVisible)
- continue;
-
- if (d->flow == LeftToRight) {
- if (widthValid() && hoffset && hoffset + child.item->width() > width()) {
- hoffset = 0;
- voffset += linemax + spacing();
- linemax = 0;
- }
- } else {
- if (heightValid() && voffset && voffset + child.item->height() > height()) {
- voffset = 0;
- hoffset += linemax + spacing();
- linemax = 0;
- }
- }
-
- if (d->isLeftToRight()) {
- if (child.item->x() != hoffset)
- positionX(hoffset, child);
- } else {
- hoffsets << hoffset;
- }
- if (child.item->y() != voffset)
- positionY(voffset, child);
-
- contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width()));
- contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height()));
-
- if (d->flow == LeftToRight) {
- hoffset += child.item->width();
- hoffset += spacing();
- linemax = qMax(linemax, qCeil(child.item->height()));
- } else {
- voffset += child.item->height();
- voffset += spacing();
- linemax = qMax(linemax, qCeil(child.item->width()));
- }
- }
- if (d->isLeftToRight())
- return;
-
- int end;
- if (widthValid())
- end = width();
- else
- end = contentSize->width();
- int acc = 0;
- for (int i = 0; i < positionedItems.count(); ++i) {
- const PositionedItem &child = positionedItems.at(i);
- if (!child.item || !child.isVisible)
- continue;
- hoffset = end - hoffsets[acc++] - child.item->width();
- if (child.item->x() != hoffset)
- positionX(hoffset, child);
- }
-}
-
-void QQuickFlow::reportConflictingAnchors()
-{
- Q_D(QQuickFlow);
- for (int ii = 0; ii < positionedItems.count(); ++ii) {
- const PositionedItem &child = positionedItems.at(ii);
- if (child.item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
- if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
- d->anchorConflict = true;
- break;
- }
- }
- }
- if (d->anchorConflict)
- qmlInfo(this) << "Cannot specify anchors for items inside Flow";
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickpositioners_p.h b/src/declarative/items/qquickpositioners_p.h
deleted file mode 100644
index b8e8879205..0000000000
--- a/src/declarative/items/qquickpositioners_p.h
+++ /dev/null
@@ -1,295 +0,0 @@
-// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKPOSITIONERS_P_H
-#define QQUICKPOSITIONERS_P_H
-
-#include "qquickimplicitsizeitem_p.h"
-
-#include <private/qdeclarativestate_p.h>
-#include <private/qpodvector_p.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qstring.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickBasePositionerPrivate;
-
-class QQuickPositionerAttached : public QObject
-{
- Q_OBJECT
-
-public:
- QQuickPositionerAttached(QObject *parent);
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- Q_PROPERTY(bool isFirstItem READ isFirstItem NOTIFY isFirstItemChanged)
- Q_PROPERTY(bool isLastItem READ isLastItem NOTIFY isLastItemChanged)
-
- int index() const { return m_index; }
- void setIndex(int index);
-
- bool isFirstItem() const { return m_isFirstItem; }
- void setIsFirstItem(bool isFirstItem);
-
- bool isLastItem() const { return m_isLastItem; }
- void setIsLastItem(bool isLastItem);
-
-Q_SIGNALS:
- void indexChanged();
- void isFirstItemChanged();
- void isLastItemChanged();
-
-private:
- int m_index;
- bool m_isFirstItem;
- bool m_isLastItem;
-};
-
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeItem
-{
- Q_OBJECT
-
- Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
- Q_PROPERTY(QDeclarativeTransition *move READ move WRITE setMove NOTIFY moveChanged)
- Q_PROPERTY(QDeclarativeTransition *add READ add WRITE setAdd NOTIFY addChanged)
-public:
- enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
- QQuickBasePositioner(PositionerType, QQuickItem *parent);
- ~QQuickBasePositioner();
-
- int spacing() const;
- void setSpacing(int);
-
- QDeclarativeTransition *move() const;
- void setMove(QDeclarativeTransition *);
-
- QDeclarativeTransition *add() const;
- void setAdd(QDeclarativeTransition *);
-
- static QQuickPositionerAttached *qmlAttachedProperties(QObject *obj);
-
- void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const;
-
-protected:
- QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent);
- virtual void componentComplete();
- virtual void itemChange(ItemChange, const ItemChangeData &);
- void finishApplyTransitions();
-
- virtual void updatePolish();
-
-Q_SIGNALS:
- void spacingChanged();
- void moveChanged();
- void addChanged();
-
-protected Q_SLOTS:
- void prePositioning();
-
-protected:
- virtual void doPositioning(QSizeF *contentSize)=0;
- virtual void reportConflictingAnchors()=0;
- class PositionedItem {
- public :
- PositionedItem(QQuickItem *i) : item(i), isNew(false), isVisible(true) {}
- bool operator==(const PositionedItem &other) const { return other.item == item; }
- QQuickItem *item;
- bool isNew;
- bool isVisible;
- };
-
- QPODVector<PositionedItem,8> positionedItems;
- void positionX(int,const PositionedItem &target);
- void positionY(int,const PositionedItem &target);
-
-private:
- Q_DISABLE_COPY(QQuickBasePositioner)
- Q_DECLARE_PRIVATE(QQuickBasePositioner)
-};
-
-class Q_AUTOTEST_EXPORT QQuickColumn : public QQuickBasePositioner
-{
- Q_OBJECT
-public:
- QQuickColumn(QQuickItem *parent=0);
-
-protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
-private:
- Q_DISABLE_COPY(QQuickColumn)
-};
-
-class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner
-{
- Q_OBJECT
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-public:
- QQuickRow(QQuickItem *parent=0);
-
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection (Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
-
-Q_SIGNALS:
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
-
-protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
-private:
- Q_DISABLE_COPY(QQuickRow)
-};
-
-class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner
-{
- Q_OBJECT
- Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
- Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
- Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
- Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
- Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-
-public:
- QQuickGrid(QQuickItem *parent=0);
-
- int rows() const {return m_rows;}
- void setRows(const int rows);
-
- int columns() const {return m_columns;}
- void setColumns(const int columns);
-
- int rowSpacing() const { return m_rowSpacing; }
- void setRowSpacing(int);
-
- int columnSpacing() const { return m_columnSpacing; }
- void setColumnSpacing(int);
-
- Q_ENUMS(Flow)
- enum Flow { LeftToRight, TopToBottom };
- Flow flow() const;
- void setFlow(Flow);
-
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection (Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
-
-Q_SIGNALS:
- void rowsChanged();
- void columnsChanged();
- void flowChanged();
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
- void rowSpacingChanged();
- void columnSpacingChanged();
-
-protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
-
-private:
- int m_rows;
- int m_columns;
- int m_rowSpacing;
- int m_columnSpacing;
- Flow m_flow;
- Q_DISABLE_COPY(QQuickGrid)
-};
-
-class QQuickFlowPrivate;
-class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner
-{
- Q_OBJECT
- Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
-public:
- QQuickFlow(QQuickItem *parent=0);
-
- Q_ENUMS(Flow)
- enum Flow { LeftToRight, TopToBottom };
- Flow flow() const;
- void setFlow(Flow);
-
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection (Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
-
-Q_SIGNALS:
- void flowChanged();
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
-
-protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
-protected:
- QQuickFlow(QQuickFlowPrivate &dd, QQuickItem *parent);
-private:
- Q_DISABLE_COPY(QQuickFlow)
- Q_DECLARE_PRIVATE(QQuickFlow)
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickColumn)
-QML_DECLARE_TYPE(QQuickRow)
-QML_DECLARE_TYPE(QQuickGrid)
-QML_DECLARE_TYPE(QQuickFlow)
-
-QML_DECLARE_TYPE(QQuickBasePositioner)
-QML_DECLARE_TYPEINFO(QQuickBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-
-#endif // QQUICKPOSITIONERS_P_H
diff --git a/src/declarative/items/qquickpositioners_p_p.h b/src/declarative/items/qquickpositioners_p_p.h
deleted file mode 100644
index 86c6c74ba6..0000000000
--- a/src/declarative/items/qquickpositioners_p_p.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKPOSITIONERS_P_P_H
-#define QQUICKPOSITIONERS_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qquickpositioners_p.h"
-#include "qquickimplicitsizeitem_p_p.h"
-
-#include <private/qdeclarativestate_p.h>
-#include <private/qdeclarativetransitionmanager_p_p.h>
-#include <private/qdeclarativestateoperations_p.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qtimer.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public QQuickItemChangeListener
-{
- Q_DECLARE_PUBLIC(QQuickBasePositioner)
-
-public:
- QQuickBasePositionerPrivate()
- : spacing(0), type(QQuickBasePositioner::None)
- , moveTransition(0), addTransition(0), positioningDirty(false)
- , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
- {
- }
-
- void init(QQuickBasePositioner::PositionerType at)
- {
- type = at;
- childrenDoNotOverlap = true;
- }
-
- int spacing;
-
- QQuickBasePositioner::PositionerType type;
- QDeclarativeTransition *moveTransition;
- QDeclarativeTransition *addTransition;
- QDeclarativeStateOperation::ActionList addActions;
- QDeclarativeStateOperation::ActionList moveActions;
- QDeclarativeTransitionManager addTransitionManager;
- QDeclarativeTransitionManager moveTransitionManager;
-
- void watchChanges(QQuickItem *other);
- void unwatchChanges(QQuickItem* other);
- void setPositioningDirty() {
- Q_Q(QQuickBasePositioner);
- if (!positioningDirty) {
- positioningDirty = true;
- q->polish();
- }
- }
-
- bool positioningDirty : 1;
- bool doingPositioning : 1;
- bool anchorConflict : 1;
-
- Qt::LayoutDirection layoutDirection;
-
- void mirrorChange() {
- if (type != QQuickBasePositioner::Vertical)
- setPositioningDirty();
- }
- bool isLeftToRight() const {
- if (type == QQuickBasePositioner::Vertical)
- return true;
- else
- return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight;
- }
-
- virtual void itemSiblingOrderChanged(QQuickItem* other)
- {
- Q_UNUSED(other);
- setPositioningDirty();
- }
-
- void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
- {
- if (newGeometry.size() != oldGeometry.size())
- setPositioningDirty();
- }
-
- virtual void itemVisibilityChanged(QQuickItem *)
- {
- setPositioningDirty();
- }
-
- void itemDestroyed(QQuickItem *item)
- {
- Q_Q(QQuickBasePositioner);
- q->positionedItems.removeOne(QQuickBasePositioner::PositionedItem(item));
- }
-
- static Qt::LayoutDirection getLayoutDirection(const QQuickBasePositioner *positioner)
- {
- return positioner->d_func()->layoutDirection;
- }
-
- static Qt::LayoutDirection getEffectiveLayoutDirection(const QQuickBasePositioner *positioner)
- {
- if (positioner->d_func()->effectiveLayoutMirror)
- return positioner->d_func()->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
- else
- return positioner->d_func()->layoutDirection;
- }
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKPOSITIONERS_P_P_H
diff --git a/src/declarative/items/qquickrectangle.cpp b/src/declarative/items/qquickrectangle.cpp
deleted file mode 100644
index c3cbaaa00e..0000000000
--- a/src/declarative/items/qquickrectangle.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickrectangle_p.h"
-#include "qquickrectangle_p_p.h"
-
-#include <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-#include <QtGui/qpixmapcache.h>
-#include <QtCore/qstringbuilder.h>
-#include <QtCore/qmath.h>
-
-QT_BEGIN_NAMESPACE
-
-// XXX todo - should we change rectangle to draw entirely within its width/height?
-/*!
- \internal
- \class QQuickPen
- \brief The QQuickPen class provides a pen used for drawing rectangle borders on a QQuickView.
-
- By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
- width is 1) or a width (then the default color is black).
-
- A width of 1 indicates is a single-pixel line on the border of the item being painted.
-
- Example:
- \qml
- Rectangle {
- border.width: 2
- border.color: "red"
- }
- \endqml
-*/
-
-QQuickPen::QQuickPen(QObject *parent)
- : QObject(parent)
- , m_width(1)
- , m_color("#000000")
- , m_aligned(true)
- , m_valid(false)
-{
-}
-
-qreal QQuickPen::width() const
-{
- return m_width;
-}
-
-void QQuickPen::setWidth(qreal w)
-{
- if (m_width == w && m_valid)
- return;
-
- m_width = w;
- m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
- emit penChanged();
-}
-
-QColor QQuickPen::color() const
-{
- return m_color;
-}
-
-void QQuickPen::setColor(const QColor &c)
-{
- m_color = c;
- m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
- emit penChanged();
-}
-
-bool QQuickPen::aligned() const
-{
- return m_aligned;
-}
-
-void QQuickPen::setAligned(bool aligned)
-{
- if (aligned == m_aligned)
- return;
- m_aligned = aligned;
- m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
- emit penChanged();
-}
-
-bool QQuickPen::isValid() const
-{
- return m_valid;
-}
-
-/*!
- \qmlclass GradientStop QQuickGradientStop
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The GradientStop item defines the color at a position in a Gradient.
-
- \sa Gradient
-*/
-
-/*!
- \qmlproperty real QtQuick2::GradientStop::position
- \qmlproperty color QtQuick2::GradientStop::color
-
- The position and color properties describe the color used at a given
- position in a gradient, as represented by a gradient stop.
-
- The default position is 0.0; the default color is black.
-
- \sa Gradient
-*/
-QQuickGradientStop::QQuickGradientStop(QObject *parent)
- : QObject(parent)
-{
-}
-
-qreal QQuickGradientStop::position() const
-{
- return m_position;
-}
-
-void QQuickGradientStop::setPosition(qreal position)
-{
- m_position = position; updateGradient();
-}
-
-QColor QQuickGradientStop::color() const
-{
- return m_color;
-}
-
-void QQuickGradientStop::setColor(const QColor &color)
-{
- m_color = color; updateGradient();
-}
-
-void QQuickGradientStop::updateGradient()
-{
- if (QQuickGradient *grad = qobject_cast<QQuickGradient*>(parent()))
- grad->doUpdate();
-}
-
-/*!
- \qmlclass Gradient QQuickGradient
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The Gradient item defines a gradient fill.
-
- A gradient is defined by two or more colors, which will be blended seamlessly.
-
- The colors are specified as a set of GradientStop child items, each of
- which defines a position on the gradient from 0.0 to 1.0 and a color.
- The position of each GradientStop is defined by setting its
- \l{GradientStop::}{position} property; its color is defined using its
- \l{GradientStop::}{color} property.
-
- A gradient without any gradient stops is rendered as a solid white fill.
-
- Note that this item is not a visual representation of a gradient. To display a
- gradient, use a visual element (like \l Rectangle) which supports the use
- of gradients.
-
- \section1 Example Usage
-
- \div {class="float-right"}
- \inlineimage qml-gradient.png
- \enddiv
-
- The following example declares a \l Rectangle item with a gradient starting
- with red, blending to yellow at one third of the height of the rectangle,
- and ending with green:
-
- \snippet doc/src/snippets/declarative/gradient.qml code
-
- \clearfloat
- \section1 Performance and Limitations
-
- Calculating gradients can be computationally expensive compared to the use
- of solid color fills or images. Consider using gradients for static items
- in a user interface.
-
- In Qt 4.7, only vertical, linear gradients can be applied to items. If you
- need to apply different orientations of gradients, a combination of rotation
- and clipping will need to be applied to the relevant items. This can
- introduce additional performance requirements for your application.
-
- The use of animations involving gradient stops may not give the desired
- result. An alternative way to animate gradients is to use pre-generated
- images or SVG drawings containing gradients.
-
- \sa GradientStop
-*/
-
-/*!
- \qmlproperty list<GradientStop> QtQuick2::Gradient::stops
- \default
-
- This property holds the gradient stops describing the gradient.
-
- By default, this property contains an empty list.
-
- To set the gradient stops, define them as children of the Gradient element.
-*/
-QQuickGradient::QQuickGradient(QObject *parent)
-: QObject(parent), m_gradient(0)
-{
-}
-
-QQuickGradient::~QQuickGradient()
-{
- delete m_gradient;
-}
-
-QDeclarativeListProperty<QQuickGradientStop> QQuickGradient::stops()
-{
- return QDeclarativeListProperty<QQuickGradientStop>(this, m_stops);
-}
-
-const QGradient *QQuickGradient::gradient() const
-{
- if (!m_gradient && !m_stops.isEmpty()) {
- m_gradient = new QLinearGradient(0,0,0,1.0);
- for (int i = 0; i < m_stops.count(); ++i) {
- const QQuickGradientStop *stop = m_stops.at(i);
- m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
- m_gradient->setColorAt(stop->position(), stop->color());
- }
- }
-
- return m_gradient;
-}
-
-void QQuickGradient::doUpdate()
-{
- delete m_gradient;
- m_gradient = 0;
- emit updated();
-}
-
-int QQuickRectanglePrivate::doUpdateSlotIdx = -1;
-
-/*!
- \qmlclass Rectangle QQuickRectangle
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The Rectangle item provides a filled rectangle with an optional border.
- \inherits Item
-
- Rectangle items are used to fill areas with solid color or gradients, and are
- often used to hold other items.
-
- \section1 Appearance
-
- Each Rectangle item is painted using either a solid fill color, specified using
- the \l color property, or a gradient, defined using a Gradient element and set
- using the \l gradient property. If both a color and a gradient are specified,
- the gradient is used.
-
- You can add an optional border to a rectangle with its own color and thickness
- by setting the \l border.color and \l border.width properties.
-
- You can also create rounded rectangles using the \l radius property. Since this
- introduces curved edges to the corners of a rectangle, it may be appropriate to
- set the \l smooth property to improve its appearance.
-
- \section1 Example Usage
-
- \div {class="float-right"}
- \inlineimage declarative-rect.png
- \enddiv
-
- The following example shows the effects of some of the common properties on a
- Rectangle item, which in this case is used to create a square:
-
- \snippet doc/src/snippets/declarative/rectangle/rectangle.qml document
-
- \clearfloat
- \section1 Performance
-
- Using the \l smooth property improves the appearance of a rounded rectangle at
- the cost of rendering performance. You should consider unsetting this property
- for rectangles in motion, and only set it when they are stationary.
-
- \sa Image
-*/
-
-QQuickRectangle::QQuickRectangle(QQuickItem *parent)
-: QQuickItem(*(new QQuickRectanglePrivate), parent)
-{
- setFlag(ItemHasContents);
-}
-
-void QQuickRectangle::doUpdate()
-{
- Q_D(QQuickRectangle);
- qreal penMargin = 0;
- qreal penOffset = 0;
- if (d->pen && d->pen->isValid()) {
- if (d->pen->aligned()) {
- const int pw = qRound(d->pen->width());
- penMargin = qreal(0.5) * pw;
- penOffset = (pw & 1) * qreal(0.5);
- } else {
- penMargin = qreal(0.5) * d->pen->width();
- }
- }
- if (penMargin != d->penMargin || penOffset != d->penOffset) {
- d->penMargin = penMargin;
- d->penOffset = penOffset;
- d->dirty(QQuickItemPrivate::Size); // update clip
- }
- update();
-}
-
-/*!
- \qmlproperty int QtQuick2::Rectangle::border.width
- \qmlproperty color QtQuick2::Rectangle::border.color
-
- The width and color used to draw the border of the rectangle.
-
- A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
-
- \note The width of the rectangle's border does not affect the geometry of the
- rectangle itself or its position relative to other items if anchors are used.
-
- If \c border.width is an odd number, the rectangle is painted at a half-pixel offset to retain
- border smoothness. Also, the border is rendered evenly on either side of the
- rectangle's boundaries, and the spare pixel is rendered to the right and below the
- rectangle (as documented for QRect rendering). This can cause unintended effects if
- \c border.width is 1 and the rectangle is \l{Item::clip}{clipped} by a parent item:
-
- \div {class="float-right"}
- \inlineimage rect-border-width.png
- \enddiv
-
- \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0
-
- \clearfloat
- Here, the innermost rectangle's border is clipped on the bottom and right edges by its
- parent. To avoid this, the border width can be set to two instead of one.
-*/
-QQuickPen *QQuickRectangle::border()
-{
- Q_D(QQuickRectangle);
- return d->getPen();
-}
-
-/*!
- \qmlproperty Gradient QtQuick2::Rectangle::gradient
-
- The gradient to use to fill the rectangle.
-
- This property allows for the construction of simple vertical gradients.
- Other gradients may by formed by adding rotation to the rectangle.
-
- \div {class="float-left"}
- \inlineimage declarative-rect_gradient.png
- \enddiv
-
- \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles
- \clearfloat
-
- If both a gradient and a color are specified, the gradient will be used.
-
- \sa Gradient, color
-*/
-QQuickGradient *QQuickRectangle::gradient() const
-{
- Q_D(const QQuickRectangle);
- return d->gradient;
-}
-
-void QQuickRectangle::setGradient(QQuickGradient *gradient)
-{
- Q_D(QQuickRectangle);
- if (d->gradient == gradient)
- return;
- static int updatedSignalIdx = -1;
- if (updatedSignalIdx < 0)
- updatedSignalIdx = QQuickGradient::staticMetaObject.indexOfSignal("updated()");
- if (d->doUpdateSlotIdx < 0)
- d->doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
- if (d->gradient)
- QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
- d->gradient = gradient;
- if (d->gradient)
- QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
- update();
-}
-
-/*!
- \qmlproperty real QtQuick2::Rectangle::radius
- This property holds the corner radius used to draw a rounded rectangle.
-
- If radius is non-zero, the rectangle will be painted as a rounded rectangle, otherwise it will be
- painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
- no way to specify different radii for different corners.
-*/
-qreal QQuickRectangle::radius() const
-{
- Q_D(const QQuickRectangle);
- return d->radius;
-}
-
-void QQuickRectangle::setRadius(qreal radius)
-{
- Q_D(QQuickRectangle);
- if (d->radius == radius)
- return;
-
- d->radius = radius;
- update();
- emit radiusChanged();
-}
-
-/*!
- \qmlproperty color QtQuick2::Rectangle::color
- This property holds the color used to fill the rectangle.
-
- The default color is white.
-
- \div {class="float-right"}
- \inlineimage rect-color.png
- \enddiv
-
- The following example shows rectangles with colors specified
- using hexadecimal and named color notation:
-
- \snippet doc/src/snippets/declarative/rectangle/rectangle-colors.qml rectangles
-
- \clearfloat
- If both a gradient and a color are specified, the gradient will be used.
-
- \sa gradient
-*/
-QColor QQuickRectangle::color() const
-{
- Q_D(const QQuickRectangle);
- return d->color;
-}
-
-void QQuickRectangle::setColor(const QColor &c)
-{
- Q_D(QQuickRectangle);
- if (d->color == c)
- return;
-
- d->color = c;
- update();
- emit colorChanged();
-}
-
-QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
-{
- Q_UNUSED(data);
- Q_D(QQuickRectangle);
-
- if (width() <= 0 || height() <= 0
- || (d->color.alpha() == 0 && (!d->pen || d->pen->width() == 0 || d->pen->color().alpha() == 0))) {
- delete oldNode;
- return 0;
- }
-
- QSGRectangleNode *rectangle = static_cast<QSGRectangleNode *>(oldNode);
- if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode();
-
- rectangle->setRect(QRectF(0, 0, width(), height()));
- rectangle->setColor(d->color);
-
- if (d->pen && d->pen->isValid()) {
- rectangle->setPenColor(d->pen->color());
- rectangle->setPenWidth(d->pen->width());
- rectangle->setAligned(d->pen->aligned());
- } else {
- rectangle->setPenWidth(0);
- }
-
- rectangle->setRadius(d->radius);
-
- QGradientStops stops;
- if (d->gradient) {
- QList<QQuickGradientStop *> qxstops = d->gradient->m_stops;
- for (int i = 0; i < qxstops.size(); ++i){
- int j = 0;
- while (j < stops.size() && stops.at(j).first < qxstops[i]->position())
- j++;
- stops.insert(j, QGradientStop(qxstops.at(i)->position(), qxstops.at(i)->color()));
- }
- }
- rectangle->setGradientStops(stops);
-
- rectangle->update();
-
- return rectangle;
-}
-/*!
- \qmlproperty bool QtQuick2::Rectangle::smooth
-
- Set this property if you want the item to be smoothly scaled or
- transformed. Smooth filtering gives better visual quality, but is slower. If
- the item is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the item is stationary on
- the screen. A common pattern when animating an item is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-
- \image rect-smooth.png
- On this image, smooth is turned off for the top half and on for the bottom half.
-*/
-
-QRectF QQuickRectangle::boundingRect() const
-{
- Q_D(const QQuickRectangle);
- return QRectF(d->penOffset - d->penMargin, d->penOffset - d->penMargin,
- d->width + 2 * d->penMargin, d->height + 2 * d->penMargin);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickrectangle_p.h b/src/declarative/items/qquickrectangle_p.h
deleted file mode 100644
index 838b944c62..0000000000
--- a/src/declarative/items/qquickrectangle_p.h
+++ /dev/null
@@ -1,189 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKRECTANGLE_P_H
-#define QQUICKRECTANGLE_P_H
-
-#include "qquickitem.h"
-
-#include <QtGui/qbrush.h>
-
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickPen : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY penChanged)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged)
- Q_PROPERTY(bool aligned READ aligned WRITE setAligned NOTIFY penChanged)
-public:
- QQuickPen(QObject *parent=0);
-
- qreal width() const;
- void setWidth(qreal w);
-
- QColor color() const;
- void setColor(const QColor &c);
-
- bool aligned() const;
- void setAligned(bool aligned);
-
- bool isValid() const;
-
-Q_SIGNALS:
- void penChanged();
-
-private:
- qreal m_width;
- QColor m_color;
- bool m_aligned : 1;
- bool m_valid : 1;
-};
-
-class Q_AUTOTEST_EXPORT QQuickGradientStop : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal position READ position WRITE setPosition)
- Q_PROPERTY(QColor color READ color WRITE setColor)
-
-public:
- QQuickGradientStop(QObject *parent=0);
-
- qreal position() const;
- void setPosition(qreal position);
-
- QColor color() const;
- void setColor(const QColor &color);
-
-private:
- void updateGradient();
-
-private:
- qreal m_position;
- QColor m_color;
-};
-
-class Q_AUTOTEST_EXPORT QQuickGradient : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QDeclarativeListProperty<QQuickGradientStop> stops READ stops)
- Q_CLASSINFO("DefaultProperty", "stops")
-
-public:
- QQuickGradient(QObject *parent=0);
- ~QQuickGradient();
-
- QDeclarativeListProperty<QQuickGradientStop> stops();
-
- const QGradient *gradient() const;
-
-Q_SIGNALS:
- void updated();
-
-private:
- void doUpdate();
-
-private:
- QList<QQuickGradientStop *> m_stops;
- mutable QGradient *m_gradient;
- friend class QQuickRectangle;
- friend class QQuickGradientStop;
-};
-
-class QQuickRectanglePrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QQuickGradient *gradient READ gradient WRITE setGradient)
- Q_PROPERTY(QQuickPen * border READ border CONSTANT)
- Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
-public:
- QQuickRectangle(QQuickItem *parent=0);
-
- QColor color() const;
- void setColor(const QColor &);
-
- QQuickPen *border();
-
- QQuickGradient *gradient() const;
- void setGradient(QQuickGradient *gradient);
-
- qreal radius() const;
- void setRadius(qreal radius);
-
- virtual QRectF boundingRect() const;
-
-Q_SIGNALS:
- void colorChanged();
- void radiusChanged();
-
-protected:
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-private Q_SLOTS:
- void doUpdate();
-
-private:
- Q_DISABLE_COPY(QQuickRectangle)
- Q_DECLARE_PRIVATE(QQuickRectangle)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPen)
-QML_DECLARE_TYPE(QQuickGradientStop)
-QML_DECLARE_TYPE(QQuickGradient)
-QML_DECLARE_TYPE(QQuickRectangle)
-
-QT_END_HEADER
-
-#endif // QQUICKRECTANGLE_P_H
diff --git a/src/declarative/items/qquickrepeater_p.h b/src/declarative/items/qquickrepeater_p.h
deleted file mode 100644
index 5b90d74e65..0000000000
--- a/src/declarative/items/qquickrepeater_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKREPEATER_P_H
-#define QQUICKREPEATER_P_H
-
-#include "qquickitem.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeChangeSet;
-
-class QQuickRepeaterPrivate;
-class Q_AUTOTEST_EXPORT QQuickRepeater : public QQuickItem
-{
- Q_OBJECT
-
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-
-public:
- QQuickRepeater(QQuickItem *parent=0);
- virtual ~QQuickRepeater();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int count() const;
-
- Q_INVOKABLE QQuickItem *itemAt(int index) const;
-
-Q_SIGNALS:
- void modelChanged();
- void delegateChanged();
- void countChanged();
-
- void itemAdded(int index, QQuickItem *item);
- void itemRemoved(int index, QQuickItem *item);
-
-private:
- void clear();
- void regenerate();
-
-protected:
- virtual void componentComplete();
- void itemChange(ItemChange change, const ItemChangeData &value);
-
-private Q_SLOTS:
- void createdItem(int index, QQuickItem *item);
- void initItem(int, QQuickItem *item);
- void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
-
-private:
- Q_DISABLE_COPY(QQuickRepeater)
- Q_DECLARE_PRIVATE(QQuickRepeater)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickRepeater)
-
-QT_END_HEADER
-
-#endif // QQUICKREPEATER_P_H
diff --git a/src/declarative/items/qquickscalegrid_p_p.h b/src/declarative/items/qquickscalegrid_p_p.h
deleted file mode 100644
index 8d93c3b1c9..0000000000
--- a/src/declarative/items/qquickscalegrid_p_p.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKSCALEGRID_P_P_H
-#define QQUICKSCALEGRID_P_P_H
-
-#include "qquickborderimage_p.h"
-
-#include <QtDeclarative/qdeclarative.h>
-#include <QtCore/qobject.h>
-
-#include <private/qdeclarativepixmapcache_p.h>
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickScaleGrid : public QObject
-{
- Q_OBJECT
- Q_ENUMS(TileRule)
-
- Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
- Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
- Q_PROPERTY(int right READ right WRITE setRight NOTIFY borderChanged)
- Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY borderChanged)
-
-public:
- QQuickScaleGrid(QObject *parent=0);
- ~QQuickScaleGrid();
-
- bool isNull() const;
-
- int left() const { return _left; }
- void setLeft(int);
-
- int top() const { return _top; }
- void setTop(int);
-
- int right() const { return _right; }
- void setRight(int);
-
- int bottom() const { return _bottom; }
- void setBottom(int);
-
-Q_SIGNALS:
- void borderChanged();
-
-private:
- int _left;
- int _top;
- int _right;
- int _bottom;
-};
-
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickGridScaledImage
-{
-public:
- QQuickGridScaledImage();
- QQuickGridScaledImage(const QQuickGridScaledImage &);
- QQuickGridScaledImage(QIODevice*);
- QQuickGridScaledImage &operator=(const QQuickGridScaledImage &);
- bool isValid() const;
- int gridLeft() const;
- int gridRight() const;
- int gridTop() const;
- int gridBottom() const;
- QQuickBorderImage::TileMode horizontalTileRule() const { return _h; }
- QQuickBorderImage::TileMode verticalTileRule() const { return _v; }
-
- QString pixmapUrl() const;
-
-private:
- static QQuickBorderImage::TileMode stringToRule(const QString &);
-
-private:
- int _l;
- int _r;
- int _t;
- int _b;
- QQuickBorderImage::TileMode _h;
- QQuickBorderImage::TileMode _v;
- QString _pix;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickScaleGrid)
-
-QT_END_HEADER
-
-#endif // QQUICKSCALEGRID_P_P_H
diff --git a/src/declarative/items/qquickshadereffect.cpp b/src/declarative/items/qquickshadereffect.cpp
deleted file mode 100644
index bdef980440..0000000000
--- a/src/declarative/items/qquickshadereffect.cpp
+++ /dev/null
@@ -1,763 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <private/qquickshadereffect_p.h>
-#include <private/qquickshadereffectnode_p.h>
-
-#include "qsgmaterial.h"
-#include "qquickitem_p.h"
-
-#include <private/qsgcontext_p.h>
-#include <private/qsgtextureprovider_p.h>
-#include "qquickcanvas.h"
-
-#include "qquickimage_p.h"
-#include "qquickshadereffectsource_p.h"
-
-#include <QtCore/qsignalmapper.h>
-#include <QtGui/qopenglframebufferobject.h>
-
-QT_BEGIN_NAMESPACE
-
-static const char qt_default_vertex_code[] =
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_Vertex; \n"
- "attribute highp vec2 qt_MultiTexCoord0; \n"
- "varying highp vec2 qt_TexCoord0; \n"
- "void main() { \n"
- " qt_TexCoord0 = qt_MultiTexCoord0; \n"
- " gl_Position = qt_Matrix * qt_Vertex; \n"
- "}";
-
-static const char qt_default_fragment_code[] =
- "varying highp vec2 qt_TexCoord0; \n"
- "uniform sampler2D source; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
- "}";
-
-static const char qt_position_attribute_name[] = "qt_Vertex";
-static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
-
-const char *qtPositionAttributeName()
-{
- return qt_position_attribute_name;
-}
-
-const char *qtTexCoordAttributeName()
-{
- return qt_texcoord_attribute_name;
-}
-
-/*!
- \qmlclass ShaderEffect QQuickShaderEffect
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The ShaderEffect element applies custom shaders to a rectangle.
- \inherits Item
-
- The ShaderEffect element applies a custom OpenGL
- \l{vertexShader}{vertex} and \l{fragmentShader}{fragment} shader to a
- rectangle. It allows you to write effects such as drop shadow, blur,
- colorize and page curl directly in QML.
-
- There are two types of input to the \l vertexShader:
- uniform variables and attributes. Some are predefined:
- \list
- \o uniform mat4 qt_Matrix - combined transformation
- matrix, the product of the matrices from the root item to this
- ShaderEffect, and an orthogonal projection.
- \o uniform float qt_Opacity - combined opacity, the product of the
- opacities from the root item to this ShaderEffect.
- \o attribute vec4 qt_Vertex - vertex position, the top-left vertex has
- position (0, 0), the bottom-right (\l{Item::width}{width},
- \l{Item::height}{height}).
- \o attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left
- coordinate is (0, 0), the bottom-right (1, 1).
- \endlist
-
- In addition, any property that can be mapped to an OpenGL Shading Language
- (GLSL) type is available as a uniform variable. The following list shows
- how properties are mapped to GLSL uniform variables:
- \list
- \o bool, int, qreal -> bool, int, float - If the type in the shader is not
- the same as in QML, the value is converted automatically.
- \o QColor -> vec4 - When colors are passed to the shader, they are first
- premultiplied. Thus Qt.rgba(0.2, 0.6, 1.0, 0.5) becomes
- vec4(0.1, 0.3, 0.5, 0.5) in the shader, for example.
- \o QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in
- the shader.
- \o QPoint, QPointF, QSize, QSizeF -> vec2
- \o QVector3D -> vec3
- \o QTransform -> mat4
- \o \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left
- corner, and the color values are premultiplied.
- \endlist
-
- The output from the \l fragmentShader should be premultiplied. If
- \l blending is enabled, source-over blending is used. However, additive
- blending can be achieved by outputting zero in the alpha channel.
-
- \row
- \o \image declarative-shadereffectitem.png
- \o \qml
- import QtQuick 2.0
-
- Rectangle {
- width: 200; height: 100
- Row {
- Image { id: img; sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
- ShaderEffect {
- width: 100; height: 100
- property variant src: img
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 coord;
- void main() {
- coord = qt_MultiTexCoord0;
- gl_Position = qt_Matrix * qt_Vertex;
- }"
- fragmentShader: "
- varying highp vec2 coord;
- uniform sampler2D src;
- uniform lowp float qt_Opacity;
- void main() {
- lowp vec4 tex = texture2D(src, coord);
- gl_FragColor = vec4(vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156))), tex.a) * qt_Opacity;
- }"
- }
- }
- }
- \endqml
- \endrow
-
- By default, the ShaderEffect consists of four vertices, one for each
- corner. For non-linear vertex transformations, like page curl, you can
- specify a fine grid of vertices by specifying a \l mesh resolution.
-
- \note Scene Graph textures have origin in the top-left corner rather than
- bottom-left which is common in OpenGL.
-*/
-
-QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
- : QQuickItem(parent)
- , m_meshResolution(1, 1)
- , m_mesh(0)
- , m_cullMode(NoCulling)
- , m_blending(true)
- , m_dirtyData(true)
- , m_programDirty(true)
- , m_dirtyMesh(true)
- , m_dirtyGeometry(true)
-{
- setFlag(QQuickItem::ItemHasContents);
-}
-
-QQuickShaderEffect::~QQuickShaderEffect()
-{
- reset();
-}
-
-void QQuickShaderEffect::componentComplete()
-{
- updateProperties();
- QQuickItem::componentComplete();
-}
-
-/*!
- \qmlproperty string QtQuick2::ShaderEffect::fragmentShader
-
- This property holds the fragment shader's GLSL source code.
- The default shader passes the texture coordinate along to the fragment
- shader as "varying highp vec2 qt_TexCoord0".
-*/
-
-void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
-{
- if (m_source.fragmentCode.constData() == code.constData())
- return;
- m_source.fragmentCode = code;
- if (isComponentComplete()) {
- reset();
- updateProperties();
- update();
- }
- emit fragmentShaderChanged();
-}
-
-/*!
- \qmlproperty string QtQuick2::ShaderEffect::vertexShader
-
- This property holds the vertex shader's GLSL source code.
- The default shader expects the texture coordinate to be passed from the
- vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
- sampler2D named "source".
-*/
-
-void QQuickShaderEffect::setVertexShader(const QByteArray &code)
-{
- if (m_source.vertexCode.constData() == code.constData())
- return;
- m_source.vertexCode = code;
- if (isComponentComplete()) {
- reset();
- updateProperties();
- update();
- }
- emit vertexShaderChanged();
-}
-
-/*!
- \qmlproperty bool QtQuick2::ShaderEffect::blending
-
- If this property is true, the output from the \l fragmentShader is blended
- with the background using source-over blend mode. If false, the background
- is disregarded. Blending decreases the performance, so you should set this
- property to false when blending is not needed. The default value is true.
-*/
-
-void QQuickShaderEffect::setBlending(bool enable)
-{
- if (blending() == enable)
- return;
-
- m_blending = enable;
- update();
-
- emit blendingChanged();
-}
-
-/*!
- \qmlproperty variant QtQuick2::ShaderEffect::mesh
-
- This property defines the mesh used to draw the ShaderEffect. It can hold
- any mesh object deriving from \l QQuickShaderEffectMesh, such as \l GridMesh.
- If a size value is assigned to this property, the ShaderEffect implicitly
- uses a \l GridMesh with the value as
- \l{GridMesh::resolution}{mesh resolution}. By default, this property is
- the size 1x1.
-
- \sa GridMesh
-*/
-
-QVariant QQuickShaderEffect::mesh() const
-{
- return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
- : qVariantFromValue(m_meshResolution);
-}
-
-void QQuickShaderEffect::setMesh(const QVariant &mesh)
-{
- QQuickShaderEffectMesh *newMesh = qobject_cast<QQuickShaderEffectMesh *>(qVariantValue<QObject *>(mesh));
- if (newMesh && newMesh == m_mesh)
- return;
- if (m_mesh)
- disconnect(m_mesh, SIGNAL(geometryChanged()), this, 0);
- m_mesh = newMesh;
- if (m_mesh) {
- connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
- } else {
- if (qVariantCanConvert<QSize>(mesh)) {
- m_meshResolution = mesh.toSize();
- } else {
- QList<QByteArray> res = mesh.toByteArray().split('x');
- bool ok = res.size() == 2;
- if (ok) {
- int w = res.at(0).toInt(&ok);
- if (ok) {
- int h = res.at(1).toInt(&ok);
- if (ok)
- m_meshResolution = QSize(w, h);
- }
- }
- if (!ok)
- qWarning("ShaderEffect: mesh property must be size or object deriving from QQuickShaderEffectMesh.");
- }
- m_defaultMesh.setResolution(m_meshResolution);
- }
-
- m_dirtyMesh = true;
- update();
- emit meshChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::ShaderEffect::cullMode
-
- This property defines which sides of the element should be visible.
-
- \list
- \o ShaderEffect.NoCulling - Both sides are visible
- \o ShaderEffect.BackFaceCulling - only front side is visible
- \o ShaderEffect.FrontFaceCulling - only back side is visible
- \endlist
-
- The default is NoCulling.
-*/
-
-void QQuickShaderEffect::setCullMode(CullMode face)
-{
- if (face == m_cullMode)
- return;
- m_cullMode = face;
- update();
- emit cullModeChanged();
-}
-
-void QQuickShaderEffect::changeSource(int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
- QVariant v = property(m_sources.at(index).name.constData());
- setSource(v, index);
-}
-
-void QQuickShaderEffect::updateData()
-{
- m_dirtyData = true;
- update();
-}
-
-void QQuickShaderEffect::updateGeometry()
-{
- m_dirtyGeometry = true;
- update();
-}
-
-void QQuickShaderEffect::setSource(const QVariant &var, int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
-
- SourceData &source = m_sources[index];
-
- source.sourceObject = 0;
- if (var.isNull()) {
- return;
- } else if (!qVariantCanConvert<QObject *>(var)) {
- qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
- return;
- }
-
- QObject *obj = qVariantValue<QObject *>(var);
- QQuickItem *item = qobject_cast<QQuickItem *>(obj);
- if (!item || !item->isTextureProvider()) {
- qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
- source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
- return;
- }
-
- source.sourceObject = item;
-
-
- // TODO: Find better solution.
- // 'item' needs a canvas to get a scenegraph node.
- // The easiest way to make sure it gets a canvas is to
- // make it a part of the same item tree as 'this'.
- if (item && item->parentItem() == 0) {
- item->setParentItem(this);
- item->setVisible(false);
- }
-}
-
-void QQuickShaderEffect::disconnectPropertySignals()
-{
- disconnect(this, 0, this, SLOT(updateData()));
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- disconnect(this, 0, source.mapper, 0);
- disconnect(source.mapper, 0, this, 0);
- }
-}
-
-void QQuickShaderEffect::connectPropertySignals()
-{
- QSet<QByteArray>::const_iterator it;
- for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
- int pi = metaObject()->indexOfProperty(it->constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- if (!mp.hasNotifySignal())
- qWarning("QQuickShaderEffect: property '%s' does not have notification method!", it->constData());
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().signature());
- connect(this, signalName, this, SLOT(updateData()));
- } else {
- qWarning("QQuickShaderEffect: '%s' does not have a matching property!", it->constData());
- }
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- int pi = metaObject()->indexOfProperty(source.name.constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().signature());
- connect(this, signalName, source.mapper, SLOT(map()));
- source.mapper->setMapping(this, i);
- connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
- } else {
- qWarning("QQuickShaderEffect: '%s' does not have a matching source!", source.name.constData());
- }
- }
-}
-
-void QQuickShaderEffect::reset()
-{
- disconnectPropertySignals();
-
- m_source.attributeNames.clear();
- m_source.uniformNames.clear();
- m_source.respectsOpacity = false;
- m_source.respectsMatrix = false;
- m_source.className = metaObject()->className();
-
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- delete source.mapper;
- QQuickItem *item = qobject_cast<QQuickItem *>(source.sourceObject);
- if (item && item->parentItem() == this)
- item->setParentItem(0);
- }
- m_sources.clear();
-
- m_programDirty = true;
- m_dirtyMesh = true;
-}
-
-void QQuickShaderEffect::updateProperties()
-{
- if (m_source.vertexCode.isEmpty()) {
- m_source.attributeNames.append(QByteArray(qt_position_attribute_name));
- m_source.attributeNames.append(QByteArray(qt_texcoord_attribute_name));
- m_source.respectsMatrix = true;
- } else {
- lookThroughShaderCode(m_source.vertexCode);
- }
- if (m_source.fragmentCode.isEmpty()) {
- m_source.respectsOpacity = true;
- QByteArray name("source");
- m_source.uniformNames.insert(name);
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- } else {
- lookThroughShaderCode(m_source.fragmentCode);
- }
-
- if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name))
- qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_position_attribute_name);
- if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
- qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
- if (!m_source.respectsMatrix)
- qWarning("QQuickShaderEffect: Missing reference to \'qt_Matrix\'.");
- if (!m_source.respectsOpacity)
- qWarning("QQuickShaderEffect: Missing reference to \'qt_Opacity\'.");
-
- for (int i = 0; i < m_sources.size(); ++i) {
- QVariant v = property(m_sources.at(i).name);
- setSource(v, i);
- }
-
- connectPropertySignals();
-}
-
-namespace {
-
- enum VariableQualifier {
- AttributeQualifier,
- UniformQualifier
- };
-
- inline bool qt_isalpha(char c)
- {
- char ch = c | 0x20;
- return (ch >= 'a' && ch <= 'z') || c == '_';
- }
-
- inline bool qt_isalnum(char c)
- {
- return qt_isalpha(c) || (c >= '0' && c <= '9');
- }
-
- inline bool qt_isspace(char c)
- {
- return c == ' ' || (c >= 0x09 && c <= 0x0d);
- }
-
- // Returns -1 if not found, returns index to first character after the name if found.
- int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
- int &typeIndex, int &typeLength,
- int &nameIndex, int &nameLength)
- {
- enum Identifier {
- QualifierIdentifier, // Base state
- PrecisionIdentifier,
- TypeIdentifier,
- NameIdentifier
- };
- Identifier expected = QualifierIdentifier;
- bool compilerDirectiveExpected = index == 0;
-
- while (index < length) {
- // Skip whitespace.
- while (qt_isspace(s[index])) {
- compilerDirectiveExpected |= s[index] == '\n';
- ++index;
- }
-
- if (qt_isalpha(s[index])) {
- // Read identifier.
- int idIndex = index;
- ++index;
- while (qt_isalnum(s[index]))
- ++index;
- int idLength = index - idIndex;
-
- const int attrLen = sizeof("attribute") - 1;
- const int uniLen = sizeof("uniform") - 1;
- const int loLen = sizeof("lowp") - 1;
- const int medLen = sizeof("mediump") - 1;
- const int hiLen = sizeof("highp") - 1;
-
- switch (expected) {
- case QualifierIdentifier:
- if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
- decl = AttributeQualifier;
- expected = PrecisionIdentifier;
- } else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
- decl = UniformQualifier;
- expected = PrecisionIdentifier;
- }
- break;
- case PrecisionIdentifier:
- if ((idLength == loLen && qstrncmp("lowp", s + idIndex, loLen) == 0)
- || (idLength == medLen && qstrncmp("mediump", s + idIndex, medLen) == 0)
- || (idLength == hiLen && qstrncmp("highp", s + idIndex, hiLen) == 0))
- {
- expected = TypeIdentifier;
- break;
- }
- // Fall through.
- case TypeIdentifier:
- typeIndex = idIndex;
- typeLength = idLength;
- expected = NameIdentifier;
- break;
- case NameIdentifier:
- nameIndex = idIndex;
- nameLength = idLength;
- return index; // Attribute or uniform declaration found. Return result.
- default:
- break;
- }
- } else if (s[index] == '#' && compilerDirectiveExpected) {
- // Skip compiler directives.
- ++index;
- while (index < length && (s[index] != '\n' || s[index - 1] == '\\'))
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '/') {
- // Skip comments.
- index += 2;
- while (index < length && s[index] != '\n')
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '*') {
- // Skip comments.
- index += 2;
- while (index < length && (s[index] != '*' || s[index + 1] != '/'))
- ++index;
- if (index < length)
- index += 2; // Skip star-slash.
- } else {
- expected = QualifierIdentifier;
- ++index;
- }
- compilerDirectiveExpected = false;
- }
- return -1;
- }
-}
-
-void QQuickShaderEffect::lookThroughShaderCode(const QByteArray &code)
-{
- int index = 0;
- int typeIndex, typeLength, nameIndex, nameLength;
- const char *s = code.constData();
- VariableQualifier decl;
- while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
- nameIndex, nameLength)) != -1)
- {
- if (decl == AttributeQualifier) {
- m_source.attributeNames.append(QByteArray(s + nameIndex, nameLength));
- } else {
- Q_ASSERT(decl == UniformQualifier);
-
- const int matLen = sizeof("qt_Matrix") - 1;
- const int opLen = sizeof("qt_Opacity") - 1;
- const int sampLen = sizeof("sampler2D") - 1;
-
- if (nameLength == matLen && qstrncmp("qt_Matrix", s + nameIndex, matLen) == 0) {
- m_source.respectsMatrix = true;
- } else if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) {
- m_source.respectsOpacity = true;
- } else {
- QByteArray name(s + nameIndex, nameLength);
- m_source.uniformNames.insert(name);
- if (typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0) {
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- }
- }
- }
- }
-}
-
-void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- m_dirtyGeometry = true;
- QQuickItem::geometryChanged(newGeometry, oldGeometry);
-}
-
-QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- QQuickShaderEffectNode *node = static_cast<QQuickShaderEffectNode *>(oldNode);
-
- // In the case of a bad vertex shader, don't try to create a node...
- if (m_source.attributeNames.isEmpty()) {
- if (node)
- delete node;
- return 0;
- }
-
- if (!node) {
- node = new QQuickShaderEffectNode;
- m_programDirty = true;
- m_dirtyData = true;
- m_dirtyGeometry = true;
- }
-
- QQuickShaderEffectMaterial *material = node->shaderMaterial();
-
- if (m_dirtyMesh) {
- node->setGeometry(0);
- m_dirtyMesh = false;
- m_dirtyGeometry = true;
- }
-
- if (m_dirtyGeometry) {
- node->setFlag(QSGNode::OwnsGeometry, false);
- QSGGeometry *geometry = node->geometry();
- QRectF rect(0, 0, width(), height());
- QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
-
- geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
- if (!geometry) {
- delete node;
- return 0;
- }
-
- node->setGeometry(geometry);
- node->setFlag(QSGNode::OwnsGeometry, true);
-
- m_dirtyGeometry = false;
- }
-
- if (m_programDirty) {
- QQuickShaderEffectProgram s = m_source;
- if (s.fragmentCode.isEmpty())
- s.fragmentCode = qt_default_fragment_code;
- if (s.vertexCode.isEmpty())
- s.vertexCode = qt_default_vertex_code;
- s.className = metaObject()->className();
-
- material->setProgramSource(s);
- node->markDirty(QSGNode::DirtyMaterial);
- m_programDirty = false;
- }
-
- // Update blending
- if (bool(material->flags() & QSGMaterial::Blending) != m_blending) {
- material->setFlag(QSGMaterial::Blending, m_blending);
- node->markDirty(QSGNode::DirtyMaterial);
- }
-
- if (int(material->cullMode()) != int(m_cullMode)) {
- material->setCullMode(QQuickShaderEffectMaterial::CullMode(m_cullMode));
- node->markDirty(QSGNode::DirtyMaterial);
- }
-
- if (m_dirtyData) {
- QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = material->textureProviders();
-
- for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
- it != m_source.uniformNames.end(); ++it) {
- values.append(qMakePair(*it, property(*it)));
- }
- for (int i = 0; i < oldTextures.size(); ++i) {
- QSGTextureProvider *t = oldTextures.at(i).second;
- if (t)
- disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- }
- 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);
- }
- material->setUniforms(values);
- material->setTextureProviders(textures);
- node->markDirty(QSGNode::DirtyMaterial);
- m_dirtyData = false;
- }
-
- return node;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickshadereffect_p.h b/src/declarative/items/qquickshadereffect_p.h
deleted file mode 100644
index 1910f43195..0000000000
--- a/src/declarative/items/qquickshadereffect_p.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKSHADEREFFECT_P_H
-#define QQUICKSHADEREFFECT_P_H
-
-#include "qquickitem.h"
-
-#include "qsgmaterial.h"
-#include <private/qsgadaptationlayer_p.h>
-#include <private/qquickshadereffectnode_p.h>
-#include "qquickshadereffectmesh_p.h"
-
-#include <QtCore/qpointer.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-const char *qtPositionAttributeName();
-const char *qtTexCoordAttributeName();
-
-class QSGContext;
-class QSignalMapper;
-class QQuickCustomMaterialShader;
-
-class Q_AUTOTEST_EXPORT QQuickShaderEffect : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
- Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
- Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY blendingChanged)
- Q_PROPERTY(QVariant mesh READ mesh WRITE setMesh NOTIFY meshChanged)
- Q_PROPERTY(CullMode culling READ cullMode WRITE setCullMode NOTIFY cullModeChanged)
- Q_ENUMS(CullMode)
-
-public:
- enum CullMode
- {
- NoCulling = QQuickShaderEffectMaterial::NoCulling,
- BackFaceCulling = QQuickShaderEffectMaterial::BackFaceCulling,
- FrontFaceCulling = QQuickShaderEffectMaterial::FrontFaceCulling
- };
-
- QQuickShaderEffect(QQuickItem *parent = 0);
- ~QQuickShaderEffect();
-
- virtual void componentComplete();
-
- QByteArray fragmentShader() const { return m_source.fragmentCode; }
- void setFragmentShader(const QByteArray &code);
-
- QByteArray vertexShader() const { return m_source.vertexCode; }
- void setVertexShader(const QByteArray &code);
-
- bool blending() const { return m_blending; }
- void setBlending(bool enable);
-
- QVariant mesh() const;
- void setMesh(const QVariant &mesh);
-
- CullMode cullMode() const { return m_cullMode; }
- void setCullMode(CullMode face);
-
-Q_SIGNALS:
- void fragmentShaderChanged();
- void vertexShaderChanged();
- void blendingChanged();
- void meshChanged();
- void cullModeChanged();
-
-protected:
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-private Q_SLOTS:
- void changeSource(int index);
- void updateData();
- void updateGeometry();
-
-private:
- friend class QQuickCustomMaterialShader;
- friend class QQuickShaderEffectNode;
-
- void setSource(const QVariant &var, int index);
- void disconnectPropertySignals();
- void connectPropertySignals();
- void reset();
- void updateProperties();
- void lookThroughShaderCode(const QByteArray &code);
-
- QQuickShaderEffectProgram m_source;
- QSize m_meshResolution;
- QQuickShaderEffectMesh *m_mesh;
- QQuickGridMesh m_defaultMesh;
- CullMode m_cullMode;
-
- struct SourceData
- {
- QSignalMapper *mapper;
- QPointer<QQuickItem> sourceObject;
- QByteArray name;
- };
- QVector<SourceData> m_sources;
-
- uint m_blending : 1;
- uint m_dirtyData : 1;
-
- uint m_programDirty : 1;
- uint m_dirtyMesh : 1;
- uint m_dirtyGeometry : 1;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSHADEREFFECT_P_H
diff --git a/src/declarative/items/qquickshadereffectmesh.cpp b/src/declarative/items/qquickshadereffectmesh.cpp
deleted file mode 100644
index 7709bed614..0000000000
--- a/src/declarative/items/qquickshadereffectmesh.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickshadereffectmesh_p.h"
-#include "qsggeometry.h"
-#include "qquickshadereffect_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQuickShaderEffectMesh::QQuickShaderEffectMesh(QObject *parent)
- : QObject(parent)
-{
-}
-
-/*!
- \qmlclass GridMesh QQuickGridMesh
- \inqmlmodule QtQuick 2
- \ingroup qml-utility-elements
- \brief GridMesh defines a mesh with vertices arranged in a grid.
-
- GridMesh defines a rectangular mesh consisting of vertices arranged in an
- evenly spaced grid. It is used to generate \l{QSGGeometry}{geometry}.
- The grid resolution is specified with the \l resolution property.
-*/
-
-QQuickGridMesh::QQuickGridMesh(QObject *parent)
- : QQuickShaderEffectMesh(parent)
- , m_resolution(1, 1)
-{
- connect(this, SIGNAL(resolutionChanged()), this, SIGNAL(geometryChanged()));
-}
-
-QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &dstRect) const
-{
- int vmesh = m_resolution.height();
- int hmesh = m_resolution.width();
- int attrCount = attributes.count();
-
- if (!geometry) {
- bool error = true;
- Q_UNUSED(error)
- switch (attrCount) {
- case 0:
- qWarning("QQuickGridMesh:: No attributes specified.");
- break;
- case 1:
- if (attributes.at(0) == qtPositionAttributeName()) {
- error = false;
- break;
- }
- qWarning("QQuickGridMesh:: Missing \'%s\' attribute.",
- qtPositionAttributeName());
- break;
- case 2:
- if (attributes.contains(qtPositionAttributeName())
- && attributes.contains(qtTexCoordAttributeName()))
- {
- error = false;
- break;
- }
- qWarning("QQuickGridMesh:: Missing \'%s\' or \'%s\' attribute.",
- qtPositionAttributeName(), qtTexCoordAttributeName());
- break;
- default:
- qWarning("QQuickGridMesh:: Too many attributes specified.");
- break;
- }
-
- geometry = new QSGGeometry(attrCount == 1
- ? QSGGeometry::defaultAttributes_Point2D()
- : QSGGeometry::defaultAttributes_TexturedPoint2D(),
- (vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2),
- GL_UNSIGNED_SHORT);
-
- } else {
- geometry->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
- }
-
- QSGGeometry::Point2D *vdata = static_cast<QSGGeometry::Point2D *>(geometry->vertexData());
-
- bool positionFirst = attributes.at(0) == qtPositionAttributeName();
-
- QRectF srcRect(0, 0, 1, 1);
- for (int iy = 0; iy <= vmesh; ++iy) {
- float fy = iy / float(vmesh);
- float y = float(dstRect.top()) + fy * float(dstRect.height());
- float ty = float(srcRect.top()) + fy * float(srcRect.height());
- for (int ix = 0; ix <= hmesh; ++ix) {
- float fx = ix / float(hmesh);
- for (int ia = 0; ia < attrCount; ++ia) {
- if (positionFirst == (ia == 0)) {
- vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
- vdata->y = y;
- ++vdata;
- } else {
- vdata->x = float(srcRect.left()) + fx * float(srcRect.width());
- vdata->y = ty;
- ++vdata;
- }
- }
- }
- }
-
- quint16 *indices = (quint16 *)geometry->indexDataAsUShort();
- int i = 0;
- for (int iy = 0; iy < vmesh; ++iy) {
- *(indices++) = i + hmesh + 1;
- for (int ix = 0; ix <= hmesh; ++ix, ++i) {
- *(indices++) = i + hmesh + 1;
- *(indices++) = i;
- }
- *(indices++) = i - 1;
- }
-
- return geometry;
-}
-
-/*!
- \qmlproperty size QtQuick2::GridMesh::resolution
-
- This property holds the grid resolution. The resolution's width and height
- specify the number of cells or spacings between vertices horizontally and
- vertically respectively. The minimum and default is 1x1, which corresponds
- to four vertices in total, one in each corner.
- For non-linear vertex transformations, you probably want to set the
- resolution higher.
-
- \row
- \o \image declarative-gridmesh.png
- \o \qml
- import QtQuick 2.0
-
- ShaderEffect {
- width: 200
- height: 200
- mesh: GridMesh {
- resolution: Qt.size(20, 20)
- }
- property variant source: Image {
- source: "qt-logo.png"
- sourceSize { width: 200; height: 200 }
- smooth: true
- }
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- uniform highp float width;
- void main() {
- highp vec4 pos = qt_Vertex;
- highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
- pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
- }
- \endqml
- \endrow
-*/
-
-void QQuickGridMesh::setResolution(const QSize &res)
-{
- if (res == m_resolution)
- return;
- if (res.width() < 1 || res.height() < 1) {
- return;
- }
- m_resolution = res;
- emit resolutionChanged();
-}
-
-QSize QQuickGridMesh::resolution() const
-{
- return m_resolution;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickshadereffectmesh_p.h b/src/declarative/items/qquickshadereffectmesh_p.h
deleted file mode 100644
index 40549f73a8..0000000000
--- a/src/declarative/items/qquickshadereffectmesh_p.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qdeclarativeparserstatus.h"
-
-#include <QtGui/qcolor.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qsize.h>
-#include <QtCore/qvariant.h>
-#include <QtGui/qopenglfunctions.h>
-
-#ifndef QQUICKSHADEREFFECTMESH_P_H
-#define QQUICKSHADEREFFECTMESH_P_H
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGGeometry;
-class QRectF;
-
-class Q_DECLARATIVE_EXPORT QQuickShaderEffectMesh : public QObject
-{
- Q_OBJECT
-public:
- QQuickShaderEffectMesh(QObject *parent = 0);
- // If 'geometry' != 0, 'attributes' is the same as last time the function was called.
- virtual QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &rect) const = 0;
-
-Q_SIGNALS:
- // Emitted when the geometry needs to be updated.
- void geometryChanged();
-};
-
-class QQuickGridMesh : public QQuickShaderEffectMesh
-{
- Q_OBJECT
- Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
-public:
- QQuickGridMesh(QObject *parent = 0);
- virtual QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &rect) const;
-
- void setResolution(const QSize &res);
- QSize resolution() const;
-
-Q_SIGNALS:
- void resolutionChanged();
-
-private:
- QSize m_resolution;
-};
-
-inline QColor qt_premultiply_color(const QColor &c)
-{
- return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
-}
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSHADEREFFECTMESH_P_H
diff --git a/src/declarative/items/qquickshadereffectnode.cpp b/src/declarative/items/qquickshadereffectnode.cpp
deleted file mode 100644
index 43c891e497..0000000000
--- a/src/declarative/items/qquickshadereffectnode.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <private/qquickshadereffectnode_p.h>
-
-#include "qquickshadereffectmesh_p.h"
-#include <private/qsgtextureprovider_p.h>
-#include <private/qsgrenderer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickCustomMaterialShader : public QSGMaterialShader
-{
-public:
- QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes);
- virtual void deactivate();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-
-protected:
- friend class QQuickShaderEffectNode;
-
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- const QQuickShaderEffectMaterialKey m_key;
- QVector<const char *> m_attributeNames;
- const QVector<QByteArray> m_attributes;
-
- QVector<int> m_uniformLocs;
- int m_opacityLoc;
- int m_matrixLoc;
- uint m_textureIndicesSet;
-};
-
-QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes)
- : m_key(key)
- , m_attributes(attributes)
- , m_textureIndicesSet(false)
-{
- for (int i = 0; i < attributes.count(); ++i)
- m_attributeNames.append(attributes.at(i).constData());
- m_attributeNames.append(0);
-}
-
-void QQuickCustomMaterialShader::deactivate()
-{
- QSGMaterialShader::deactivate();
- glDisable(GL_CULL_FACE);
-}
-
-void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(newEffect != 0);
-
- const QQuickShaderEffectMaterial *material = static_cast<const QQuickShaderEffectMaterial *>(newEffect);
-
- if (!m_textureIndicesSet) {
- for (int i = 0; i < material->m_textures.size(); ++i)
- program()->setUniformValue(material->m_textures.at(i).first.constData(), i);
- m_textureIndicesSet = true;
- }
-
- if (m_uniformLocs.size() != material->m_uniformValues.size()) {
- m_uniformLocs.reserve(material->m_uniformValues.size());
- for (int i = 0; i < material->m_uniformValues.size(); ++i) {
- const QByteArray &name = material->m_uniformValues.at(i).first;
- m_uniformLocs.append(program()->uniformLocation(name.constData()));
- }
- }
-
- QOpenGLFunctions *functions = state.context()->functions();
- for (int i = material->m_textures.size() - 1; i >= 0; --i) {
- functions->glActiveTexture(GL_TEXTURE0 + i);
- if (QSGTextureProvider *provider = material->m_textures.at(i).second) {
- if (QSGTexture *texture = provider->texture()) {
- texture->bind();
- continue;
- }
- }
- qWarning("ShaderEffect: source or provider missing when binding textures");
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- if (material->m_source.respectsOpacity)
- program()->setUniformValue(m_opacityLoc, state.opacity());
-
- for (int i = 0; i < material->m_uniformValues.count(); ++i) {
- const QVariant &v = material->m_uniformValues.at(i).second;
-
- switch (v.type()) {
- case QVariant::Color:
- program()->setUniformValue(m_uniformLocs.at(i), qt_premultiply_color(qvariant_cast<QColor>(v)));
- break;
- case QVariant::Double:
- program()->setUniformValue(m_uniformLocs.at(i), (float) qvariant_cast<double>(v));
- break;
- case QVariant::Transform:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QTransform>(v));
- break;
- case QVariant::Int:
- program()->setUniformValue(m_uniformLocs.at(i), v.toInt());
- break;
- case QVariant::Bool:
- program()->setUniformValue(m_uniformLocs.at(i), GLint(v.toBool()));
- break;
- case QVariant::Size:
- case QVariant::SizeF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toSizeF());
- break;
- case QVariant::Point:
- case QVariant::PointF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toPointF());
- break;
- case QVariant::Rect:
- case QVariant::RectF:
- {
- QRectF r = v.toRectF();
- program()->setUniformValue(m_uniformLocs.at(i), r.x(), r.y(), r.width(), r.height());
- }
- break;
- case QVariant::Vector3D:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QVector3D>(v));
- break;
- default:
- break;
- }
- }
-
- const QQuickShaderEffectMaterial *oldMaterial = static_cast<const QQuickShaderEffectMaterial *>(oldEffect);
- if (oldEffect == 0 || material->cullMode() != oldMaterial->cullMode()) {
- switch (material->cullMode()) {
- case QQuickShaderEffectMaterial::FrontFaceCulling:
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
- break;
- case QQuickShaderEffectMaterial::BackFaceCulling:
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- break;
- default:
- glDisable(GL_CULL_FACE);
- break;
- }
- }
-
- if ((state.isMatrixDirty()) && material->m_source.respectsMatrix)
- program()->setUniformValue(m_matrixLoc, state.combinedMatrix());
-}
-
-char const *const *QQuickCustomMaterialShader::attributeNames() const
-{
- return m_attributeNames.constData();
-}
-
-void QQuickCustomMaterialShader::initialize()
-{
- m_opacityLoc = program()->uniformLocation("qt_Opacity");
- m_matrixLoc = program()->uniformLocation("qt_Matrix");
-}
-
-const char *QQuickCustomMaterialShader::vertexShader() const
-{
- return m_key.vertexCode.constData();
-}
-
-const char *QQuickCustomMaterialShader::fragmentShader() const
-{
- return m_key.fragmentCode.constData();
-}
-
-
-bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const
-{
- return vertexCode == other.vertexCode && fragmentCode == other.fragmentCode && className == other.className;
-}
-
-uint qHash(const QQuickShaderEffectMaterialKey &key)
-{
- return qHash(qMakePair(qMakePair(key.vertexCode, key.fragmentCode), key.className));
-}
-
-
-QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > QQuickShaderEffectMaterial::materialMap;
-
-QQuickShaderEffectMaterial::QQuickShaderEffectMaterial()
- : m_cullMode(NoCulling)
-{
- setFlag(Blending, true);
-}
-
-QSGMaterialType *QQuickShaderEffectMaterial::type() const
-{
- return m_type.data();
-}
-
-QSGMaterialShader *QQuickShaderEffectMaterial::createShader() const
-{
- return new QQuickCustomMaterialShader(m_source, m_source.attributeNames);
-}
-
-int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
-{
- return this - static_cast<const QQuickShaderEffectMaterial *>(other);
-}
-
-void QQuickShaderEffectMaterial::setCullMode(QQuickShaderEffectMaterial::CullMode face)
-{
- m_cullMode = face;
-}
-
-QQuickShaderEffectMaterial::CullMode QQuickShaderEffectMaterial::cullMode() const
-{
- return m_cullMode;
-}
-
-void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgram &source)
-{
- m_source = source;
- m_type = materialMap.value(m_source);
- if (m_type.isNull()) {
- m_type = QSharedPointer<QSGMaterialType>(new QSGMaterialType);
- materialMap.insert(m_source, m_type);
- }
-}
-
-void QQuickShaderEffectMaterial::setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues)
-{
- m_uniformValues = uniformValues;
-}
-
-void QQuickShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures)
-{
- m_textures = textures;
-}
-
-const QVector<QPair<QByteArray, QSGTextureProvider *> > &QQuickShaderEffectMaterial::textureProviders() const
-{
- return m_textures;
-}
-
-void QQuickShaderEffectMaterial::updateTextures() const
-{
- for (int i = 0; i < m_textures.size(); ++i) {
- if (QSGTextureProvider *provider = m_textures.at(i).second) {
- if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
- texture->updateTexture();
- }
- }
-}
-
-
-QQuickShaderEffectNode::QQuickShaderEffectNode()
-{
- QSGNode::setFlag(UsePreprocess, true);
- setMaterial(&m_material);
-
-#ifdef QML_RUNTIME_TESTING
- description = QLatin1String("shadereffect");
-#endif
-}
-
-QQuickShaderEffectNode::~QQuickShaderEffectNode()
-{
-}
-
-void QQuickShaderEffectNode::markDirtyTexture()
-{
- markDirty(DirtyMaterial);
-}
-
-void QQuickShaderEffectNode::preprocess()
-{
- Q_ASSERT(material());
- static_cast<QQuickShaderEffectMaterial *>(material())->updateTextures();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickshadereffectnode_p.h b/src/declarative/items/qquickshadereffectnode_p.h
deleted file mode 100644
index 50213ff396..0000000000
--- a/src/declarative/items/qquickshadereffectnode_p.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKSHADEREFFECTNODE_P_H
-#define QQUICKSHADEREFFECTNODE_P_H
-
-#include "qsgnode.h"
-#include "qsgmaterial.h"
-#include <private/qsgtextureprovider_p.h>
-#include <qquickitem.h>
-
-#include <QtCore/qsharedpointer.h>
-#include <QtCore/qpointer.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-struct QQuickShaderEffectMaterialKey {
- QByteArray vertexCode;
- QByteArray fragmentCode;
- const char *className;
-
- bool operator == (const QQuickShaderEffectMaterialKey &other) const;
-};
-
-uint qHash(const QQuickShaderEffectMaterialKey &key);
-
-// TODO: Implement support for multisampling.
-struct QQuickShaderEffectProgram : public QQuickShaderEffectMaterialKey
-{
- QQuickShaderEffectProgram() : respectsOpacity(false), respectsMatrix(false) {}
-
- QVector<QByteArray> attributeNames;
- QSet<QByteArray> uniformNames;
-
- uint respectsOpacity : 1;
- uint respectsMatrix : 1;
-};
-
-
-class QQuickCustomMaterialShader;
-class QQuickShaderEffectMaterial : public QSGMaterial
-{
-public:
- enum CullMode
- {
- NoCulling,
- BackFaceCulling,
- FrontFaceCulling
- };
-
- QQuickShaderEffectMaterial();
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
-
- void setCullMode(CullMode face);
- CullMode cullMode() const;
-
- void setProgramSource(const QQuickShaderEffectProgram &);
- void setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues);
- void setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures);
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &textureProviders() const;
- void updateTextures() const;
-
-protected:
- friend class QQuickCustomMaterialShader;
-
- // The type pointer needs to be unique. It is not safe to let the type object be part of the
- // QQuickShaderEffectMaterial, since it can be deleted and a new one constructed on top of the old
- // one. The new QQuickShaderEffectMaterial would then get the same type pointer as the old one, and
- // CustomMaterialShaders based on the old one would incorrectly be used together with the new
- // one. To guarantee that the type pointer is unique, the type object must live as long as
- // there are any CustomMaterialShaders of that type.
- QSharedPointer<QSGMaterialType> m_type;
-
- QQuickShaderEffectProgram m_source;
- QVector<QPair<QByteArray, QVariant> > m_uniformValues;
- QVector<QPair<QByteArray, QSGTextureProvider *> > m_textures;
- CullMode m_cullMode;
-
- static QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > materialMap;
-};
-
-
-class QSGShaderEffectMesh;
-
-class QQuickShaderEffectNode : public QObject, public QSGGeometryNode
-{
- Q_OBJECT
-public:
- QQuickShaderEffectNode();
- virtual ~QQuickShaderEffectNode();
-
- virtual void preprocess();
-
- QQuickShaderEffectMaterial *shaderMaterial() { return &m_material; }
-
-private Q_SLOTS:
- void markDirtyTexture();
-
-private:
- QQuickShaderEffectMaterial m_material;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSHADEREFFECTNODE_P_H
diff --git a/src/declarative/items/qquickshadereffectsource.cpp b/src/declarative/items/qquickshadereffectsource.cpp
deleted file mode 100644
index 952f240cd3..0000000000
--- a/src/declarative/items/qquickshadereffectsource.cpp
+++ /dev/null
@@ -1,921 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickshadereffectsource_p.h"
-
-#include "qquickitem_p.h"
-#include "qquickcanvas_p.h"
-#include <private/qsgadaptationlayer_p.h>
-#include <private/qsgrenderer_p.h>
-
-#include "qopenglframebufferobject.h"
-#include "qmath.h"
-#include <private/qsgtexture_p.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
-
-class QQuickShaderEffectSourceTextureProvider : public QSGTextureProvider
-{
- Q_OBJECT
-public:
- QQuickShaderEffectSourceTextureProvider()
- : sourceTexture(0)
- {
- }
-
- QSGTexture *texture() const {
- sourceTexture->setMipmapFiltering(mipmapFiltering);
- sourceTexture->setFiltering(filtering);
- sourceTexture->setHorizontalWrapMode(horizontalWrap);
- sourceTexture->setVerticalWrapMode(verticalWrap);
- return sourceTexture;
- }
-
- QQuickShaderEffectTexture *sourceTexture;
-
- QSGTexture::Filtering mipmapFiltering;
- QSGTexture::Filtering filtering;
- QSGTexture::WrapMode horizontalWrap;
- QSGTexture::WrapMode verticalWrap;
-};
-#include "qquickshadereffectsource.moc"
-
-
-QQuickShaderEffectSourceNode::QQuickShaderEffectSourceNode()
-{
- setFlag(UsePreprocess, true);
-}
-
-void QQuickShaderEffectSourceNode::markDirtyTexture()
-{
- markDirty(DirtyMaterial);
-}
-
-
-QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource)
- : QSGDynamicTexture()
- , m_item(0)
- , m_format(GL_RGBA)
- , m_shaderSource(shaderSource)
- , m_renderer(0)
- , m_fbo(0)
- , m_secondaryFbo(0)
-#ifdef QSG_DEBUG_FBO_OVERLAY
- , m_debugOverlay(0)
-#endif
- , m_context(QQuickItemPrivate::get(shaderSource)->sceneGraphContext())
- , m_mipmap(false)
- , m_live(true)
- , m_recursive(false)
- , m_dirtyTexture(true)
- , m_multisamplingSupportChecked(false)
- , m_multisampling(false)
- , m_grab(false)
-{
-}
-
-QQuickShaderEffectTexture::~QQuickShaderEffectTexture()
-{
- if (m_renderer)
- disconnect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
- delete m_renderer;
- delete m_fbo;
- delete m_secondaryFbo;
-#ifdef QSG_DEBUG_FBO_OVERLAY
- delete m_debugOverlay;
-#endif
-}
-
-int QQuickShaderEffectTexture::textureId() const
-{
- return m_fbo ? m_fbo->texture() : 0;
-}
-
-bool QQuickShaderEffectTexture::hasAlphaChannel() const
-{
- return m_format != GL_RGB;
-}
-
-bool QQuickShaderEffectTexture::hasMipmaps() const
-{
- return m_mipmap;
-}
-
-
-void QQuickShaderEffectTexture::bind()
-{
-#ifndef QT_NO_DEBUG
- if (!m_recursive && m_fbo && ((m_multisampling && m_secondaryFbo->isBound()) || m_fbo->isBound()))
- qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively.");
-#endif
- glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
- updateBindOptions();
-}
-
-bool QQuickShaderEffectTexture::updateTexture()
-{
- if ((m_live || m_grab) && m_dirtyTexture) {
- grab();
- m_grab = false;
- return true;
- }
- return false;
-}
-
-void QQuickShaderEffectTexture::setHasMipmaps(bool mipmap)
-{
- if (mipmap == m_mipmap)
- return;
- m_mipmap = mipmap;
- if (m_mipmap && m_fbo && !m_fbo->format().mipmap())
- markDirtyTexture();
-}
-
-
-void QQuickShaderEffectTexture::setItem(QSGNode *item)
-{
- if (item == m_item)
- return;
- m_item = item;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setRect(const QRectF &rect)
-{
- if (rect == m_rect)
- return;
- m_rect = rect;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setSize(const QSize &size)
-{
- if (size == m_size)
- return;
- m_size = size;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setFormat(GLenum format)
-{
- if (format == m_format)
- return;
- m_format = format;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::setLive(bool live)
-{
- if (live == m_live)
- return;
- m_live = live;
- markDirtyTexture();
-}
-
-void QQuickShaderEffectTexture::scheduleUpdate()
-{
- if (m_grab)
- return;
- m_grab = true;
- if (m_dirtyTexture)
- emit updateRequested();
-}
-
-void QQuickShaderEffectTexture::setRecursive(bool recursive)
-{
- m_recursive = recursive;
-}
-
-void QQuickShaderEffectTexture::markDirtyTexture()
-{
- m_dirtyTexture = true;
- if (m_live || m_grab)
- emit updateRequested();
-}
-
-void QQuickShaderEffectTexture::grab()
-{
- if (!m_item || m_size.isNull()) {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = m_secondaryFbo = 0;
- m_dirtyTexture = false;
- if (m_grab)
- emit scheduledUpdateCompleted();
- return;
- }
- QSGNode *root = m_item;
- while (root->firstChild() && root->type() != QSGNode::RootNodeType)
- root = root->firstChild();
- if (root->type() != QSGNode::RootNodeType)
- return;
-
- if (!m_renderer) {
- m_renderer = m_context->createRenderer();
- connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
- }
- m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
-
- bool deleteFboLater = false;
- if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
- || (!m_fbo->format().mipmap() && m_mipmap))
- {
- if (!m_multisamplingSupportChecked) {
- QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
- m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample")
- && extensions.contains("GL_EXT_framebuffer_blit");
- m_multisamplingSupportChecked = true;
- }
- if (m_multisampling) {
- // Don't delete the FBO right away in case it is used recursively.
- deleteFboLater = true;
- delete m_secondaryFbo;
- QOpenGLFramebufferObjectFormat format;
-
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(m_format);
- format.setSamples(8);
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
- } else {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(m_format);
- format.setMipmap(m_mipmap);
- if (m_recursive) {
- deleteFboLater = true;
- delete m_secondaryFbo;
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
- glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
- updateBindOptions(true);
- } else {
- delete m_fbo;
- delete m_secondaryFbo;
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- m_secondaryFbo = 0;
- glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
- }
- }
-
- if (m_recursive && !m_secondaryFbo) {
- // m_fbo already created, m_recursive was just set.
- Q_ASSERT(m_fbo);
- Q_ASSERT(!m_multisampling);
-
- m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
- glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
- updateBindOptions(true);
- }
-
- // Render texture.
- root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
- m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update.
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- if (qmlFboOverlay()) {
- if (!m_debugOverlay)
- m_debugOverlay = m_context->createRectangleNode();
- m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
- m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
- m_debugOverlay->setPenColor(QColor());
- m_debugOverlay->setPenWidth(0);
- m_debugOverlay->setRadius(0);
- m_debugOverlay->update();
- root->appendChildNode(m_debugOverlay);
- }
-#endif
-
- m_dirtyTexture = false;
-
- QOpenGLContext *ctx = m_context->glContext();
- m_renderer->setDeviceRect(m_size);
- m_renderer->setViewportRect(m_size);
- QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
- m_renderer->setProjectionMatrixToRect(mirrored);
- m_renderer->setClearColor(Qt::transparent);
-
- if (m_multisampling) {
- m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
-
- if (deleteFboLater) {
- delete m_fbo;
- QOpenGLFramebufferObjectFormat format;
- format.setInternalTextureFormat(m_format);
- format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
- format.setMipmap(m_mipmap);
- format.setSamples(0);
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
-
- QRect r(QPoint(), m_size);
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
- } else {
- if (m_recursive) {
- m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
-
- if (deleteFboLater) {
- delete m_fbo;
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(m_format);
- format.setMipmap(m_mipmap);
- m_fbo = new QOpenGLFramebufferObject(m_size, format);
- glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
- qSwap(m_fbo, m_secondaryFbo);
- } else {
- m_renderer->renderScene(QSGBindableFbo(m_fbo));
- }
- }
-
- if (m_mipmap) {
- glBindTexture(GL_TEXTURE_2D, textureId());
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
- }
-
- root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- if (qmlFboOverlay())
- root->removeChildNode(m_debugOverlay);
-#endif
- if (m_recursive)
- markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
-
- if (m_grab)
- emit scheduledUpdateCompleted();
-}
-
-QImage QQuickShaderEffectTexture::toImage() const
-{
- if (m_fbo)
- return m_fbo->toImage();
-
- return QImage();
-}
-
-/*!
- \qmlclass ShaderEffectSource QQuickShaderEffectSource
- \since 5.0
- \ingroup qml-basic-visual-elements
- \brief The ShaderEffectSource element renders a QML element into a texture
- and displays it.
- \inherits Item
-
- The ShaderEffectSource element renders \l sourceItem into a texture and
- displays it in the scene. \l sourceItem is drawn into the texture as though
- it was a fully opaque root element. Thus \l sourceItem itself can be
- invisible, but still appear in the texture.
-
- ShaderEffectSource can be used as:
- \list
- \o a texture source in a \l ShaderEffect.
- This allows you to apply custom shader effects to any QML element.
- \o a cache for a complex element.
- The complex element can be rendered once into the texture, which can
- then be animated freely without the need to render the complex element
- again every frame.
- \o an opacity layer.
- ShaderEffectSource allows you to apply an opacity to elements as a group
- rather than each element individually.
- \endlist
-
- \table
- \row
- \o \image declarative-shadereffectsource.png
- \o \qml
- import QtQuick 2.0
-
- Rectangle {
- width: 200
- height: 100
- gradient: Gradient {
- GradientStop { position: 0; color: "white" }
- GradientStop { position: 1; color: "black" }
- }
- Row {
- opacity: 0.5
- Item {
- id: foo
- width: 100; height: 100
- Rectangle { x: 5; y: 5; width: 60; height: 60; color: "red" }
- Rectangle { x: 20; y: 20; width: 60; height: 60; color: "orange" }
- Rectangle { x: 35; y: 35; width: 60; height: 60; color: "yellow" }
- }
- ShaderEffectSource {
- width: 100; height: 100
- sourceItem: foo
- }
- }
- }
- \endqml
- \endrow
- \endtable
-
- The ShaderEffectSource element does not redirect any mouse or keyboard
- input to \l sourceItem. If you hide the \l sourceItem by setting
- \l{Item::visible}{visible} to false or \l{Item::opacity}{opacity} to zero,
- it will no longer react to input. In cases where the ShaderEffectSource is
- meant to replace the \l sourceItem, you typically want to hide the
- \l sourceItem while still handling input. For this, you can use
- the \l hideSource property.
-
- \note If \l sourceItem is a \l Rectangle with border, by default half the
- border width falls outside the texture. To get the whole border, you can
- extend the \l sourceRect.
-
- \warning In most cases, using a ShaderEffectSource will decrease
- performance, and in all cases, it will increase video memory usage.
- Rendering through a ShaderEffectSource might also lead to lower quality
- since some OpenGL implementations support multisampled backbuffer,
- but not multisampled framebuffer objects.
-*/
-
-QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
- : QQuickItem(parent)
- , m_provider(0)
- , m_texture(0)
- , m_wrapMode(ClampToEdge)
- , m_sourceItem(0)
- , m_textureSize(0, 0)
- , m_format(RGBA)
- , m_live(true)
- , m_hideSource(false)
- , m_mipmap(false)
- , m_recursive(false)
- , m_grab(true)
-{
- setFlag(ItemHasContents);
-}
-
-QQuickShaderEffectSource::~QQuickShaderEffectSource()
-{
- if (m_texture)
- m_texture->deleteLater();
-
- if (m_provider)
- m_provider->deleteLater();
-
- if (m_sourceItem) {
- QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem);
- sd->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
- sd->derefFromEffectItem(m_hideSource);
- }
-}
-
-void QQuickShaderEffectSource::ensureTexture()
-{
- if (m_texture)
- return;
-
- Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
- && QQuickItemPrivate::get(this)->sceneGraphContext()
- && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
- "QQuickShaderEffectSource::ensureTexture",
- "Cannot be used outside the rendering thread");
-
- m_texture = new QQuickShaderEffectTexture(this);
- connect(m_texture, SIGNAL(updateRequested()), this, SLOT(update()));
- connect(m_texture, SIGNAL(scheduledUpdateCompleted()), this, SIGNAL(scheduledUpdateCompleted()));
-}
-
-QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const
-{
- if (!m_provider) {
- // Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
- && QQuickItemPrivate::get(this)->sceneGraphContext()
- && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
- "QQuickShaderEffectSource::textureProvider",
- "Cannot be used outside the rendering thread");
- const_cast<QQuickShaderEffectSource *>(this)->m_provider = new QQuickShaderEffectSourceTextureProvider();
- const_cast<QQuickShaderEffectSource *>(this)->ensureTexture();
- connect(m_texture, SIGNAL(updateRequested()), m_provider, SIGNAL(textureChanged()));
- m_provider->sourceTexture = m_texture;
- }
- return m_provider;
-}
-
-/*!
- \qmlproperty enumeration ShaderEffectSource::wrapMode
-
- This property defines the OpenGL wrap modes associated with the texture.
- Modifying this property makes most sense when the element is used as a
- source texture of a \l ShaderEffect.
-
- \list
- \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically
- \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
- \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
- \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically
- \endlist
-
- \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
- wrap mode with non-power-of-two textures.
-*/
-
-QQuickShaderEffectSource::WrapMode QQuickShaderEffectSource::wrapMode() const
-{
- return m_wrapMode;
-}
-
-void QQuickShaderEffectSource::setWrapMode(WrapMode mode)
-{
- if (mode == m_wrapMode)
- return;
- m_wrapMode = mode;
- update();
- emit wrapModeChanged();
-}
-
-/*!
- \qmlproperty Item ShaderEffectSource::sourceItem
-
- This property holds the element to be rendered into the texture.
-*/
-
-QQuickItem *QQuickShaderEffectSource::sourceItem() const
-{
- return m_sourceItem;
-}
-
-void QQuickShaderEffectSource::itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect)
-{
- Q_ASSERT(item == m_sourceItem);
- Q_UNUSED(item);
- if (newRect.size() != oldRect.size())
- update();
-}
-
-void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
-{
- if (item == m_sourceItem)
- return;
- if (m_sourceItem) {
- QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
- d->derefFromEffectItem(m_hideSource);
- d->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
- }
- m_sourceItem = item;
- if (m_sourceItem) {
- // TODO: Find better solution.
- // 'm_sourceItem' needs a canvas to get a scenegraph node.
- // The easiest way to make sure it gets a canvas is to
- // make it a part of the same item tree as 'this'.
- if (m_sourceItem->parentItem() == 0) {
- m_sourceItem->setParentItem(this);
- m_sourceItem->setVisible(false);
- }
- QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
- d->refFromEffectItem(m_hideSource);
- d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- }
- update();
- emit sourceItemChanged();
-}
-
-/*!
- \qmlproperty rect ShaderEffectSource::sourceRect
-
- This property defines which rectangular area of the \l sourceItem to
- render into the texture. The source rectangle can be larger than
- \l sourceItem itself. If the rectangle is null, which is the default,
- the whole \l sourceItem is rendered to texture.
-*/
-
-QRectF QQuickShaderEffectSource::sourceRect() const
-{
- return m_sourceRect;
-}
-
-void QQuickShaderEffectSource::setSourceRect(const QRectF &rect)
-{
- if (rect == m_sourceRect)
- return;
- m_sourceRect = rect;
- update();
- emit sourceRectChanged();
-}
-
-/*!
- \qmlproperty size ShaderEffectSource::textureSize
-
- This property holds the requested size of the texture. If it is empty,
- which is the default, the size of the source rectangle is used.
-
- \note Some platforms have a limit on how small framebuffer objects can be,
- which means the actual texture size might be larger than the requested
- size.
-*/
-
-QSize QQuickShaderEffectSource::textureSize() const
-{
- return m_textureSize;
-}
-
-void QQuickShaderEffectSource::setTextureSize(const QSize &size)
-{
- if (size == m_textureSize)
- return;
- m_textureSize = size;
- update();
- emit textureSizeChanged();
-}
-
-/*!
- \qmlproperty enumeration ShaderEffectSource::format
-
- This property defines the internal OpenGL format of the texture.
- Modifying this property makes most sense when the element is used as a
- source texture of a \l ShaderEffect. Depending on the OpenGL
- implementation, this property might allow you to save some texture memory.
-
- \list
- \o ShaderEffectSource.Alpha - GL_ALPHA
- \o ShaderEffectSource.RGB - GL_RGB
- \o ShaderEffectSource.RGBA - GL_RGBA
- \endlist
-
- \note Some OpenGL implementations do not support the GL_ALPHA format.
-*/
-
-QQuickShaderEffectSource::Format QQuickShaderEffectSource::format() const
-{
- return m_format;
-}
-
-void QQuickShaderEffectSource::setFormat(QQuickShaderEffectSource::Format format)
-{
- if (format == m_format)
- return;
- m_format = format;
- update();
- emit formatChanged();
-}
-
-/*!
- \qmlproperty bool ShaderEffectSource::live
-
- If this property is true, the texture is updated whenever the
- \l sourceItem changes. Otherwise, it will be a frozen image of the
- \l sourceItem. The property is true by default.
-*/
-
-bool QQuickShaderEffectSource::live() const
-{
- return m_live;
-}
-
-void QQuickShaderEffectSource::setLive(bool live)
-{
- if (live == m_live)
- return;
- m_live = live;
- update();
- emit liveChanged();
-}
-
-/*!
- \qmlproperty bool ShaderEffectSource::hideSource
-
- If this property is true, the \l sourceItem is hidden, though it will still
- be rendered into the texture. As opposed to hiding the \l sourceItem by
- setting \l{Item::visible}{visible} to false, setting this property to true
- will not prevent mouse or keyboard input from reaching \l sourceItem.
- The property is useful when the ShaderEffectSource is anchored on top of,
- and meant to replace the \l sourceItem.
-*/
-
-bool QQuickShaderEffectSource::hideSource() const
-{
- return m_hideSource;
-}
-
-void QQuickShaderEffectSource::setHideSource(bool hide)
-{
- if (hide == m_hideSource)
- return;
- if (m_sourceItem) {
- QQuickItemPrivate::get(m_sourceItem)->refFromEffectItem(hide);
- QQuickItemPrivate::get(m_sourceItem)->derefFromEffectItem(m_hideSource);
- }
- m_hideSource = hide;
- update();
- emit hideSourceChanged();
-}
-
-/*!
- \qmlproperty bool ShaderEffectSource::mipmap
-
- If this property is true, mipmaps are generated for the texture.
-
- \note Some OpenGL ES 2 implementations do not support mipmapping of
- non-power-of-two textures.
-*/
-
-bool QQuickShaderEffectSource::mipmap() const
-{
- return m_mipmap;
-}
-
-void QQuickShaderEffectSource::setMipmap(bool enabled)
-{
- if (enabled == m_mipmap)
- return;
- m_mipmap = enabled;
- update();
- emit mipmapChanged();
-}
-
-/*!
- \qmlproperty bool ShaderEffectSource::recursive
-
- Set this property to true if the ShaderEffectSource has a dependency on
- itself. ShaderEffectSources form a dependency chain, where one
- ShaderEffectSource can be part of the \l sourceItem of another.
- If there is a loop in this chain, a ShaderEffectSource could end up trying
- to render into the same texture it is using as source, which is not allowed
- by OpenGL. When this property is set to true, an extra texture is allocated
- so that ShaderEffectSource can keep a copy of the texture from the previous
- frame. It can then render into one texture and use the texture from the
- previous frame as source.
-
- Setting both this property and \l live to true will cause the scene graph
- to render continuously. Since the ShaderEffectSource depends on itself,
- updating it means that it immediately becomes dirty again.
-*/
-
-bool QQuickShaderEffectSource::recursive() const
-{
- return m_recursive;
-}
-
-void QQuickShaderEffectSource::setRecursive(bool enabled)
-{
- if (enabled == m_recursive)
- return;
- m_recursive = enabled;
- emit recursiveChanged();
-}
-
-/*!
- \qmlmethod ShaderEffectSource::scheduleUpdate()
-
- Schedules a re-rendering of the texture for the next frame.
- Use this to update the texture when \l live is false.
-*/
-
-void QQuickShaderEffectSource::scheduleUpdate()
-{
- if (m_grab)
- return;
- m_grab = true;
- update();
-}
-
-static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::WrapMode *hWrap, QSGTexture::WrapMode *vWrap)
-{
- switch (mode) {
- case QQuickShaderEffectSource::RepeatHorizontally:
- *hWrap = QSGTexture::Repeat;
- *vWrap = QSGTexture::ClampToEdge;
- break;
- case QQuickShaderEffectSource::RepeatVertically:
- *vWrap = QSGTexture::Repeat;
- *hWrap = QSGTexture::ClampToEdge;
- break;
- case QQuickShaderEffectSource::Repeat:
- *hWrap = *vWrap = QSGTexture::Repeat;
- break;
- default:
- // QQuickShaderEffectSource::ClampToEdge
- *hWrap = *vWrap = QSGTexture::ClampToEdge;
- break;
- }
-}
-
-
-QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
- delete oldNode;
- return 0;
- }
-
- ensureTexture();
-
- QQuickShaderEffectTexture *tex = qobject_cast<QQuickShaderEffectTexture *>(m_texture);
- tex->setLive(m_live);
- tex->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);
- QSize textureSize = m_textureSize.isEmpty()
- ? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())))
- : m_textureSize;
- Q_ASSERT(!textureSize.isEmpty());
- QQuickItemPrivate *d = static_cast<QQuickItemPrivate *>(QObjectPrivate::get(this));
- const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
- // Keep power-of-two by doubling the size.
- while (textureSize.width() < minTextureSize.width())
- textureSize.rwidth() *= 2;
- while (textureSize.height() < minTextureSize.height())
- textureSize.rheight() *= 2;
-
- tex->setSize(textureSize);
- tex->setRecursive(m_recursive);
- tex->setFormat(GLenum(m_format));
- tex->setHasMipmaps(m_mipmap);
-
- if (m_grab)
- tex->scheduleUpdate();
- m_grab = false;
-
- QSGTexture::Filtering filtering = QQuickItemPrivate::get(this)->smooth
- ? QSGTexture::Linear
- : QSGTexture::Nearest;
- QSGTexture::Filtering mmFiltering = m_mipmap ? filtering : QSGTexture::None;
- QSGTexture::WrapMode hWrap, vWrap;
- get_wrap_mode(m_wrapMode, &hWrap, &vWrap);
-
- if (m_provider) {
- m_provider->mipmapFiltering = mmFiltering;
- m_provider->filtering = filtering;
- m_provider->horizontalWrap = hWrap;
- m_provider->verticalWrap = vWrap;
- }
-
- // Don't create the paint node if we're not spanning any area
- if (width() == 0 || height() == 0) {
- delete oldNode;
- return 0;
- }
-
- QQuickShaderEffectSourceNode *node = static_cast<QQuickShaderEffectSourceNode *>(oldNode);
- if (!node) {
- node = new QQuickShaderEffectSourceNode;
- node->setTexture(m_texture);
- connect(m_texture, SIGNAL(updateRequested()), node, SLOT(markDirtyTexture()));
- }
-
- // If live and recursive, update continuously.
- if (m_live && m_recursive)
- node->markDirty(QSGNode::DirtyMaterial);
-
- node->setMipmapFiltering(mmFiltering);
- node->setFiltering(filtering);
- node->setHorizontalWrapMode(hWrap);
- node->setVerticalWrapMode(vWrap);
- node->setTargetRect(QRectF(0, 0, width(), height()));
- node->setSourceRect(QRectF(0, 0, 1, 1));
- node->update();
-
- return node;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickshadereffectsource_p.h b/src/declarative/items/qquickshadereffectsource_p.h
deleted file mode 100644
index fee361c27c..0000000000
--- a/src/declarative/items/qquickshadereffectsource_p.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKSHADEREFFECTSOURCE_P_H
-#define QQUICKSHADEREFFECTSOURCE_P_H
-
-#include "qquickitem.h"
-#include <private/qsgtextureprovider_p.h>
-#include <private/qsgadaptationlayer_p.h>
-#include <private/qsgcontext_p.h>
-#include <private/qsgdefaultimagenode_p.h>
-#include <private/qquickitemchangelistener_p.h>
-
-#include "qpointer.h"
-#include "qsize.h"
-#include "qrect.h"
-
-#define QSG_DEBUG_FBO_OVERLAY
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGNode;
-class UpdatePaintNodeData;
-class QOpenGLFramebufferObject;
-
-class QQuickShaderEffectSourceTextureProvider;
-
-class QQuickShaderEffectSourceNode : public QObject, public QSGDefaultImageNode
-{
- Q_OBJECT
-
-public:
- QQuickShaderEffectSourceNode();
-
-private Q_SLOTS:
- void markDirtyTexture();
-};
-
-class Q_DECLARATIVE_EXPORT QQuickShaderEffectTexture : public QSGDynamicTexture
-{
- Q_OBJECT
-public:
- QQuickShaderEffectTexture(QQuickItem *shaderSource);
- ~QQuickShaderEffectTexture();
-
- virtual bool updateTexture();
-
- // The item's "paint node", not effect node.
- QSGNode *item() const { return m_item; }
- void setItem(QSGNode *item);
-
- QRectF rect() const { return m_rect; }
- void setRect(const QRectF &rect);
-
- QSize size() const { return m_size; }
- void setSize(const QSize &size);
-
- void setHasMipmaps(bool mipmap);
-
- void bind();
-
- bool hasAlphaChannel() const;
- bool hasMipmaps() const;
- int textureId() const;
- QSize textureSize() const { return m_size; }
-
- GLenum format() const { return m_format; }
- void setFormat(GLenum format);
-
- bool live() const { return bool(m_live); }
- void setLive(bool live);
-
- bool recursive() const { return bool(m_recursive); }
- void setRecursive(bool recursive);
-
- void scheduleUpdate();
-
- QImage toImage() const;
-
-Q_SIGNALS:
- void updateRequested();
- void scheduledUpdateCompleted();
-
-public Q_SLOTS:
- void markDirtyTexture();
-
-private:
- void grab();
-
- QSGNode *m_item;
- QRectF m_rect;
- QSize m_size;
- GLenum m_format;
-
- QQuickItem *m_shaderSource;
- QSGRenderer *m_renderer;
- QOpenGLFramebufferObject *m_fbo;
- QOpenGLFramebufferObject *m_secondaryFbo;
-
-#ifdef QSG_DEBUG_FBO_OVERLAY
- QSGRectangleNode *m_debugOverlay;
-#endif
-
- QSGContext *m_context;
-
- uint m_mipmap : 1;
- uint m_live : 1;
- uint m_recursive : 1;
- uint m_dirtyTexture : 1;
- uint m_multisamplingSupportChecked : 1;
- uint m_multisampling : 1;
- uint m_grab : 1;
-};
-
-class Q_DECLARATIVE_EXPORT QQuickShaderEffectSource : public QQuickItem, public QQuickItemChangeListener
-{
- Q_OBJECT
- Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
- Q_PROPERTY(QQuickItem *sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged)
- Q_PROPERTY(QRectF sourceRect READ sourceRect WRITE setSourceRect NOTIFY sourceRectChanged)
- Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
- Q_PROPERTY(Format format READ format WRITE setFormat NOTIFY formatChanged)
- Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged)
- Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
- Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
- Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
-
- Q_ENUMS(Format WrapMode)
-public:
- enum WrapMode {
- ClampToEdge,
- RepeatHorizontally,
- RepeatVertically,
- Repeat
- };
-
- enum Format {
- Alpha = GL_ALPHA,
- RGB = GL_RGB,
- RGBA = GL_RGBA
- };
-
- QQuickShaderEffectSource(QQuickItem *parent = 0);
- ~QQuickShaderEffectSource();
-
- WrapMode wrapMode() const;
- void setWrapMode(WrapMode mode);
-
- QQuickItem *sourceItem() const;
- void setSourceItem(QQuickItem *item);
-
- QRectF sourceRect() const;
- void setSourceRect(const QRectF &rect);
-
- QSize textureSize() const;
- void setTextureSize(const QSize &size);
-
- Format format() const;
- void setFormat(Format format);
-
- bool live() const;
- void setLive(bool live);
-
- bool hideSource() const;
- void setHideSource(bool hide);
-
- bool mipmap() const;
- void setMipmap(bool enabled);
-
- bool recursive() const;
- void setRecursive(bool enabled);
-
- bool isTextureProvider() const { return true; }
- QSGTextureProvider *textureProvider() const;
-
- Q_INVOKABLE void scheduleUpdate();
-
-Q_SIGNALS:
- void wrapModeChanged();
- void sourceItemChanged();
- void sourceRectChanged();
- void textureSizeChanged();
- void formatChanged();
- void liveChanged();
- void hideSourceChanged();
- void mipmapChanged();
- void recursiveChanged();
-
- void scheduledUpdateCompleted();
-
-protected:
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
- virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect);
-
-private:
- void ensureTexture();
-
- QQuickShaderEffectSourceTextureProvider *m_provider;
- QQuickShaderEffectTexture *m_texture;
- WrapMode m_wrapMode;
- QPointer<QQuickItem> m_sourceItem;
- QRectF m_sourceRect;
- QSize m_textureSize;
- Format m_format;
- uint m_live : 1;
- uint m_hideSource : 1;
- uint m_mipmap : 1;
- uint m_recursive : 1;
- uint m_grab : 1;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSHADEREFFECTSOURCE_P_H
diff --git a/src/declarative/items/qquicksprite_p.h b/src/declarative/items/qquicksprite_p.h
deleted file mode 100644
index e7f3bbce80..0000000000
--- a/src/declarative/items/qquicksprite_p.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQUICKSPRITE_P_H
-#define QQUICKSPRITE_P_H
-
-#include <QObject>
-#include <QUrl>
-#include <QVariantMap>
-#include <QDeclarativeListProperty>
-#include "qquickspriteengine_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickSprite : public QQuickStochasticState
-{
- Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- //If frame height or width is not specified, it is assumed to be a single long row of square frames.
- //Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used.
- Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged)
- Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged)
-
-public:
- explicit QQuickSprite(QObject *parent = 0);
-
- QUrl source() const
- {
- return m_source;
- }
-
- int frameHeight() const
- {
- return m_frameHeight;
- }
-
- int frameWidth() const
- {
- return m_frameWidth;
- }
-
-
-signals:
-
- void sourceChanged(QUrl arg);
-
- void frameHeightChanged(int arg);
-
- void frameWidthChanged(int arg);
-
-public slots:
-
- void setSource(QUrl arg)
- {
- if (m_source != arg) {
- m_source = arg;
- emit sourceChanged(arg);
- }
- }
-
- void setFrameHeight(int arg)
- {
- if (m_frameHeight != arg) {
- m_frameHeight = arg;
- emit frameHeightChanged(arg);
- }
- }
-
- void setFrameWidth(int arg)
- {
- if (m_frameWidth != arg) {
- m_frameWidth = arg;
- emit frameWidthChanged(arg);
- }
- }
-
-
-private:
- friend class QSGImageParticle;
- friend class QQuickSpriteEngine;
- friend class QQuickStochasticEngine;
- int m_generatedCount;
- int m_framesPerRow;
- QUrl m_source;
- int m_frameHeight;
- int m_frameWidth;
- int m_rowY;
-
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // QQUICKSPRITE_P_H
diff --git a/src/declarative/items/qquickspriteengine_p.h b/src/declarative/items/qquickspriteengine_p.h
deleted file mode 100644
index 1040140a28..0000000000
--- a/src/declarative/items/qquickspriteengine_p.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQUICKSPRITEENGINE_P_H
-#define QQUICKSPRITEENGINE_P_H
-
-#include <QObject>
-#include <QVector>
-#include <QTimer>
-#include <QTime>
-#include <QList>
-#include <QDeclarativeListProperty>
-#include <QImage>
-#include <QPair>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickSprite;
-class Q_AUTOTEST_EXPORT QQuickStochasticState : public QObject //For internal use
-{
- Q_OBJECT
- Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
- Q_PROPERTY(int durationVariation READ durationVariance WRITE setDurationVariance NOTIFY durationVarianceChanged)
- Q_PROPERTY(QVariantMap to READ to WRITE setTo NOTIFY toChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(qreal speedModifiesDuration READ speedModifer WRITE setSpeedModifier NOTIFY speedModifierChanged)
- Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged)
-
-public:
- QQuickStochasticState(QObject* parent = 0)
- : QObject(parent)
- , m_frames(1)
- , m_duration(1000)
- {
- }
-
- int duration() const
- {
- return m_duration;
- }
-
- QString name() const
- {
- return m_name;
- }
-
- QVariantMap to() const
- {
- return m_to;
- }
-
- qreal speedModifer() const
- {
- return m_speedModifier;
- }
-
- int durationVariance() const
- {
- return m_durationVariance;
- }
-
-
- int variedDuration() const
- {
- return m_duration
- + (m_durationVariance * ((qreal)qrand()/RAND_MAX) * 2)
- - m_durationVariance;
- }
-
- int frames() const
- {
- return m_frames;
- }
-
-signals:
- void durationChanged(int arg);
-
- void nameChanged(QString arg);
-
- void toChanged(QVariantMap arg);
-
- void speedModifierChanged(qreal arg);
-
- void durationVarianceChanged(int arg);
-
- void entered();//### Just playing around - don't expect full state API
- void framesChanged(int arg);
-
-public slots:
- void setDuration(int arg)
- {
- if (m_duration != arg) {
- m_duration = arg;
- emit durationChanged(arg);
- }
- }
-
- void setName(QString arg)
- {
- if (m_name != arg) {
- m_name = arg;
- emit nameChanged(arg);
- }
- }
-
- void setTo(QVariantMap arg)
- {
- if (m_to != arg) {
- m_to = arg;
- emit toChanged(arg);
- }
- }
-
- void setSpeedModifier(qreal arg)
- {
- if (m_speedModifier != arg) {
- m_speedModifier = arg;
- emit speedModifierChanged(arg);
- }
- }
-
- void setDurationVariance(int arg)
- {
- if (m_durationVariance != arg) {
- m_durationVariance = arg;
- emit durationVarianceChanged(arg);
- }
- }
-
- void setFrames(int arg)
- {
- if (m_frames != arg) {
- m_frames = arg;
- emit framesChanged(arg);
- }
- }
-
-private:
- QString m_name;
- int m_frames;
- QVariantMap m_to;
- int m_duration;
- qreal m_speedModifier;
- int m_durationVariance;
-
- friend class QQuickStochasticEngine;
-};
-
-class Q_AUTOTEST_EXPORT QQuickStochasticEngine : public QObject
-{
- Q_OBJECT
- //TODO: Optimize single state case?
- Q_PROPERTY(QString globalGoal READ globalGoal WRITE setGlobalGoal NOTIFY globalGoalChanged)
- Q_PROPERTY(QDeclarativeListProperty<QQuickStochasticState> states READ states)
-public:
- explicit QQuickStochasticEngine(QObject *parent = 0);
- QQuickStochasticEngine(QList<QQuickStochasticState*> states, QObject *parent=0);
- ~QQuickStochasticEngine();
-
- QDeclarativeListProperty<QQuickStochasticState> states()
- {
- return QDeclarativeListProperty<QQuickStochasticState>(this, m_states);
- }
-
- QString globalGoal() const
- {
- return m_globalGoal;
- }
-
- int count() const {return m_things.count();}
- void setCount(int c);
-
- void setGoal(int state, int sprite=0, bool jump=false);
- void start(int index=0, int state=0);
- void stop(int index=0);
- int curState(int index=0) {return m_things[index];}
-
- QQuickStochasticState* state(int idx){return m_states[idx];}
- int stateIndex(QQuickStochasticState* s){return m_states.indexOf(s);}
- int stateIndex(const QString& s) {
- for (int i=0; i<m_states.count(); i++)
- if (m_states[i]->name() == s)
- return i;
- return -1;
- }
-
- int stateCount() {return m_states.count();}
-private:
-signals:
-
- void globalGoalChanged(QString arg);
- void stateChanged(int idx);
-
-public slots:
- void setGlobalGoal(QString arg)
- {
- if (m_globalGoal != arg) {
- m_globalGoal = arg;
- emit globalGoalChanged(arg);
- }
- }
-
- uint updateSprites(uint time);
-
-protected:
- friend class QQuickParticleSystem;
- void restart(int index);
- void addToUpdateList(uint t, int idx);
- int goalSeek(int curState, int idx, int dist=-1);
- QList<QQuickStochasticState*> m_states;
- //### Consider struct or class for the four data variables?
- QVector<int> m_things;//int is the index in m_states of the current state
- QVector<int> m_goals;
- QVector<int> m_duration;
- QVector<int> m_startTimes;
- QList<QPair<uint, QList<int> > > m_stateUpdates;//### This could be done faster - priority queue?
-
- QTime m_advanceTime;
- uint m_timeOffset;
- QString m_globalGoal;
- int m_maxFrames;
- int m_imageStateCount;
-};
-
-class QQuickSpriteEngine : public QQuickStochasticEngine
-{
- Q_OBJECT
- Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
-public:
- explicit QQuickSpriteEngine(QObject *parent = 0);
- QQuickSpriteEngine(QList<QQuickSprite*> sprites, QObject *parent=0);
- ~QQuickSpriteEngine();
- QDeclarativeListProperty<QQuickSprite> sprites()
- {
- return QDeclarativeListProperty<QQuickSprite>(this, m_sprites);
- }
-
-
- int spriteState(int sprite=0);
- int spriteStart(int sprite=0);
- int spriteFrames(int sprite=0);
- int spriteDuration(int sprite=0);
- int spriteX(int /* sprite */ = 0) { return 0; }//Currently all rows are 0 aligned, if we get more space efficient we might change this
- int spriteY(int sprite=0);
- int spriteWidth(int sprite=0);
- int spriteHeight(int sprite=0);
- int spriteCount();//Like state count, but for the image states
- int maxFrames();
- QImage assembledImage();
-private:
- QList<QQuickSprite*> m_sprites;
-};
-
-//Common use is to have your own list property which is transparently an engine
-inline void spriteAppend(QDeclarativeListProperty<QQuickSprite> *p, QQuickSprite* s)
-{
- reinterpret_cast<QList<QQuickSprite *> *>(p->data)->append(s);
- p->object->metaObject()->invokeMethod(p->object, "createEngine");
-}
-
-inline QQuickSprite* spriteAt(QDeclarativeListProperty<QQuickSprite> *p, int idx)
-{
- return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->at(idx);
-}
-
-inline void spriteClear(QDeclarativeListProperty<QQuickSprite> *p)
-{
- reinterpret_cast<QList<QQuickSprite *> *>(p->data)->clear();
- p->object->metaObject()->invokeMethod(p->object, "createEngine");
-}
-
-inline int spriteCount(QDeclarativeListProperty<QQuickSprite> *p)
-{
- return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->count();
-}
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSPRITEENGINE_P_H
diff --git a/src/declarative/items/qquickspriteimage.cpp b/src/declarative/items/qquickspriteimage.cpp
deleted file mode 100644
index a18d0f95c7..0000000000
--- a/src/declarative/items/qquickspriteimage.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 "qquickspriteimage_p.h"
-#include "qquicksprite_p.h"
-#include "qquickspriteengine_p.h"
-#include <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-#include <qsgnode.h>
-#include <qsgengine.h>
-#include <qsgtexturematerial.h>
-#include <qsgtexture.h>
-#include <qquickcanvas.h>
-#include <QFile>
-#include <cmath>
-#include <qmath.h>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-static const char vertexShaderCode[] =
- "attribute highp vec2 vTex;\n"
- "uniform highp vec4 animData;// interpolate(bool), duration, frameCount (this anim), timestamp (this anim)\n"
- "uniform highp vec4 animPos;//sheet x,y, width/height of this anim\n"
- "uniform highp vec4 animSheetSize; //width/height of whole sheet, width/height of element\n"
- "\n"
- "uniform highp mat4 qt_Matrix;\n"
- "uniform highp float timestamp;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "\n"
- "void main() {\n"
- " //Calculate frame location in texture\n"
- " highp float frameIndex = mod((((timestamp - animData.w)*1000.)/animData.y),animData.z);\n"
- " progress = mod((timestamp - animData.w)*1000., animData.y) / animData.y;\n"
- "\n"
- " frameIndex = floor(frameIndex);\n"
- " fTexS.xy = vec2(((frameIndex + vTex.x) * animPos.z / animSheetSize.x), ((animPos.y + vTex.y * animPos.w) / animSheetSize.y));\n"
- "\n"
- " //Next frame is also passed, for interpolation\n"
- " //### Should the next anim be precalculated to allow for interpolation there?\n"
- " if (animData.x == 1.0 && frameIndex != animData.z - 1.)//Can't do it for the last frame though, this anim may not loop\n"
- " frameIndex = mod(frameIndex+1., animData.z);\n"
- " fTexS.zw = vec2(((frameIndex + vTex.x) * animPos.z / animSheetSize.x), ((animPos.y + vTex.y * animPos.w) / animSheetSize.y));\n"
- "\n"
- " gl_Position = qt_Matrix * vec4(animSheetSize.z * vTex.x, animSheetSize.w * vTex.y, 0, 1);\n"
- "}\n";
-
-static const char fragmentShaderCode[] =
- "uniform sampler2D texture;\n"
- "uniform lowp float qt_Opacity;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "void main() {\n"
- " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n"
- "}\n";
-
-class QQuickSpriteMaterial : public QSGMaterial
-{
-public:
- QQuickSpriteMaterial();
- virtual ~QQuickSpriteMaterial();
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const
- {
- return this - static_cast<const QQuickSpriteMaterial *>(other);
- }
-
- QSGTexture *texture;
-
- qreal timestamp;
- float interpolate;
- float frameDuration;
- float frameCount;
- float animT;
- float animX;
- float animY;
- float animWidth;
- float animHeight;
- float sheetWidth;
- float sheetHeight;
- float elementWidth;
- float elementHeight;
-};
-
-QQuickSpriteMaterial::QQuickSpriteMaterial()
- : timestamp(0)
- , interpolate(1.0f)
- , frameDuration(1.0f)
- , frameCount(1.0f)
- , animT(0.0f)
- , animX(0.0f)
- , animY(0.0f)
- , animWidth(1.0f)
- , animHeight(1.0f)
- , sheetWidth(1.0f)
- , sheetHeight(1.0f)
- , elementWidth(1.0f)
- , elementHeight(1.0f)
-{
- setFlag(Blending, true);
-}
-
-QQuickSpriteMaterial::~QQuickSpriteMaterial()
-{
- delete texture;
-}
-
-class SpriteMaterialData : public QSGMaterialShader
-{
-public:
- SpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
- {
- }
-
- void deactivate() {
- QSGMaterialShader::deactivate();
-
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
- }
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
- {
- QQuickSpriteMaterial *m = static_cast<QQuickSpriteMaterial *>(newEffect);
- m->texture->bind();
-
- program()->setUniformValue(m_opacity_id, state.opacity());
- program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
- program()->setUniformValue(m_animData_id, m->interpolate, m->frameDuration, m->frameCount, m->animT);
- program()->setUniformValue(m_animPos_id, m->animX, m->animY, m->animWidth, m->animHeight);
- program()->setUniformValue(m_animSheetSize_id, m->sheetWidth, m->sheetHeight, m->elementWidth, m->elementHeight);
-
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
- }
-
- virtual void initialize() {
- m_matrix_id = program()->uniformLocation("qt_Matrix");
- m_opacity_id = program()->uniformLocation("qt_Opacity");
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_animData_id = program()->uniformLocation("animData");
- m_animPos_id = program()->uniformLocation("animPos");
- m_animSheetSize_id = program()->uniformLocation("animSheetSize");
- }
-
- virtual const char *vertexShader() const { return vertexShaderCode; }
- virtual const char *fragmentShader() const { return fragmentShaderCode; }
-
- virtual char const *const *attributeNames() const {
- static const char *attr[] = {
- "vTex",
- 0
- };
- return attr;
- }
-
- int m_matrix_id;
- int m_opacity_id;
- int m_timestamp_id;
- int m_animData_id;
- int m_animPos_id;
- int m_animSheetSize_id;
-
- static float chunkOfBytes[1024];
-};
-
-float SpriteMaterialData::chunkOfBytes[1024];
-
-QSGMaterialShader *QQuickSpriteMaterial::createShader() const
-{
- return new SpriteMaterialData;
-}
-
-struct SpriteVertex {
- float tx;
- float ty;
-};
-
-struct SpriteVertices {
- SpriteVertex v1;
- SpriteVertex v2;
- SpriteVertex v3;
- SpriteVertex v4;
-};
-
-/*!
- \qmlclass SpriteImage QQuickSpriteImage
- \inqmlmodule QtQuick 2
- \inherits Item
- \brief The SpriteImage element draws a sprite animation
-
-*/
-/*!
- \qmlproperty bool QtQuick2::SpriteImage::running
-
- Whether the sprite is animating or not.
-
- Default is true
-*/
-/*!
- \qmlproperty bool QtQuick2::SpriteImage::interpolate
-
- If true, interpolation will occur between sprite frames to make the
- animation appear smoother.
-
- Default is true.
-*/
-/*!
- \qmlproperty string QtQuick2::SpriteImage::goalState
-
- The name of the Sprite which the animation should move to.
-
- Sprite states have defined durations and transitions between them, setting goalState
- will cause it to disregard any path weightings (including 0) and head down the path
- which will reach the goalState quickest (fewest animations). It will pass through
- intermediate states on that path, and animate them for their duration.
-
- If it is possible to return to the goalState from the starting point of the goalState
- it will continue to do so until goalState is set to "" or an unreachable state.
-*/
-/*! \qmlmethod void QtQuick2::SpriteImage::jumpTo(string sprite)
-
- This function causes the sprite to jump to the specified state immediately, intermediate
- states are not played.
-*/
-/*!
- \qmlproperty list<Sprite> QtQuick2::SpriteImage::sprites
-
- 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?
-QQuickSpriteImage::QQuickSpriteImage(QQuickItem *parent) :
- QQuickItem(parent)
- , m_node(0)
- , m_material(0)
- , m_spriteEngine(0)
- , m_pleaseReset(false)
- , m_running(true)
- , m_interpolate(true)
-{
- setFlag(ItemHasContents);
- connect(this, SIGNAL(runningChanged(bool)),
- this, SLOT(update()));
-}
-
-void QQuickSpriteImage::jumpTo(const QString &sprite)
-{
- if (!m_spriteEngine)
- return;
- m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true);
-}
-
-void QQuickSpriteImage::setGoalState(const QString &sprite)
-{
- if (m_goalState != sprite){
- m_goalState = sprite;
- emit goalStateChanged(sprite);
- m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite));
- }
-}
-
-QDeclarativeListProperty<QQuickSprite> QQuickSpriteImage::sprites()
-{
- return QDeclarativeListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
-}
-
-void QQuickSpriteImage::createEngine()
-{
- //TODO: delay until component complete
- if (m_spriteEngine)
- delete m_spriteEngine;
- if (m_sprites.count())
- m_spriteEngine = new QQuickSpriteEngine(m_sprites, this);
- else
- m_spriteEngine = 0;
- reset();
-}
-
-static QSGGeometry::Attribute SpriteImage_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT), // tex
-};
-
-static QSGGeometry::AttributeSet SpriteImage_AttributeSet =
-{
- 1, // Attribute Count
- 2 * sizeof(float),
- SpriteImage_Attributes
-};
-
-QSGGeometryNode* QQuickSpriteImage::buildNode()
-{
- if (!m_spriteEngine) {
- qWarning() << "SpriteImage: No sprite engine...";
- return 0;
- }
-
- m_material = new QQuickSpriteMaterial();
-
- QImage image = m_spriteEngine->assembledImage();
- if (image.isNull())
- return 0;
- m_material->texture = canvas()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
- m_spriteEngine->start(0);
- m_material->interpolate = m_interpolate ? 1.0 : 0.0;
- m_material->frameCount = m_spriteEngine->spriteFrames();
- m_material->frameDuration = m_spriteEngine->spriteDuration();
- m_material->animT = 0;
- m_material->animX = m_spriteEngine->spriteX();
- m_material->animY = m_spriteEngine->spriteY();
- m_material->animWidth = m_spriteEngine->spriteWidth();
- m_material->animHeight = m_spriteEngine->spriteHeight();
- m_material->sheetWidth = image.width();
- m_material->sheetHeight = image.height();
- m_material->elementWidth = width();
- m_material->elementHeight = height();
-
- int vCount = 4;
- int iCount = 6;
- QSGGeometry *g = new QSGGeometry(SpriteImage_AttributeSet, vCount, iCount);
- g->setDrawingMode(GL_TRIANGLES);
-
- SpriteVertices *p = (SpriteVertices *) g->vertexData();
-
- p->v1.tx = 0;
- p->v1.ty = 0;
-
- p->v2.tx = 1.0;
- p->v2.ty = 0;
-
- p->v3.tx = 0;
- p->v3.ty = 1.0;
-
- p->v4.tx = 1.0;
- p->v4.ty = 1.0;
-
- quint16 *indices = g->indexDataAsUShort();
- indices[0] = 0;
- indices[1] = 1;
- indices[2] = 2;
- indices[3] = 1;
- indices[4] = 3;
- indices[5] = 2;
-
-
- m_timestamp.start();
- m_node = new QSGGeometryNode();
- m_node->setGeometry(g);
- m_node->setMaterial(m_material);
- m_node->setFlag(QSGGeometryNode::OwnsMaterial);
- return m_node;
-}
-
-void QQuickSpriteImage::reset()
-{
- m_pleaseReset = true;
-}
-
-QSGNode *QQuickSpriteImage::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
-{
- if (m_pleaseReset) {
- delete m_node;
- delete m_material;
-
- m_node = 0;
- m_material = 0;
- m_pleaseReset = false;
- }
-
- prepareNextFrame();
-
- if (m_running) {
- update();
- if (m_node)
- m_node->markDirty(QSGNode::DirtyMaterial);
- }
-
- return m_node;
-}
-
-void QQuickSpriteImage::prepareNextFrame()
-{
- if (m_node == 0)
- m_node = buildNode();
- if (m_node == 0) //error creating node
- return;
-
- uint timeInt = m_timestamp.elapsed();
- qreal time = timeInt / 1000.;
- m_material->timestamp = time;
- m_material->elementHeight = height();
- m_material->elementWidth = width();
- m_material->interpolate = m_interpolate;
-
- //Advance State
- m_spriteEngine->updateSprites(timeInt);
- int curY = m_spriteEngine->spriteY();
- if (curY != m_material->animY){
- m_material->animT = m_spriteEngine->spriteStart()/1000.0;
- m_material->frameCount = m_spriteEngine->spriteFrames();
- m_material->frameDuration = m_spriteEngine->spriteDuration();
- m_material->animX = m_spriteEngine->spriteX();
- m_material->animY = m_spriteEngine->spriteY();
- m_material->animWidth = m_spriteEngine->spriteWidth();
- m_material->animHeight = m_spriteEngine->spriteHeight();
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickspriteimage_p.h b/src/declarative/items/qquickspriteimage_p.h
deleted file mode 100644
index 39384cedca..0000000000
--- a/src/declarative/items/qquickspriteimage_p.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQUICKSPRITEIMAGE_P_H
-#define QQUICKSPRITEIMAGE_P_H
-
-#include <QQuickItem>
-#include <QTime>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGContext;
-class QQuickSprite;
-class QQuickSpriteEngine;
-class QSGGeometryNode;
-class QQuickSpriteMaterial;
-class Q_AUTOTEST_EXPORT QQuickSpriteImage : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged)
- Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
- //###try to share similar spriteEngines for less overhead?
- Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
- Q_CLASSINFO("DefaultProperty", "sprites")
-
-public:
- explicit QQuickSpriteImage(QQuickItem *parent = 0);
-
- QDeclarativeListProperty<QQuickSprite> sprites();
-
- bool running() const
- {
- return m_running;
- }
-
- bool interpolate() const
- {
- return m_interpolate;
- }
-
- QString goalState() const
- {
- return m_goalState;
- }
-
-signals:
-
- void runningChanged(bool arg);
- void interpolateChanged(bool arg);
- void goalStateChanged(QString arg);
-
-public slots:
-
- void jumpTo(const QString &sprite);
- void setGoalState(const QString &sprite);
-
- void setRunning(bool arg)
- {
- if (m_running != arg) {
- m_running = arg;
- emit runningChanged(arg);
- }
- }
-
- void setInterpolate(bool arg)
- {
- if (m_interpolate != arg) {
- m_interpolate = arg;
- emit interpolateChanged(arg);
- }
- }
-
-private slots:
- void createEngine();
-protected:
- void reset();
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-private:
- void prepareNextFrame();
- QSGGeometryNode* buildNode();
- QSGGeometryNode *m_node;
- QQuickSpriteMaterial *m_material;
- QList<QQuickSprite*> m_sprites;
- QQuickSpriteEngine* m_spriteEngine;
- QTime m_timestamp;
- int m_maxFrames;
- bool m_pleaseReset;
- bool m_running;
- bool m_interpolate;
- QString m_goalState;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKSPRITEIMAGE_P_H
diff --git a/src/declarative/items/qquickstateoperations_p.h b/src/declarative/items/qquickstateoperations_p.h
deleted file mode 100644
index 7844c6d7dd..0000000000
--- a/src/declarative/items/qquickstateoperations_p.h
+++ /dev/null
@@ -1,275 +0,0 @@
-// Commit: 84c47bbb133304d7ef35642fa1fbb17619d4a43d
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKSTATEOPERATIONS_P_H
-#define QQUICKSTATEOPERATIONS_P_H
-
-#include "qquickitem.h"
-#include "qquickanchors_p.h"
-
-#include <private/qdeclarativestate_p.h>
-
-#include <QtDeclarative/qdeclarativescriptstring.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParentChangePrivate;
-class Q_AUTOTEST_EXPORT QQuickParentChange : public QDeclarativeStateOperation, public QDeclarativeActionEvent
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickParentChange)
-
- Q_PROPERTY(QQuickItem *target READ object WRITE setObject)
- Q_PROPERTY(QQuickItem *parent READ parent WRITE setParent)
- Q_PROPERTY(QDeclarativeScriptString x READ x WRITE setX)
- Q_PROPERTY(QDeclarativeScriptString y READ y WRITE setY)
- Q_PROPERTY(QDeclarativeScriptString width READ width WRITE setWidth)
- Q_PROPERTY(QDeclarativeScriptString height READ height WRITE setHeight)
- Q_PROPERTY(QDeclarativeScriptString scale READ scale WRITE setScale)
- Q_PROPERTY(QDeclarativeScriptString rotation READ rotation WRITE setRotation)
-public:
- QQuickParentChange(QObject *parent=0);
- ~QQuickParentChange();
-
- QQuickItem *object() const;
- void setObject(QQuickItem *);
-
- QQuickItem *parent() const;
- void setParent(QQuickItem *);
-
- QQuickItem *originalParent() const;
-
- QDeclarativeScriptString x() const;
- void setX(QDeclarativeScriptString x);
- bool xIsSet() const;
-
- QDeclarativeScriptString y() const;
- void setY(QDeclarativeScriptString y);
- bool yIsSet() const;
-
- QDeclarativeScriptString width() const;
- void setWidth(QDeclarativeScriptString width);
- bool widthIsSet() const;
-
- QDeclarativeScriptString height() const;
- void setHeight(QDeclarativeScriptString height);
- bool heightIsSet() const;
-
- QDeclarativeScriptString scale() const;
- void setScale(QDeclarativeScriptString scale);
- bool scaleIsSet() const;
-
- QDeclarativeScriptString rotation() const;
- void setRotation(QDeclarativeScriptString rotation);
- bool rotationIsSet() const;
-
- virtual ActionList actions();
-
- virtual void saveOriginals();
- //virtual void copyOriginals(QDeclarativeActionEvent*);
- virtual void execute(Reason reason = ActualChange);
- virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
- virtual QString typeName() const;
- virtual bool override(QDeclarativeActionEvent*other);
- virtual void rewind();
- virtual void saveCurrentValues();
-};
-
-class QQuickAnchorChanges;
-class QQuickAnchorSetPrivate;
-class Q_AUTOTEST_EXPORT QQuickAnchorSet : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QDeclarativeScriptString left READ left WRITE setLeft RESET resetLeft)
- Q_PROPERTY(QDeclarativeScriptString right READ right WRITE setRight RESET resetRight)
- Q_PROPERTY(QDeclarativeScriptString horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter)
- Q_PROPERTY(QDeclarativeScriptString top READ top WRITE setTop RESET resetTop)
- Q_PROPERTY(QDeclarativeScriptString bottom READ bottom WRITE setBottom RESET resetBottom)
- Q_PROPERTY(QDeclarativeScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
- Q_PROPERTY(QDeclarativeScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline)
- //Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill)
- //Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn)
-
- /*Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
- Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
- Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
- Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
- Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
- Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
- Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
- Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())*/
-
-public:
- QQuickAnchorSet(QObject *parent=0);
- virtual ~QQuickAnchorSet();
-
- QDeclarativeScriptString left() const;
- void setLeft(const QDeclarativeScriptString &edge);
- void resetLeft();
-
- QDeclarativeScriptString right() const;
- void setRight(const QDeclarativeScriptString &edge);
- void resetRight();
-
- QDeclarativeScriptString horizontalCenter() const;
- void setHorizontalCenter(const QDeclarativeScriptString &edge);
- void resetHorizontalCenter();
-
- QDeclarativeScriptString top() const;
- void setTop(const QDeclarativeScriptString &edge);
- void resetTop();
-
- QDeclarativeScriptString bottom() const;
- void setBottom(const QDeclarativeScriptString &edge);
- void resetBottom();
-
- QDeclarativeScriptString verticalCenter() const;
- void setVerticalCenter(const QDeclarativeScriptString &edge);
- void resetVerticalCenter();
-
- QDeclarativeScriptString baseline() const;
- void setBaseline(const QDeclarativeScriptString &edge);
- void resetBaseline();
-
- QQuickItem *fill() const;
- void setFill(QQuickItem *);
- void resetFill();
-
- QQuickItem *centerIn() const;
- void setCenterIn(QQuickItem *);
- void resetCenterIn();
-
- /*qreal leftMargin() const;
- void setLeftMargin(qreal);
-
- qreal rightMargin() const;
- void setRightMargin(qreal);
-
- qreal horizontalCenterOffset() const;
- void setHorizontalCenterOffset(qreal);
-
- qreal topMargin() const;
- void setTopMargin(qreal);
-
- qreal bottomMargin() const;
- void setBottomMargin(qreal);
-
- qreal margins() const;
- void setMargins(qreal);
-
- qreal verticalCenterOffset() const;
- void setVerticalCenterOffset(qreal);
-
- qreal baselineOffset() const;
- void setBaselineOffset(qreal);*/
-
- QQuickAnchors::Anchors usedAnchors() const;
-
-/*Q_SIGNALS:
- void leftMarginChanged();
- void rightMarginChanged();
- void topMarginChanged();
- void bottomMarginChanged();
- void marginsChanged();
- void verticalCenterOffsetChanged();
- void horizontalCenterOffsetChanged();
- void baselineOffsetChanged();*/
-
-private:
- friend class QQuickAnchorChanges;
- Q_DISABLE_COPY(QQuickAnchorSet)
- Q_DECLARE_PRIVATE(QQuickAnchorSet)
-};
-
-class QQuickAnchorChangesPrivate;
-class Q_AUTOTEST_EXPORT QQuickAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickAnchorChanges)
-
- Q_PROPERTY(QQuickItem *target READ object WRITE setObject)
- Q_PROPERTY(QQuickAnchorSet *anchors READ anchors CONSTANT)
-
-public:
- QQuickAnchorChanges(QObject *parent=0);
- ~QQuickAnchorChanges();
-
- virtual ActionList actions();
-
- QQuickAnchorSet *anchors();
-
- QQuickItem *object() const;
- void setObject(QQuickItem *);
-
- virtual void execute(Reason reason = ActualChange);
- virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
- virtual QString typeName() const;
- virtual bool override(QDeclarativeActionEvent*other);
- virtual bool changesBindings();
- virtual void saveOriginals();
- virtual bool needsCopy() { return true; }
- virtual void copyOriginals(QDeclarativeActionEvent*);
- virtual void clearBindings();
- virtual void rewind();
- virtual void saveCurrentValues();
-
- QList<QDeclarativeAction> additionalActions();
- virtual void saveTargetValues();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickParentChange)
-QML_DECLARE_TYPE(QQuickAnchorSet)
-QML_DECLARE_TYPE(QQuickAnchorChanges)
-
-QT_END_HEADER
-
-#endif // QQUICKSTATEOPERATIONS_P_H
-
diff --git a/src/declarative/items/qquicktext.cpp b/src/declarative/items/qquicktext.cpp
deleted file mode 100644
index 630b466d80..0000000000
--- a/src/declarative/items/qquicktext.cpp
+++ /dev/null
@@ -1,1950 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquicktext_p.h"
-#include "qquicktext_p_p.h"
-
-#include <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-#include "qquicktextnode_p.h"
-#include "qquickimage_p_p.h"
-#include <private/qsgtexture_p.h>
-
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qabstracttextdocumentlayout.h>
-#include <QtGui/qpainter.h>
-#include <QtGui/qtextdocument.h>
-#include <QtGui/qtextobject.h>
-#include <QtGui/qtextcursor.h>
-#include <QtGui/qguiapplication.h>
-
-#include <private/qdeclarativestyledtext_p.h>
-#include <private/qdeclarativepixmapcache_p.h>
-
-#include <qmath.h>
-#include <limits.h>
-
-QT_BEGIN_NAMESPACE
-
-extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
-
-class QQuickTextDocumentWithImageResources : public QTextDocument {
- Q_OBJECT
-
-public:
- QQuickTextDocumentWithImageResources(QQuickText *parent);
- virtual ~QQuickTextDocumentWithImageResources();
-
- void setText(const QString &);
- int resourcesLoading() const { return outstanding; }
-
-protected:
- QVariant loadResource(int type, const QUrl &name);
-
-private slots:
- void requestFinished();
-
-private:
- QHash<QUrl, QDeclarativePixmap *> m_resources;
-
- int outstanding;
- static QSet<QUrl> errors;
-};
-
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
-
-QString QQuickTextPrivate::elideChar = QString(0x2026);
-
-QQuickTextPrivate::QQuickTextPrivate()
-: color((QRgb)0), style(QQuickText::Normal), hAlign(QQuickText::AlignLeft),
- vAlign(QQuickText::AlignTop), elideMode(QQuickText::ElideNone),
- format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap), lineHeight(1),
- lineHeightMode(QQuickText::ProportionalHeight), lineCount(1), maximumLineCount(INT_MAX),
- maximumLineCountValid(false),
- texture(0),
- imageCacheDirty(false), updateOnComponentComplete(true),
- richText(false), styledText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false),
- requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
- layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), textHasChanged(true),
- naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull)
-
-#if defined(Q_OS_MAC)
-, layoutThread(0), paintingThread(0)
-#endif
-
-{
- cacheAllTextAsImage = enableImageCache();
-}
-
-void QQuickTextPrivate::init()
-{
- Q_Q(QQuickText);
- q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setFlag(QQuickItem::ItemHasContents);
-}
-
-QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickText *parent)
-: QTextDocument(parent), outstanding(0)
-{
- setUndoRedoEnabled(false);
-}
-
-QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
-{
- if (!m_resources.isEmpty())
- qDeleteAll(m_resources);
-}
-
-QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
-{
- QDeclarativeContext *context = qmlContext(parent());
- QUrl url = context->resolvedUrl(name);
-
- if (type == QTextDocument::ImageResource) {
- QHash<QUrl, QDeclarativePixmap *>::Iterator iter = m_resources.find(url);
-
- if (iter == m_resources.end()) {
- QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url);
- iter = m_resources.insert(url, p);
-
- if (p->isLoading()) {
- p->connectFinished(this, SLOT(requestFinished()));
- outstanding++;
- }
- }
-
- QDeclarativePixmap *p = *iter;
- if (p->isReady()) {
- return p->image();
- } else if (p->isError()) {
- if (!errors.contains(url)) {
- errors.insert(url);
- qmlInfo(parent()) << p->error();
- }
- }
- }
-
- return QTextDocument::loadResource(type,url); // The *resolved* URL
-}
-
-void QQuickTextDocumentWithImageResources::requestFinished()
-{
- outstanding--;
- if (outstanding == 0) {
- QQuickText *textItem = static_cast<QQuickText*>(parent());
- QString text = textItem->text();
-#ifndef QT_NO_TEXTHTMLPARSER
- setHtml(text);
-#else
- setPlainText(text);
-#endif
- QQuickTextPrivate *d = QQuickTextPrivate::get(textItem);
- d->updateLayout();
- }
-}
-
-void QQuickTextDocumentWithImageResources::setText(const QString &text)
-{
- if (!m_resources.isEmpty()) {
- qDeleteAll(m_resources);
- m_resources.clear();
- outstanding = 0;
- }
-
-#ifndef QT_NO_TEXTHTMLPARSER
- setHtml(text);
-#else
- setPlainText(text);
-#endif
-}
-
-QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
-
-QQuickTextPrivate::~QQuickTextPrivate()
-{
- delete elipsisLayout;
- delete textLine; textLine = 0;
-}
-
-qreal QQuickTextPrivate::getImplicitWidth() const
-{
- if (!requireImplicitWidth) {
- // We don't calculate implicitWidth unless it is required.
- // We need to force a size update now to ensure implicitWidth is calculated
- QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
- me->requireImplicitWidth = true;
- me->updateSize();
- }
- return implicitWidth;
-}
-
-void QQuickTextPrivate::updateLayout()
-{
- Q_Q(QQuickText);
- if (!q->isComponentComplete()) {
- updateOnComponentComplete = true;
- return;
- }
- updateOnComponentComplete = false;
- layoutTextElided = false;
- // Setup instance of QTextLayout for all cases other than richtext
- if (!richText) {
- if (elipsisLayout) {
- delete elipsisLayout;
- elipsisLayout = 0;
- }
- layout.clearLayout();
- layout.setFont(font);
- if (!styledText) {
- QString tmp = text;
- tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
- singleline = !tmp.contains(QChar::LineSeparator);
- if (singleline && !maximumLineCountValid && elideMode != QQuickText::ElideNone && q->widthValid() && wrapMode == QQuickText::NoWrap) {
- QFontMetrics fm(font);
- tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
- if (tmp != text) {
- layoutTextElided = true;
- if (!truncated) {
- truncated = true;
- emit q->truncatedChanged();
- }
- }
- }
- layout.setText(tmp);
- } else {
- singleline = false;
- if (textHasChanged) {
- QDeclarativeStyledText::parse(text, layout);
- textHasChanged = false;
- }
- }
- } else {
- ensureDoc();
- QTextBlockFormat::LineHeightTypes type;
- type = lineHeightMode == QQuickText::FixedHeight ? QTextBlockFormat::FixedHeight : QTextBlockFormat::ProportionalHeight;
- QTextBlockFormat blockFormat;
- blockFormat.setLineHeight((lineHeightMode == QQuickText::FixedHeight ? lineHeight : lineHeight * 100), type);
- for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) {
- QTextCursor cursor(it);
- cursor.mergeBlockFormat(blockFormat);
- }
- }
-
- updateSize();
-}
-
-void QQuickTextPrivate::updateSize()
-{
- Q_Q(QQuickText);
-
- if (!q->isComponentComplete()) {
- updateOnComponentComplete = true;
- return;
- }
-
- if (!requireImplicitWidth) {
- emit q->implicitWidthChanged();
- // if the implicitWidth is used, then updateSize() has already been called (recursively)
- if (requireImplicitWidth)
- return;
- }
-
- invalidateImageCache();
-
- QFontMetrics fm(font);
- if (text.isEmpty()) {
- q->setImplicitSize(0, fm.height());
- paintedSize = QSize(0, fm.height());
- emit q->paintedSizeChanged();
- q->update();
- return;
- }
-
- int dy = q->height();
- QSize size(0, 0);
-
-#if defined(Q_OS_MAC)
- layoutThread = QThread::currentThread();
-#endif
-
- //setup instance of QTextLayout for all cases other than richtext
- if (!richText) {
- QRect textRect = setupTextLayout();
- layedOutTextRect = textRect;
- size = textRect.size();
- dy -= size.height();
- } else {
- singleline = false; // richtext can't elide or be optimized for single-line case
- ensureDoc();
- doc->setDefaultFont(font);
- QQuickText::HAlignment horizontalAlignment = q->effectiveHAlign();
- if (rightToLeftText) {
- if (horizontalAlignment == QQuickText::AlignLeft)
- horizontalAlignment = QQuickText::AlignRight;
- else if (horizontalAlignment == QQuickText::AlignRight)
- horizontalAlignment = QQuickText::AlignLeft;
- }
- QTextOption option;
- option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
- option.setWrapMode(QTextOption::WrapMode(wrapMode));
- if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
- option.setUseDesignMetrics(true);
- doc->setDefaultTextOption(option);
- if (requireImplicitWidth && q->widthValid()) {
- doc->setTextWidth(-1);
- naturalWidth = doc->idealWidth();
- }
- if (wrapMode != QQuickText::NoWrap && q->widthValid())
- doc->setTextWidth(q->width());
- else
- doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
- dy -= (int)doc->size().height();
- QSize dsize = doc->size().toSize();
- layedOutTextRect = QRect(QPoint(0,0), dsize);
- size = QSize(int(doc->idealWidth()),dsize.height());
- }
- int yoff = 0;
-
- if (q->heightValid()) {
- if (vAlign == QQuickText::AlignBottom)
- yoff = dy;
- else if (vAlign == QQuickText::AlignVCenter)
- yoff = dy/2;
- }
- q->setBaselineOffset(fm.ascent() + yoff);
-
- //### need to comfirm cost of always setting these for richText
- internalWidthUpdate = true;
- qreal iWidth = -1;
- if (!q->widthValid())
- iWidth = size.width();
- else if (requireImplicitWidth)
- iWidth = naturalWidth;
- if (iWidth > -1)
- q->setImplicitSize(iWidth, size.height());
- internalWidthUpdate = false;
-
- if (iWidth == -1)
- q->setImplicitHeight(size.height());
- if (paintedSize != size) {
- paintedSize = size;
- emit q->paintedSizeChanged();
- }
- q->update();
-}
-
-QQuickTextLine::QQuickTextLine()
- : QObject(), m_line(0), m_height(0)
-{
-}
-
-void QQuickTextLine::setLine(QTextLine *line)
-{
- m_line = line;
-}
-
-int QQuickTextLine::number() const
-{
- if (m_line)
- return m_line->lineNumber();
- return 0;
-}
-
-qreal QQuickTextLine::width() const
-{
- if (m_line)
- return m_line->width();
- return 0;
-}
-
-void QQuickTextLine::setWidth(qreal width)
-{
- if (m_line)
- m_line->setLineWidth(width);
-}
-
-qreal QQuickTextLine::height() const
-{
- if (m_height)
- return m_height;
- if (m_line)
- return m_line->height();
- return 0;
-}
-
-void QQuickTextLine::setHeight(qreal height)
-{
- if (m_line)
- m_line->setPosition(QPointF(m_line->x(), m_line->y() - m_line->height() + height));
- m_height = height;
-}
-
-qreal QQuickTextLine::x() const
-{
- if (m_line)
- return m_line->x();
- return 0;
-}
-
-void QQuickTextLine::setX(qreal x)
-{
- if (m_line)
- m_line->setPosition(QPointF(x, m_line->y()));
-}
-
-qreal QQuickTextLine::y() const
-{
- if (m_line)
- return m_line->y();
- return 0;
-}
-
-void QQuickTextLine::setY(qreal y)
-{
- if (m_line)
- m_line->setPosition(QPointF(m_line->x(), y));
-}
-
-void QQuickText::doLayout()
-{
- Q_D(QQuickText);
- d->updateSize();
-}
-
-bool QQuickTextPrivate::isLineLaidOutConnected()
-{
- static int idx = this->signalIndex("lineLaidOut(QQuickTextLine*)");
- return this->isSignalConnected(idx);
-}
-
-void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, qreal elideWidth = 0)
-{
- Q_Q(QQuickText);
-
-#if defined(Q_OS_MAC)
- if (QThread::currentThread() != paintingThread) {
-#endif
- if (!line.lineNumber())
- linesRects.clear();
-
- if (!textLine)
- textLine = new QQuickTextLine;
- textLine->setLine(&line);
- textLine->setY(height);
- textLine->setHeight(0);
-
- // use the text item's width by default if it has one and wrap is on
- if (q->widthValid() && q->wrapMode() != QQuickText::NoWrap)
- textLine->setWidth(q->width() - elideWidth);
- else
- textLine->setWidth(INT_MAX);
- if (lineHeight != 1.0)
- textLine->setHeight((lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight);
-
- emit q->lineLaidOut(textLine);
-
- linesRects << QRectF(textLine->x(), textLine->y(), textLine->width(), textLine->height());
- height += textLine->height();
-
-#if defined(Q_OS_MAC)
- } else {
- if (line.lineNumber() < linesRects.count()) {
- QRectF r = linesRects.at(line.lineNumber());
- line.setLineWidth(r.width());
- line.setPosition(r.topLeft());
- }
- }
-#endif
-}
-
-/*!
- Lays out the QQuickTextPrivate::layout QTextLayout in the constraints of the QQuickText.
-
- Returns the size of the final text. This can be used to position the text vertically (the text is
- already absolutely positioned horizontally).
-*/
-QRect QQuickTextPrivate::setupTextLayout()
-{
- // ### text layout handling should be profiled and optimized as needed
- // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
- Q_Q(QQuickText);
- layout.setCacheEnabled(true);
-
- qreal lineWidth = 0;
- int visibleCount = 0;
-
- //set manual width
- if (q->widthValid())
- lineWidth = q->width();
-
- QTextOption textOption = layout.textOption();
- textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
- textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
- if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
- textOption.setUseDesignMetrics(true);
- layout.setTextOption(textOption);
-
- QFontMetrics fm(layout.font());
- elidePos = QPointF();
-
- if (requireImplicitWidth && q->widthValid()) {
- // requires an extra layout
- QString elidedText;
- if (layoutTextElided) {
- // We have provided elided text to the layout, but we must calculate unelided width.
- elidedText = layout.text();
- layout.setText(text);
- }
- layout.beginLayout();
- forever {
- QTextLine line = layout.createLine();
- if (!line.isValid())
- break;
- }
- layout.endLayout();
- QRectF br;
- for (int i = 0; i < layout.lineCount(); ++i) {
- QTextLine line = layout.lineAt(i);
- br = br.united(line.naturalTextRect());
- }
- naturalWidth = br.width();
- if (layoutTextElided)
- layout.setText(elidedText);
- }
-
- qreal height = 0;
- QRectF br;
-
- bool truncate = false;
- bool customLayout = isLineLaidOutConnected();
- bool elideEnabled = elideMode == QQuickText::ElideRight && q->widthValid();
-
- layout.beginLayout();
- if (!lineWidth)
- lineWidth = INT_MAX;
- int linesLeft = maximumLineCount;
- int visibleTextLength = 0;
- forever {
- QTextLine line = layout.createLine();
- if (!line.isValid())
- break;
-
- visibleCount++;
-
- qreal preLayoutHeight = height;
- if (customLayout) {
- setupCustomLineGeometry(line, height);
- } else if (lineWidth) {
- line.setLineWidth(lineWidth);
- line.setPosition(QPointF(line.position().x(), height));
- height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight;
- }
-
- bool elide = false;
- if (elideEnabled && q->heightValid() && height > q->height()) {
- // This line does not fit in the remaining area.
- elide = true;
- if (visibleCount > 1) {
- --visibleCount;
- height = preLayoutHeight;
- line.setLineWidth(0.0);
- line.setPosition(QPointF(FLT_MAX,FLT_MAX));
- line = layout.lineAt(visibleCount-1);
- }
- } else {
- visibleTextLength += line.textLength();
- }
-
- if (elide || (maximumLineCountValid && --linesLeft == 0)) {
- if (visibleTextLength < text.length()) {
- truncate = true;
- if (elideEnabled) {
- qreal elideWidth = fm.width(elideChar);
- // Need to correct for alignment
- if (customLayout)
- setupCustomLineGeometry(line, height, elideWidth);
- else
- line.setLineWidth(lineWidth - elideWidth);
- if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
- line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
- elidePos.setX(line.naturalTextRect().left() - elideWidth);
- } else {
- elidePos.setX(line.naturalTextRect().right());
- }
- elidePos.setY(line.position().y());
- if (!elipsisLayout)
- elipsisLayout = new QTextLayout(elideChar, layout.font());
- elipsisLayout->beginLayout();
- QTextLine el = elipsisLayout->createLine();
- el.setPosition(elidePos);
- elipsisLayout->endLayout();
- br = br.united(el.naturalTextRect());
- }
- br = br.united(line.naturalTextRect());
- break;
- }
- }
- br = br.united(line.naturalTextRect());
- }
- layout.endLayout();
-
- //Update truncated
- if (truncated != truncate) {
- truncated = truncate;
- emit q->truncatedChanged();
- }
-
- if (!customLayout)
- br.setHeight(height);
-
- if (!q->widthValid())
- naturalWidth = br.width();
-
- //Update the number of visible lines
- if (lineCount != visibleCount) {
- lineCount = visibleCount;
- emit q->lineCountChanged();
- }
-
- return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
-}
-
-/*!
- Returns a painted version of the QQuickTextPrivate::layout QTextLayout.
- If \a drawStyle is true, the style color overrides all colors in the document.
-*/
-QPixmap QQuickTextPrivate::textLayoutImage(bool drawStyle)
-{
- QSize size = layedOutTextRect.size();
-
- //paint text
- QPixmap img(size);
- if (!size.isEmpty()) {
- img.fill(Qt::transparent);
-/*#ifdef Q_OS_MAC // Fails on CocoaX64
- bool oldSmooth = qt_applefontsmoothing_enabled;
- qt_applefontsmoothing_enabled = false;
-#endif*/
- QPainter p(&img);
-/*#ifdef Q_OS_MAC // Fails on CocoaX64
- qt_applefontsmoothing_enabled = oldSmooth;
-#endif*/
- drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle);
- }
- return img;
-}
-
-/*!
- Paints the QQuickTextPrivate::layout QTextLayout into \a painter at \a pos. If
- \a drawStyle is true, the style color overrides all colors in the document.
-*/
-void QQuickTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
-{
- if (drawStyle)
- painter->setPen(styleColor);
- else
- painter->setPen(color);
- painter->setFont(font);
- layout.draw(painter, pos);
- if (!elidePos.isNull())
- painter->drawText(pos + elidePos, elideChar);
-}
-
-/*!
- Returns a painted version of the QQuickTextPrivate::doc QTextDocument.
- If \a drawStyle is true, the style color overrides all colors in the document.
-*/
-QPixmap QQuickTextPrivate::textDocumentImage(bool drawStyle)
-{
- QSize size = doc->size().toSize();
-
- //paint text
- QPixmap img(size);
- img.fill(Qt::transparent);
-/*#ifdef Q_OS_MAC // Fails on CocoaX64
- bool oldSmooth = qt_applefontsmoothing_enabled;
- qt_applefontsmoothing_enabled = false;
-#endif*/
- QPainter p(&img);
-/*#ifdef Q_OS_MAC // Fails on CocoaX64
- qt_applefontsmoothing_enabled = oldSmooth;
-#endif*/
-
- QAbstractTextDocumentLayout::PaintContext context;
-
- QTextOption oldOption(doc->defaultTextOption());
- if (drawStyle) {
- context.palette.setColor(QPalette::Text, styleColor);
- QTextOption colorOption(doc->defaultTextOption());
- colorOption.setFlags(QTextOption::SuppressColors);
- doc->setDefaultTextOption(colorOption);
- } else {
- context.palette.setColor(QPalette::Text, color);
- }
- doc->documentLayout()->draw(&p, context);
- if (drawStyle)
- doc->setDefaultTextOption(oldOption);
- return img;
-}
-
-/*!
- Mark the image cache as dirty.
-*/
-void QQuickTextPrivate::invalidateImageCache()
-{
- Q_Q(QQuickText);
-
- if (richTextAsImage || cacheAllTextAsImage || (qmlDisableDistanceField() && style != QQuickText::Normal)) { // If actually using the image cache
- if (imageCacheDirty)
- return;
-
- imageCacheDirty = true;
-
- if (q->isComponentComplete())
- QCoreApplication::postEvent(q, new QEvent(QEvent::User));
- } else if (q->isComponentComplete())
- q->update();
-}
-
-/*!
- Tests if the image cache is dirty, and repaints it if it is.
-*/
-void QQuickTextPrivate::checkImageCache()
-{
- Q_Q(QQuickText);
-
- if (!imageCacheDirty)
- return;
-
- if (text.isEmpty()) {
-
- imageCache = QPixmap();
-
- } else {
-
- QPixmap textImage;
- QPixmap styledImage;
-
- if (richText) {
- textImage = textDocumentImage(false);
- if (style != QQuickText::Normal)
- styledImage = textDocumentImage(true); //### should use styleColor
- } else {
- textImage = textLayoutImage(false);
- if (style != QQuickText::Normal)
- styledImage = textLayoutImage(true); //### should use styleColor
- }
-
- switch (style) {
- case QQuickText::Outline:
- imageCache = drawOutline(textImage, styledImage);
- break;
- case QQuickText::Sunken:
- imageCache = drawOutline(textImage, styledImage, -1);
- break;
- case QQuickText::Raised:
- imageCache = drawOutline(textImage, styledImage, 1);
- break;
- default:
- imageCache = textImage;
- break;
- }
-
- }
-
- imageCacheDirty = false;
- textureImageCacheDirty = true;
- q->update();
-}
-
-/*!
- Ensures the QQuickTextPrivate::doc variable is set to a valid text document
-*/
-void QQuickTextPrivate::ensureDoc()
-{
- if (!doc) {
- Q_Q(QQuickText);
- doc = new QQuickTextDocumentWithImageResources(q);
- doc->setDocumentMargin(0);
- }
-}
-
-/*!
- Draw \a styleSource as an outline around \a source and return the new image.
-*/
-QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource)
-{
- QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
- img.fill(Qt::transparent);
-
- QPainter ppm(&img);
-
- QPoint pos(0, 0);
- pos += QPoint(-1, 0);
- ppm.drawPixmap(pos, styleSource);
- pos += QPoint(2, 0);
- ppm.drawPixmap(pos, styleSource);
- pos += QPoint(-1, -1);
- ppm.drawPixmap(pos, styleSource);
- pos += QPoint(0, 2);
- ppm.drawPixmap(pos, styleSource);
-
- pos += QPoint(0, -1);
- ppm.drawPixmap(pos, source);
- ppm.end();
-
- return img;
-}
-
-/*!
- Draw \a styleSource below \a source at \a yOffset and return the new image.
-*/
-QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
-{
- QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
- img.fill(Qt::transparent);
-
- QPainter ppm(&img);
-
- ppm.drawPixmap(QPoint(0, yOffset), styleSource);
- ppm.drawPixmap(0, 0, source);
-
- ppm.end();
-
- return img;
-}
-
-/*!
- \qmlclass Text QQuickText
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The Text item allows you to add formatted text to a scene.
- \inherits Item
-
- Text items can display both plain and rich text. For example, red text with
- a specific font and size can be defined like this:
-
- \qml
- Text {
- text: "Hello World!"
- font.family: "Helvetica"
- font.pointSize: 24
- color: "red"
- }
- \endqml
-
- Rich text is defined using HTML-style markup:
-
- \qml
- Text {
- text: "<b>Hello</b> <i>World!</i>"
- }
- \endqml
-
- \image declarative-text.png
-
- If height and width are not explicitly set, Text will attempt to determine how
- much room is needed and set it accordingly. Unless \l wrapMode is set, it will always
- prefer width to height (all text will be placed on a single line).
-
- The \l elide property can alternatively be used to fit a single line of
- plain text to a set width.
-
- Note that the \l{Supported HTML Subset} is limited. Also, if the text contains
- HTML img tags that load remote images, the text is reloaded.
-
- Text provides read-only text. For editable text, see \l TextEdit.
-
- \sa {declarative/text/fonts}{Fonts example}
-*/
-QQuickText::QQuickText(QQuickItem *parent)
-: QQuickImplicitSizeItem(*(new QQuickTextPrivate), parent)
-{
- Q_D(QQuickText);
- d->init();
-}
-
-QQuickText::~QQuickText()
-{
-}
-
-/*!
- \qmlproperty bool QtQuick2::Text::clip
- This property holds whether the text is clipped.
-
- Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
-
- If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Text::smooth
-
- This property holds whether the text is smoothly scaled or transformed.
-
- Smooth filtering gives better visual quality, but is slower. If
- the item is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the item is stationary on
- the screen. A common pattern when animating an item is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-*/
-
-/*!
- \qmlsignal QtQuick2::Text::onLineLaidOut(line)
-
- This handler is called for every line during the layout process.
- This gives the opportunity to position and resize a line as it is being laid out.
- It can for example be used to create columns or lay out text around objects.
-
- The properties of a line are:
- \list
- \o number (read-only)
- \o x
- \o y
- \o width
- \o height
- \endlist
-
- For example, this will move the first 5 lines of a text element by 100 pixels to the right:
- \code
- onLineLaidOut: {
- if (line.number < 5) {
- line.x = line.x + 100
- line.width = line.width - 100
- }
- }
- \endcode
-*/
-
-/*!
- \qmlsignal QtQuick2::Text::onLinkActivated(string link)
-
- This handler is called when the user clicks on a link embedded in the text.
- The link must be in rich text or HTML format and the
- \a link string provides access to the particular link.
-
- \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
-
- The example code will display the text
- "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
-
- Clicking on the highlighted link will output
- \tt{http://qt.nokia.com link activated} to the console.
-*/
-
-/*!
- \qmlproperty string QtQuick2::Text::font.family
-
- Sets the family name of the font.
-
- The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
- If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
- If the family isn't available a family will be set using the font matching algorithm.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Text::font.bold
-
- Sets whether the font weight is bold.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::font.weight
-
- Sets the font's weight.
-
- The weight can be one of:
- \list
- \o Font.Light
- \o Font.Normal - the default
- \o Font.DemiBold
- \o Font.Bold
- \o Font.Black
- \endlist
-
- \qml
- Text { text: "Hello"; font.weight: Font.DemiBold }
- \endqml
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Text::font.italic
-
- Sets whether the font has an italic style.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Text::font.underline
-
- Sets whether the text is underlined.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::Text::font.strikeout
-
- Sets whether the font has a strikeout style.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Text::font.pointSize
-
- Sets the font size in points. The point size must be greater than zero.
-*/
-
-/*!
- \qmlproperty int QtQuick2::Text::font.pixelSize
-
- Sets the font size in pixels.
-
- Using this function makes the font device dependent.
- Use \c pointSize to set the size of the font in a device independent manner.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Text::font.letterSpacing
-
- Sets the letter spacing for the font.
-
- Letter spacing changes the default spacing between individual letters in the font.
- A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
-*/
-
-/*!
- \qmlproperty real QtQuick2::Text::font.wordSpacing
-
- Sets the word spacing for the font.
-
- Word spacing changes the default spacing between individual words.
- A positive value increases the word spacing by a corresponding amount of pixels,
- while a negative value decreases the inter-word spacing accordingly.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::font.capitalization
-
- Sets the capitalization for the text.
-
- \list
- \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
- \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
- \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
- \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
- \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
- \endlist
-
- \qml
- Text { text: "Hello"; font.capitalization: Font.AllLowercase }
- \endqml
-*/
-QFont QQuickText::font() const
-{
- Q_D(const QQuickText);
- return d->sourceFont;
-}
-
-void QQuickText::setFont(const QFont &font)
-{
- Q_D(QQuickText);
- if (d->sourceFont == font)
- return;
-
- d->sourceFont = font;
- QFont oldFont = d->font;
- d->font = font;
-
- if (d->font.pointSizeF() != -1) {
- // 0.5pt resolution
- qreal size = qRound(d->font.pointSizeF()*2.0);
- d->font.setPointSizeF(size/2.0);
- }
-
- if (oldFont != d->font)
- d->updateLayout();
-
- emit fontChanged(d->sourceFont);
-}
-
-/*!
- \qmlproperty string QtQuick2::Text::text
-
- The text to display. Text supports both plain and rich text strings.
-
- The item will try to automatically determine whether the text should
- be treated as styled text. This determination is made using Qt::mightBeRichText().
-*/
-QString QQuickText::text() const
-{
- Q_D(const QQuickText);
- return d->text;
-}
-
-void QQuickText::setText(const QString &n)
-{
- Q_D(QQuickText);
- if (d->text == n)
- return;
-
- d->richText = d->format == RichText;
- d->styledText = d->format == StyledText || (d->format == AutoText && Qt::mightBeRichText(n));
- d->text = n;
- if (isComponentComplete()) {
- if (d->richText) {
- d->ensureDoc();
- d->doc->setText(n);
- d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
- d->richTextAsImage = enableImageCache();
- } else {
- d->rightToLeftText = d->text.isRightToLeft();
- }
- d->determineHorizontalAlignment();
- }
- d->textHasChanged = true;
- d->updateLayout();
- emit textChanged(d->text);
-}
-
-/*!
- \qmlproperty color QtQuick2::Text::color
-
- The text color.
-
- An example of green text defined using hexadecimal notation:
- \qml
- Text {
- color: "#00FF00"
- text: "green text"
- }
- \endqml
-
- An example of steel blue text defined using an SVG color name:
- \qml
- Text {
- color: "steelblue"
- text: "blue text"
- }
- \endqml
-*/
-QColor QQuickText::color() const
-{
- Q_D(const QQuickText);
- return d->color;
-}
-
-void QQuickText::setColor(const QColor &color)
-{
- Q_D(QQuickText);
- if (d->color == color)
- return;
-
- d->color = color;
- d->invalidateImageCache();
- emit colorChanged(d->color);
-}
-/*!
- \qmlproperty enumeration QtQuick2::Text::style
-
- Set an additional text style.
-
- Supported text styles are:
- \list
- \o Text.Normal - the default
- \o Text.Outline
- \o Text.Raised
- \o Text.Sunken
- \endlist
-
- \qml
- Row {
- Text { font.pointSize: 24; text: "Normal" }
- Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
- Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" }
- Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
- }
- \endqml
-
- \image declarative-textstyle.png
-*/
-QQuickText::TextStyle QQuickText::style() const
-{
- Q_D(const QQuickText);
- return d->style;
-}
-
-void QQuickText::setStyle(QQuickText::TextStyle style)
-{
- Q_D(QQuickText);
- if (d->style == style)
- return;
-
- // changing to/from Normal requires the boundingRect() to change
- if (isComponentComplete() && (d->style == Normal || style == Normal))
- update();
- d->style = style;
- d->invalidateImageCache();
- emit styleChanged(d->style);
-}
-
-/*!
- \qmlproperty color QtQuick2::Text::styleColor
-
- Defines the secondary color used by text styles.
-
- \c styleColor is used as the outline color for outlined text, and as the
- shadow color for raised or sunken text. If no style has been set, it is not
- used at all.
-
- \qml
- Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" }
- \endqml
-
- \sa style
- */
-QColor QQuickText::styleColor() const
-{
- Q_D(const QQuickText);
- return d->styleColor;
-}
-
-void QQuickText::setStyleColor(const QColor &color)
-{
- Q_D(QQuickText);
- if (d->styleColor == color)
- return;
-
- d->styleColor = color;
- d->invalidateImageCache();
- emit styleColorChanged(d->styleColor);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::horizontalAlignment
- \qmlproperty enumeration QtQuick2::Text::verticalAlignment
- \qmlproperty enumeration QtQuick2::Text::effectiveHorizontalAlignment
-
- Sets the horizontal and vertical alignment of the text within the Text items
- width and height. By default, the text is vertically aligned to the top. Horizontal
- alignment follows the natural alignment of the text, for example text that is read
- from left to right will be aligned to the left.
-
- The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and
- \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom
- and \c Text.AlignVCenter.
-
- Note that for a single line of text, the size of the text is the area of the text. In this common case,
- all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will
- need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to
- that of the parent.
-
- When using the attached property LayoutMirroring::enabled to mirror application
- layouts, the horizontal alignment of text will also be mirrored. However, the property
- \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
- of Text, use the read-only property \c effectiveHorizontalAlignment.
-*/
-QQuickText::HAlignment QQuickText::hAlign() const
-{
- Q_D(const QQuickText);
- return d->hAlign;
-}
-
-void QQuickText::setHAlign(HAlignment align)
-{
- Q_D(QQuickText);
- bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
- d->hAlignImplicit = false;
- if (d->setHAlign(align, forceAlign) && isComponentComplete())
- d->updateLayout();
-}
-
-void QQuickText::resetHAlign()
-{
- Q_D(QQuickText);
- d->hAlignImplicit = true;
- if (isComponentComplete() && d->determineHorizontalAlignment())
- d->updateLayout();
-}
-
-QQuickText::HAlignment QQuickText::effectiveHAlign() const
-{
- Q_D(const QQuickText);
- QQuickText::HAlignment effectiveAlignment = d->hAlign;
- if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
- switch (d->hAlign) {
- case QQuickText::AlignLeft:
- effectiveAlignment = QQuickText::AlignRight;
- break;
- case QQuickText::AlignRight:
- effectiveAlignment = QQuickText::AlignLeft;
- break;
- default:
- break;
- }
- }
- return effectiveAlignment;
-}
-
-bool QQuickTextPrivate::setHAlign(QQuickText::HAlignment alignment, bool forceAlign)
-{
- Q_Q(QQuickText);
- if (hAlign != alignment || forceAlign) {
- QQuickText::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
- hAlign = alignment;
-
- emit q->horizontalAlignmentChanged(hAlign);
- if (oldEffectiveHAlign != q->effectiveHAlign())
- emit q->effectiveHorizontalAlignmentChanged();
- return true;
- }
- return false;
-}
-
-bool QQuickTextPrivate::determineHorizontalAlignment()
-{
- if (hAlignImplicit) {
- bool alignToRight = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
- return setHAlign(alignToRight ? QQuickText::AlignRight : QQuickText::AlignLeft);
- }
- return false;
-}
-
-void QQuickTextPrivate::mirrorChange()
-{
- Q_Q(QQuickText);
- if (q->isComponentComplete()) {
- if (!hAlignImplicit && (hAlign == QQuickText::AlignRight || hAlign == QQuickText::AlignLeft)) {
- updateLayout();
- emit q->effectiveHorizontalAlignmentChanged();
- }
- }
-}
-
-QTextDocument *QQuickTextPrivate::textDocument()
-{
- return doc;
-}
-
-QQuickText::VAlignment QQuickText::vAlign() const
-{
- Q_D(const QQuickText);
- return d->vAlign;
-}
-
-void QQuickText::setVAlign(VAlignment align)
-{
- Q_D(QQuickText);
- if (d->vAlign == align)
- return;
-
- d->vAlign = align;
- emit verticalAlignmentChanged(align);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::wrapMode
-
- Set this property to wrap the text to the Text item's width. The text will only
- wrap if an explicit width has been set. wrapMode can be one of:
-
- \list
- \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width.
- \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width.
- \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
- \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
- \endlist
-*/
-QQuickText::WrapMode QQuickText::wrapMode() const
-{
- Q_D(const QQuickText);
- return d->wrapMode;
-}
-
-void QQuickText::setWrapMode(WrapMode mode)
-{
- Q_D(QQuickText);
- if (mode == d->wrapMode)
- return;
-
- d->wrapMode = mode;
- d->updateLayout();
-
- emit wrapModeChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::Text::lineCount
-
- Returns the number of lines visible in the text item.
-
- This property is not supported for rich text.
-
- \sa maximumLineCount
-*/
-int QQuickText::lineCount() const
-{
- Q_D(const QQuickText);
- return d->lineCount;
-}
-
-/*!
- \qmlproperty bool QtQuick2::Text::truncated
-
- Returns true if the text has been truncated due to \l maximumLineCount
- or \l elide.
-
- This property is not supported for rich text.
-
- \sa maximumLineCount, elide
-*/
-bool QQuickText::truncated() const
-{
- Q_D(const QQuickText);
- return d->truncated;
-}
-
-/*!
- \qmlproperty int QtQuick2::Text::maximumLineCount
-
- Set this property to limit the number of lines that the text item will show.
- If elide is set to Text.ElideRight, the text will be elided appropriately.
- By default, this is the value of the largest possible integer.
-
- This property is not supported for rich text.
-
- \sa lineCount, elide
-*/
-int QQuickText::maximumLineCount() const
-{
- Q_D(const QQuickText);
- return d->maximumLineCount;
-}
-
-void QQuickText::setMaximumLineCount(int lines)
-{
- Q_D(QQuickText);
-
- d->maximumLineCountValid = lines==INT_MAX ? false : true;
- if (d->maximumLineCount != lines) {
- d->maximumLineCount = lines;
- d->updateLayout();
- emit maximumLineCountChanged();
- }
-}
-
-void QQuickText::resetMaximumLineCount()
-{
- Q_D(QQuickText);
- setMaximumLineCount(INT_MAX);
- d->elidePos = QPointF();
- if (d->truncated != false) {
- d->truncated = false;
- emit truncatedChanged();
- }
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::textFormat
-
- The way the text property should be displayed.
-
- Supported text formats are:
-
- \list
- \o Text.AutoText (default)
- \o Text.PlainText
- \o Text.StyledText
- \o Text.RichText
- \endlist
-
- If the text format is \c Text.AutoText the text element
- will automatically determine whether the text should be treated as
- styled text. This determination is made using Qt::mightBeRichText().
-
- Text.StyledText is an optimized format supporting some basic text
- styling markup, in the style of html 3.2:
-
- \code
- <b></b> - bold
- <i></i> - italic
- <br> - new line
- <p> - paragraph
- <u> - underlined text
- <font color="color_name" size="1-7"></font>
- <h1> to <h6> - headers
- <a href=""> - anchor
- <ol type="">, <ul type=""> and <li> - ordered and unordered lists
- &gt; &lt; &amp;
- \endcode
-
- \c Text.StyledText parser is strict, requiring tags to be correctly nested.
-
- \table
- \row
- \o
- \qml
-Column {
- Text {
- font.pointSize: 24
- text: "<b>Hello</b> <i>World!</i>"
- }
- Text {
- font.pointSize: 24
- textFormat: Text.RichText
- text: "<b>Hello</b> <i>World!</i>"
- }
- Text {
- font.pointSize: 24
- textFormat: Text.PlainText
- text: "<b>Hello</b> <i>World!</i>"
- }
-}
- \endqml
- \o \image declarative-textformat.png
- \endtable
-*/
-QQuickText::TextFormat QQuickText::textFormat() const
-{
- Q_D(const QQuickText);
- return d->format;
-}
-
-void QQuickText::setTextFormat(TextFormat format)
-{
- Q_D(QQuickText);
- if (format == d->format)
- return;
- d->format = format;
- bool wasRich = d->richText;
- d->richText = format == RichText;
- d->styledText = format == StyledText || (format == AutoText && Qt::mightBeRichText(d->text));
-
- if (isComponentComplete()) {
- if (!wasRich && d->richText) {
- d->ensureDoc();
- d->doc->setText(d->text);
- d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
- d->richTextAsImage = enableImageCache();
- } else {
- d->rightToLeftText = d->text.isRightToLeft();
- }
- d->determineHorizontalAlignment();
- }
- d->updateLayout();
-
- emit textFormatChanged(d->format);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::elide
-
- Set this property to elide parts of the text fit to the Text item's width.
- The text will only elide if an explicit width has been set.
-
- This property cannot be used with rich text.
-
- Eliding can be:
- \list
- \o Text.ElideNone - the default
- \o Text.ElideLeft
- \o Text.ElideMiddle
- \o Text.ElideRight
- \endlist
-
- If this property is set to Text.ElideRight, it can be used with multiline
- text. The text will only elide if \c maximumLineCount, or \c height has been set.
- If both \c maximumLineCount and \c height are set, \c maximumLineCount will
- apply unless the lines do not fit in the height allowed.
-
- If the text is a multi-length string, and the mode is not \c Text.ElideNone,
- the first string that fits will be used, otherwise the last will be elided.
-
- Multi-length strings are ordered from longest to shortest, separated by the
- Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
-*/
-QQuickText::TextElideMode QQuickText::elideMode() const
-{
- Q_D(const QQuickText);
- return d->elideMode;
-}
-
-void QQuickText::setElideMode(QQuickText::TextElideMode mode)
-{
- Q_D(QQuickText);
- if (mode == d->elideMode)
- return;
-
- d->elideMode = mode;
- d->updateLayout();
-
- emit elideModeChanged(d->elideMode);
-}
-
-/*! \internal */
-QRectF QQuickText::boundingRect() const
-{
- Q_D(const QQuickText);
-
- QRect rect = d->layedOutTextRect;
- if (d->style != Normal)
- rect.adjust(-1, 0, 1, 2);
-
- // Could include font max left/right bearings to either side of rectangle.
-
- int h = height();
- switch (d->vAlign) {
- case AlignTop:
- break;
- case AlignBottom:
- rect.moveTop(h - rect.height());
- break;
- case AlignVCenter:
- rect.moveTop((h - rect.height()) / 2);
- break;
- }
-
- return QRectF(rect);
-}
-
-/*! \internal */
-void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_D(QQuickText);
- bool elide = d->elideMode != QQuickText::ElideNone && widthValid();
- if ((!d->internalWidthUpdate
- && (newGeometry.width() != oldGeometry.width() || (elide && newGeometry.height() != oldGeometry.height())))
- && (d->wrapMode != QQuickText::NoWrap
- || d->elideMode != QQuickText::ElideNone
- || d->hAlign != QQuickText::AlignLeft)) {
- if ((d->singleline || d->maximumLineCountValid || heightValid()) && elide) {
- // We need to re-elide
- d->updateLayout();
- } else {
- // We just need to re-layout
- d->updateSize();
- }
- }
-
- QQuickItem::geometryChanged(newGeometry, oldGeometry);
-}
-
-QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
-{
- Q_UNUSED(data);
- Q_D(QQuickText);
-
- if (d->text.isEmpty()) {
- delete oldNode;
- return 0;
- }
-
- QRectF bounds = boundingRect();
-
- // We need to make sure the layout is done in the current thread
-#if defined(Q_OS_MAC)
- d->paintingThread = QThread::currentThread();
- if (d->layoutThread != d->paintingThread)
- d->updateLayout();
-#endif
-
- // XXX todo - some styled text can be done by the QQuickTextNode
- if (d->richTextAsImage || d->cacheAllTextAsImage || (qmlDisableDistanceField() && d->style != Normal)) {
- bool wasDirty = d->textureImageCacheDirty;
- d->textureImageCacheDirty = false;
-
- if (d->imageCache.isNull()) {
- delete oldNode;
- return 0;
- }
-
- QSGImageNode *node = 0;
- if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsTexture) {
- delete oldNode;
- node = QQuickItemPrivate::get(this)->sceneGraphContext()->createImageNode();
- d->texture = new QSGPlainTexture();
- wasDirty = true;
- d->nodeType = QQuickTextPrivate::NodeIsTexture;
- } else {
- node = static_cast<QSGImageNode *>(oldNode);
- Q_ASSERT(d->texture);
- }
-
- if (wasDirty) {
- qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->imageCache.toImage());
- node->setTexture(0);
- node->setTexture(d->texture);
- }
-
- node->setTargetRect(QRectF(bounds.x(), bounds.y(), d->imageCache.width(), d->imageCache.height()));
- node->setSourceRect(QRectF(0, 0, 1, 1));
- node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- node->setVerticalWrapMode(QSGTexture::ClampToEdge);
- node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that..
- node->update();
-
- return node;
-
- } else {
- QQuickTextNode *node = 0;
- if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsText) {
- delete oldNode;
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
- d->nodeType = QQuickTextPrivate::NodeIsText;
- } else {
- node = static_cast<QQuickTextNode *>(oldNode);
- }
-
- node->deleteContent();
- node->setMatrix(QMatrix4x4());
-
- if (d->richText) {
- d->ensureDoc();
- node->addTextDocument(bounds.topLeft(), d->doc, d->color, d->style, d->styleColor);
-
- } else {
- node->addTextLayout(QPoint(0, bounds.y()), &d->layout, d->color, d->style, d->styleColor);
- if (d->elipsisLayout)
- node->addTextLayout(QPoint(0, bounds.y()), d->elipsisLayout, d->color, d->style, d->styleColor);
- }
-
- return node;
- }
-}
-
-bool QQuickText::event(QEvent *e)
-{
- Q_D(QQuickText);
- if (e->type() == QEvent::User) {
- d->checkImageCache();
- return true;
- } else {
- return QQuickImplicitSizeItem::event(e);
- }
-}
-
-/*!
- \qmlproperty real QtQuick2::Text::paintedWidth
-
- Returns the width of the text, including width past the width
- which is covered due to insufficient wrapping if WrapMode is set.
-*/
-qreal QQuickText::paintedWidth() const
-{
- Q_D(const QQuickText);
- return d->paintedSize.width();
-}
-
-/*!
- \qmlproperty real QtQuick2::Text::paintedHeight
-
- Returns the height of the text, including height past the height
- which is covered due to there being more text than fits in the set height.
-*/
-qreal QQuickText::paintedHeight() const
-{
- Q_D(const QQuickText);
- return d->paintedSize.height();
-}
-
-/*!
- \qmlproperty real QtQuick2::Text::lineHeight
-
- Sets the line height for the text.
- The value can be in pixels or a multiplier depending on lineHeightMode.
-
- The default value is a multiplier of 1.0.
- The line height must be a positive value.
-*/
-qreal QQuickText::lineHeight() const
-{
- Q_D(const QQuickText);
- return d->lineHeight;
-}
-
-void QQuickText::setLineHeight(qreal lineHeight)
-{
- Q_D(QQuickText);
-
- if ((d->lineHeight == lineHeight) || (lineHeight < 0.0))
- return;
-
- d->lineHeight = lineHeight;
- d->updateLayout();
- emit lineHeightChanged(lineHeight);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::Text::lineHeightMode
-
- This property determines how the line height is specified.
- The possible values are:
-
- \list
- \o Text.ProportionalHeight (default) - this sets the spacing proportional to the
- line (as a multiplier). For example, set to 2 for double spacing.
- \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels).
- \endlist
-*/
-QQuickText::LineHeightMode QQuickText::lineHeightMode() const
-{
- Q_D(const QQuickText);
- return d->lineHeightMode;
-}
-
-void QQuickText::setLineHeightMode(LineHeightMode mode)
-{
- Q_D(QQuickText);
- if (mode == d->lineHeightMode)
- return;
-
- d->lineHeightMode = mode;
- d->updateLayout();
-
- emit lineHeightModeChanged(mode);
-}
-
-/*!
- Returns the number of resources (images) that are being loaded asynchronously.
-*/
-int QQuickText::resourcesLoading() const
-{
- Q_D(const QQuickText);
- return d->doc ? d->doc->resourcesLoading() : 0;
-}
-
-/*! \internal */
-void QQuickText::componentComplete()
-{
- Q_D(QQuickText);
- if (d->updateOnComponentComplete) {
- if (d->richText) {
- d->ensureDoc();
- d->doc->setText(d->text);
- d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
- d->richTextAsImage = enableImageCache();
- } else {
- d->rightToLeftText = d->text.isRightToLeft();
- }
- d->determineHorizontalAlignment();
- }
- QQuickItem::componentComplete();
- if (d->updateOnComponentComplete)
- d->updateLayout();
-}
-
-
-QString QQuickTextPrivate::anchorAt(const QPointF &mousePos)
-{
- if (styledText) {
- for (int i = 0; i < layout.lineCount(); ++i) {
- QTextLine line = layout.lineAt(i);
- if (line.naturalTextRect().contains(mousePos)) {
- int charPos = line.xToCursor(mousePos.x());
- foreach (const QTextLayout::FormatRange &formatRange, layout.additionalFormats()) {
- if (formatRange.format.isAnchor()
- && charPos >= formatRange.start
- && charPos <= formatRange.start + formatRange.length) {
- return formatRange.format.anchorHref();
- }
- }
- break;
- }
- }
- }
- return QString();
-}
-
-bool QQuickTextPrivate::isLinkActivatedConnected()
-{
- static int idx = this->signalIndex("linkActivated(QString)");
- return this->isSignalConnected(idx);
-}
-
-/*! \internal */
-void QQuickText::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickText);
-
- if (d->isLinkActivatedConnected()) {
- if (d->styledText)
- d->activeLink = d->anchorAt(event->localPos());
- else if (d->richText && d->doc)
- d->activeLink = d->doc->documentLayout()->anchorAt(event->localPos());
- }
-
- if (d->activeLink.isEmpty())
- event->setAccepted(false);
-
- // ### may malfunction if two of the same links are clicked & dragged onto each other)
-
- if (!event->isAccepted())
- QQuickItem::mousePressEvent(event);
-
-}
-
-/*! \internal */
-void QQuickText::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickText);
-
- // ### confirm the link, and send a signal out
-
- QString link;
- if (d->isLinkActivatedConnected()) {
- if (d->styledText)
- link = d->anchorAt(event->localPos());
- else if (d->richText && d->doc)
- link = d->doc->documentLayout()->anchorAt(event->localPos());
- }
-
- if (!link.isEmpty() && d->activeLink == link)
- emit linkActivated(d->activeLink);
- else
- event->setAccepted(false);
-
- if (!event->isAccepted())
- QQuickItem::mouseReleaseEvent(event);
-}
-
-QT_END_NAMESPACE
-
-#include "qquicktext.moc"
diff --git a/src/declarative/items/qquicktext_p.h b/src/declarative/items/qquicktext_p.h
deleted file mode 100644
index be77f2eb45..0000000000
--- a/src/declarative/items/qquicktext_p.h
+++ /dev/null
@@ -1,252 +0,0 @@
-// Commit: 27e4302b7f45f22180693d26747f419177c81e27
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKTEXT_P_H
-#define QQUICKTEXT_P_H
-
-#include "qquickimplicitsizeitem_p.h"
-
-#include <private/qdeclarativeglobal_p.h>
-
-#include <QtGui/qtextoption.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class QQuickTextPrivate;
-class QQuickTextLine;
-class Q_DECLARATIVE_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
-{
- Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
- Q_ENUMS(TextStyle)
- Q_ENUMS(TextFormat)
- Q_ENUMS(TextElideMode)
- Q_ENUMS(WrapMode)
- Q_ENUMS(LineHeightMode)
-
- Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
- Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(TextStyle style READ style WRITE setStyle NOTIFY styleChanged)
- Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor NOTIFY styleColorChanged)
- Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
- Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
- Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
- Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
- Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
- Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged)
- Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount)
-
- Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
- Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode?
- Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
- Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
- Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged)
- Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged)
-
-public:
- QQuickText(QQuickItem *parent=0);
- ~QQuickText();
-
- enum HAlignment { AlignLeft = Qt::AlignLeft,
- AlignRight = Qt::AlignRight,
- AlignHCenter = Qt::AlignHCenter,
- AlignJustify = Qt::AlignJustify };
- enum VAlignment { AlignTop = Qt::AlignTop,
- AlignBottom = Qt::AlignBottom,
- AlignVCenter = Qt::AlignVCenter };
- enum TextStyle { Normal,
- Outline,
- Raised,
- Sunken };
- enum TextFormat { PlainText = Qt::PlainText,
- RichText = Qt::RichText,
- AutoText = Qt::AutoText,
- StyledText = 4 };
- enum TextElideMode { ElideLeft = Qt::ElideLeft,
- ElideRight = Qt::ElideRight,
- ElideMiddle = Qt::ElideMiddle,
- ElideNone = Qt::ElideNone };
-
- enum WrapMode { NoWrap = QTextOption::NoWrap,
- WordWrap = QTextOption::WordWrap,
- WrapAnywhere = QTextOption::WrapAnywhere,
- WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
- Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
- };
-
- enum LineHeightMode { ProportionalHeight, FixedHeight };
-
- QString text() const;
- void setText(const QString &);
-
- QFont font() const;
- void setFont(const QFont &font);
-
- QColor color() const;
- void setColor(const QColor &c);
-
- TextStyle style() const;
- void setStyle(TextStyle style);
-
- QColor styleColor() const;
- void setStyleColor(const QColor &c);
-
- HAlignment hAlign() const;
- void setHAlign(HAlignment align);
- void resetHAlign();
- HAlignment effectiveHAlign() const;
-
- VAlignment vAlign() const;
- void setVAlign(VAlignment align);
-
- WrapMode wrapMode() const;
- void setWrapMode(WrapMode w);
-
- int lineCount() const;
- bool truncated() const;
-
- int maximumLineCount() const;
- void setMaximumLineCount(int lines);
- void resetMaximumLineCount();
-
- TextFormat textFormat() const;
- void setTextFormat(TextFormat format);
-
- TextElideMode elideMode() const;
- void setElideMode(TextElideMode);
-
- qreal lineHeight() const;
- void setLineHeight(qreal lineHeight);
-
- LineHeightMode lineHeightMode() const;
- void setLineHeightMode(LineHeightMode);
-
- virtual void componentComplete();
-
- int resourcesLoading() const; // mainly for testing
-
- qreal paintedWidth() const;
- qreal paintedHeight() const;
-
- QRectF boundingRect() const;
- Q_INVOKABLE void doLayout();
-
-Q_SIGNALS:
- void textChanged(const QString &text);
- void linkActivated(const QString &link);
- void fontChanged(const QFont &font);
- void colorChanged(const QColor &color);
- void styleChanged(TextStyle style);
- void styleColorChanged(const QColor &color);
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
- void wrapModeChanged();
- void lineCountChanged();
- void truncatedChanged();
- void maximumLineCountChanged();
- void textFormatChanged(TextFormat textFormat);
- void elideModeChanged(TextElideMode mode);
- void paintedSizeChanged();
- void lineHeightChanged(qreal lineHeight);
- void lineHeightModeChanged(LineHeightMode mode);
- void effectiveHorizontalAlignmentChanged();
- void lineLaidOut(QQuickTextLine *line);
-
-protected:
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual bool event(QEvent *);
-
-private:
- Q_DISABLE_COPY(QQuickText)
- Q_DECLARE_PRIVATE(QQuickText)
-};
-
-class QTextLine;
-class Q_AUTOTEST_EXPORT QQuickTextLine : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int number READ number)
- Q_PROPERTY(qreal width READ width WRITE setWidth)
- Q_PROPERTY(qreal height READ height WRITE setHeight)
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
-
-public:
- QQuickTextLine();
-
- void setLine(QTextLine* line);
- int number() const;
-
- qreal width() const;
- void setWidth(qreal width);
-
- qreal height() const;
- void setHeight(qreal height);
-
- qreal x() const;
- void setX(qreal x);
-
- qreal y() const;
- void setY(qreal y);
-
-private:
- QTextLine *m_line;
- qreal m_height;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickText)
-QML_DECLARE_TYPE(QQuickTextLine)
-
-QT_END_HEADER
-
-#endif // QQUICKTEXT_P_H
diff --git a/src/declarative/items/qquicktextedit.cpp b/src/declarative/items/qquicktextedit.cpp
deleted file mode 100644
index b40b5c09a1..0000000000
--- a/src/declarative/items/qquicktextedit.cpp
+++ /dev/null
@@ -1,2091 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquicktextedit_p.h"
-#include "qquicktextedit_p_p.h"
-#include "qquickevents_p_p.h"
-#include "qquickcanvas.h"
-#include "qquicktextnode_p.h"
-#include "qsgsimplerectnode.h"
-
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qpainter.h>
-#include <QtGui/qtextobject.h>
-#include <QtCore/qmath.h>
-
-#include <private/qdeclarativeglobal_p.h>
-#include <private/qtextcontrol_p.h>
-#include <private/qtextengine_p.h>
-#include <private/qsgtexture_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-DEFINE_BOOL_CONFIG_OPTION(qmlEnableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE)
-
-/*!
- \qmlclass TextEdit QQuickTextEdit
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The TextEdit item displays multiple lines of editable formatted text.
- \inherits Item
-
- The TextEdit item displays a block of editable, formatted text.
-
- It can display both plain and rich text. For example:
-
- \qml
-TextEdit {
- width: 240
- text: "<b>Hello</b> <i>World!</i>"
- font.family: "Helvetica"
- font.pointSize: 20
- color: "blue"
- focus: true
-}
- \endqml
-
- \image declarative-textedit.gif
-
- Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
-
- Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
- to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
-
- \snippet snippets/declarative/texteditor.qml 0
-
- A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
- scrollbar, or a scrollbar that fades in to show location, etc.
-
- Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
- be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
- from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
-
- You can translate between cursor positions (characters from the start of the document) and pixel
- points using positionAt() and positionToRectangle().
-
- \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
-*/
-
-/*!
- \qmlsignal QtQuick2::TextEdit::onLinkActivated(string link)
-
- This handler is called when the user clicks on a link embedded in the text.
- The link must be in rich text or HTML format and the
- \a link string provides access to the particular link.
-*/
-QQuickTextEdit::QQuickTextEdit(QQuickItem *parent)
-: QQuickImplicitSizeItem(*(new QQuickTextEditPrivate), parent)
-{
- Q_D(QQuickTextEdit);
- d->init();
-}
-
-QString QQuickTextEdit::text() const
-{
- Q_D(const QQuickTextEdit);
-
-#ifndef QT_NO_TEXTHTMLPARSER
- if (d->richText)
- return d->document->toHtml();
- else
-#endif
- return d->document->toPlainText();
-}
-
-/*!
- \qmlproperty string QtQuick2::TextEdit::font.family
-
- Sets the family name of the font.
-
- The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
- If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
- If the family isn't available a family will be set using the font matching algorithm.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::font.bold
-
- Sets whether the font weight is bold.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::TextEdit::font.weight
-
- Sets the font's weight.
-
- The weight can be one of:
- \list
- \o Font.Light
- \o Font.Normal - the default
- \o Font.DemiBold
- \o Font.Bold
- \o Font.Black
- \endlist
-
- \qml
- TextEdit { text: "Hello"; font.weight: Font.DemiBold }
- \endqml
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::font.italic
-
- Sets whether the font has an italic style.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::font.underline
-
- Sets whether the text is underlined.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::font.strikeout
-
- Sets whether the font has a strikeout style.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextEdit::font.pointSize
-
- Sets the font size in points. The point size must be greater than zero.
-*/
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::font.pixelSize
-
- Sets the font size in pixels.
-
- Using this function makes the font device dependent. Use
- \l{TextEdit::font.pointSize} to set the size of the font in a
- device independent manner.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextEdit::font.letterSpacing
-
- Sets the letter spacing for the font.
-
- Letter spacing changes the default spacing between individual letters in the font.
- A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextEdit::font.wordSpacing
-
- Sets the word spacing for the font.
-
- Word spacing changes the default spacing between individual words.
- A positive value increases the word spacing by a corresponding amount of pixels,
- while a negative value decreases the inter-word spacing accordingly.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::TextEdit::font.capitalization
-
- Sets the capitalization for the text.
-
- \list
- \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
- \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
- \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
- \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
- \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
- \endlist
-
- \qml
- TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
- \endqml
-*/
-
-/*!
- \qmlproperty string QtQuick2::TextEdit::text
-
- The text to display. If the text format is AutoText the text edit will
- automatically determine whether the text should be treated as
- rich text. This determination is made using Qt::mightBeRichText().
-*/
-void QQuickTextEdit::setText(const QString &text)
-{
- Q_D(QQuickTextEdit);
- if (QQuickTextEdit::text() == text)
- return;
-
- d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
- if (d->richText) {
-#ifndef QT_NO_TEXTHTMLPARSER
- d->control->setHtml(text);
-#else
- d->control->setPlainText(text);
-#endif
- d->useImageFallback = qmlEnableImageCache();
- } else {
- d->control->setPlainText(text);
- }
- q_textChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::TextEdit::textFormat
-
- The way the text property should be displayed.
-
- \list
- \o TextEdit.AutoText
- \o TextEdit.PlainText
- \o TextEdit.RichText
- \endlist
-
- The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
- will automatically determine whether the text should be treated as
- rich text. This determination is made using Qt::mightBeRichText().
-
- \table
- \row
- \o
- \qml
-Column {
- TextEdit {
- font.pointSize: 24
- text: "<b>Hello</b> <i>World!</i>"
- }
- TextEdit {
- font.pointSize: 24
- textFormat: TextEdit.RichText
- text: "<b>Hello</b> <i>World!</i>"
- }
- TextEdit {
- font.pointSize: 24
- textFormat: TextEdit.PlainText
- text: "<b>Hello</b> <i>World!</i>"
- }
-}
- \endqml
- \o \image declarative-textformat.png
- \endtable
-*/
-QQuickTextEdit::TextFormat QQuickTextEdit::textFormat() const
-{
- Q_D(const QQuickTextEdit);
- return d->format;
-}
-
-void QQuickTextEdit::setTextFormat(TextFormat format)
-{
- Q_D(QQuickTextEdit);
- if (format == d->format)
- return;
- bool wasRich = d->richText;
- d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
-
- if (wasRich && !d->richText) {
- d->control->setPlainText(d->text);
- updateSize();
- } else if (!wasRich && d->richText) {
-#ifndef QT_NO_TEXTHTMLPARSER
- d->control->setHtml(d->text);
-#else
- d->control->setPlainText(d->text);
-#endif
- updateSize();
- d->useImageFallback = qmlEnableImageCache();
- }
- d->format = format;
- d->control->setAcceptRichText(d->format != PlainText);
- emit textFormatChanged(d->format);
-}
-
-QFont QQuickTextEdit::font() const
-{
- Q_D(const QQuickTextEdit);
- return d->sourceFont;
-}
-
-void QQuickTextEdit::setFont(const QFont &font)
-{
- Q_D(QQuickTextEdit);
- if (d->sourceFont == font)
- return;
-
- d->sourceFont = font;
- QFont oldFont = d->font;
- d->font = font;
- if (d->font.pointSizeF() != -1) {
- // 0.5pt resolution
- qreal size = qRound(d->font.pointSizeF()*2.0);
- d->font.setPointSizeF(size/2.0);
- }
-
- if (oldFont != d->font) {
- d->document->setDefaultFont(d->font);
- if (d->cursor) {
- d->cursor->setHeight(QFontMetrics(d->font).height());
- moveCursorDelegate();
- }
- updateSize();
- updateDocument();
- }
- emit fontChanged(d->sourceFont);
-}
-
-/*!
- \qmlproperty color QtQuick2::TextEdit::color
-
- The text color.
-
- \qml
- // green text using hexadecimal notation
- TextEdit { color: "#00FF00" }
- \endqml
-
- \qml
- // steelblue text using SVG color name
- TextEdit { color: "steelblue" }
- \endqml
-*/
-QColor QQuickTextEdit::color() const
-{
- Q_D(const QQuickTextEdit);
- return d->color;
-}
-
-void QQuickTextEdit::setColor(const QColor &color)
-{
- Q_D(QQuickTextEdit);
- if (d->color == color)
- return;
-
- d->color = color;
- QPalette pal = d->control->palette();
- pal.setColor(QPalette::Text, color);
- d->control->setPalette(pal);
- updateDocument();
- emit colorChanged(d->color);
-}
-
-/*!
- \qmlproperty color QtQuick2::TextEdit::selectionColor
-
- The text highlight color, used behind selections.
-*/
-QColor QQuickTextEdit::selectionColor() const
-{
- Q_D(const QQuickTextEdit);
- return d->selectionColor;
-}
-
-void QQuickTextEdit::setSelectionColor(const QColor &color)
-{
- Q_D(QQuickTextEdit);
- if (d->selectionColor == color)
- return;
-
- d->selectionColor = color;
- QPalette pal = d->control->palette();
- pal.setColor(QPalette::Highlight, color);
- d->control->setPalette(pal);
- updateDocument();
- emit selectionColorChanged(d->selectionColor);
-}
-
-/*!
- \qmlproperty color QtQuick2::TextEdit::selectedTextColor
-
- The selected text color, used in selections.
-*/
-QColor QQuickTextEdit::selectedTextColor() const
-{
- Q_D(const QQuickTextEdit);
- return d->selectedTextColor;
-}
-
-void QQuickTextEdit::setSelectedTextColor(const QColor &color)
-{
- Q_D(QQuickTextEdit);
- if (d->selectedTextColor == color)
- return;
-
- d->selectedTextColor = color;
- QPalette pal = d->control->palette();
- pal.setColor(QPalette::HighlightedText, color);
- d->control->setPalette(pal);
- updateDocument();
- emit selectedTextColorChanged(d->selectedTextColor);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::TextEdit::horizontalAlignment
- \qmlproperty enumeration QtQuick2::TextEdit::verticalAlignment
- \qmlproperty enumeration QtQuick2::TextEdit::effectiveHorizontalAlignment
-
- Sets the horizontal and vertical alignment of the text within the TextEdit item's
- width and height. By default, the text alignment follows the natural alignment
- of the text, for example text that is read from left to right will be aligned to
- the left.
-
- Valid values for \c horizontalAlignment are:
- \list
- \o TextEdit.AlignLeft (default)
- \o TextEdit.AlignRight
- \o TextEdit.AlignHCenter
- \o TextEdit.AlignJustify
- \endlist
-
- Valid values for \c verticalAlignment are:
- \list
- \o TextEdit.AlignTop (default)
- \o TextEdit.AlignBottom
- \o TextEdit.AlignVCenter
- \endlist
-
- When using the attached property LayoutMirroring::enabled to mirror application
- layouts, the horizontal alignment of text will also be mirrored. However, the property
- \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
- of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
-*/
-QQuickTextEdit::HAlignment QQuickTextEdit::hAlign() const
-{
- Q_D(const QQuickTextEdit);
- return d->hAlign;
-}
-
-void QQuickTextEdit::setHAlign(HAlignment align)
-{
- Q_D(QQuickTextEdit);
- bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
- d->hAlignImplicit = false;
- if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
- d->updateDefaultTextOption();
- updateSize();
- }
-}
-
-void QQuickTextEdit::resetHAlign()
-{
- Q_D(QQuickTextEdit);
- d->hAlignImplicit = true;
- if (d->determineHorizontalAlignment() && isComponentComplete()) {
- d->updateDefaultTextOption();
- updateSize();
- }
-}
-
-QQuickTextEdit::HAlignment QQuickTextEdit::effectiveHAlign() const
-{
- Q_D(const QQuickTextEdit);
- QQuickTextEdit::HAlignment effectiveAlignment = d->hAlign;
- if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
- switch (d->hAlign) {
- case QQuickTextEdit::AlignLeft:
- effectiveAlignment = QQuickTextEdit::AlignRight;
- break;
- case QQuickTextEdit::AlignRight:
- effectiveAlignment = QQuickTextEdit::AlignLeft;
- break;
- default:
- break;
- }
- }
- return effectiveAlignment;
-}
-
-bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment alignment, bool forceAlign)
-{
- Q_Q(QQuickTextEdit);
- if (hAlign != alignment || forceAlign) {
- QQuickTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
- hAlign = alignment;
- emit q->horizontalAlignmentChanged(alignment);
- if (oldEffectiveHAlign != q->effectiveHAlign())
- emit q->effectiveHorizontalAlignmentChanged();
- return true;
- }
- return false;
-}
-
-bool QQuickTextEditPrivate::determineHorizontalAlignment()
-{
- Q_Q(QQuickTextEdit);
- if (hAlignImplicit && q->isComponentComplete()) {
- bool alignToRight;
- if (text.isEmpty()) {
- const QString preeditText = control->textCursor().block().layout()->preeditAreaText();
- alignToRight = preeditText.isEmpty()
- ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft
- : preeditText.isRightToLeft();
- } else {
- alignToRight = rightToLeftText;
- }
- return setHAlign(alignToRight ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft);
- }
- return false;
-}
-
-void QQuickTextEditPrivate::mirrorChange()
-{
- Q_Q(QQuickTextEdit);
- if (q->isComponentComplete()) {
- if (!hAlignImplicit && (hAlign == QQuickTextEdit::AlignRight || hAlign == QQuickTextEdit::AlignLeft)) {
- updateDefaultTextOption();
- q->updateSize();
- emit q->effectiveHorizontalAlignmentChanged();
- }
- }
-}
-
-QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const
-{
- Q_D(const QQuickTextEdit);
- return d->vAlign;
-}
-
-void QQuickTextEdit::setVAlign(QQuickTextEdit::VAlignment alignment)
-{
- Q_D(QQuickTextEdit);
- if (alignment == d->vAlign)
- return;
- d->vAlign = alignment;
- d->updateDefaultTextOption();
- updateSize();
- moveCursorDelegate();
- emit verticalAlignmentChanged(d->vAlign);
-}
-/*!
- \qmlproperty enumeration QtQuick2::TextEdit::wrapMode
-
- Set this property to wrap the text to the TextEdit item's width.
- The text will only wrap if an explicit width has been set.
-
- \list
- \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
- \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
- \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
- \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
- \endlist
-
- The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
-*/
-QQuickTextEdit::WrapMode QQuickTextEdit::wrapMode() const
-{
- Q_D(const QQuickTextEdit);
- return d->wrapMode;
-}
-
-void QQuickTextEdit::setWrapMode(WrapMode mode)
-{
- Q_D(QQuickTextEdit);
- if (mode == d->wrapMode)
- return;
- d->wrapMode = mode;
- d->updateDefaultTextOption();
- updateSize();
- emit wrapModeChanged();
-}
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::lineCount
-
- Returns the total number of lines in the textEdit item.
-*/
-int QQuickTextEdit::lineCount() const
-{
- Q_D(const QQuickTextEdit);
- return d->lineCount;
-}
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::length
-
- Returns the total number of plain text characters in the TextEdit item.
-
- As this number doesn't include any formatting markup it may not be the same as the
- length of the string returned by the \l text property.
-
- This property can be faster than querying the length the \l text property as it doesn't
- require any copying or conversion of the TextEdit's internal string data.
-*/
-
-int QQuickTextEdit::length() const
-{
- Q_D(const QQuickTextEdit);
- // QTextDocument::characterCount() includes the terminating null character.
- return qMax(0, d->document->characterCount() - 1);
-}
-
-/*!
- \qmlproperty real QtQuick2::TextEdit::paintedWidth
-
- Returns the width of the text, including the width past the width
- which is covered due to insufficient wrapping if \l wrapMode is set.
-*/
-qreal QQuickTextEdit::paintedWidth() const
-{
- Q_D(const QQuickTextEdit);
- return d->paintedSize.width();
-}
-
-/*!
- \qmlproperty real QtQuick2::TextEdit::paintedHeight
-
- Returns the height of the text, including the height past the height
- that is covered if the text does not fit within the set height.
-*/
-qreal QQuickTextEdit::paintedHeight() const
-{
- Q_D(const QQuickTextEdit);
- return d->paintedSize.height();
-}
-
-/*!
- \qmlmethod rectangle QtQuick2::TextEdit::positionToRectangle(position)
-
- Returns the rectangle at the given \a position in the text. The x, y,
- and height properties correspond to the cursor that would describe
- that position.
-*/
-QRectF QQuickTextEdit::positionToRectangle(int pos) const
-{
- Q_D(const QQuickTextEdit);
- QTextCursor c(d->document);
- c.setPosition(pos);
- return d->control->cursorRect(c);
-
-}
-
-/*!
- \qmlmethod int QtQuick2::TextEdit::positionAt(int x, int y)
-
- Returns the text position closest to pixel position (\a x, \a y).
-
- Position 0 is before the first character, position 1 is after the first character
- but before the second, and so on until position \l {text}.length, which is after all characters.
-*/
-int QQuickTextEdit::positionAt(int x, int y) const
-{
- Q_D(const QQuickTextEdit);
- int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
- QTextCursor cursor = d->control->textCursor();
- if (r > cursor.position()) {
- // The cursor position includes positions within the preedit text, but only positions in the
- // same text block are offset so it is possible to get a position that is either part of the
- // preedit or the next text block.
- QTextLayout *layout = cursor.block().layout();
- const int preeditLength = layout
- ? layout->preeditAreaText().length()
- : 0;
- if (preeditLength > 0
- && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
- r = r > cursor.position() + preeditLength
- ? r - preeditLength
- : cursor.position();
- }
- }
- return r;
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
-
- Moves the cursor to \a position and updates the selection according to the optional \a mode
- parameter. (To only move the cursor, set the \l cursorPosition property.)
-
- When this method is called it additionally sets either the
- selectionStart or the selectionEnd (whichever was at the previous cursor position)
- to the specified position. This allows you to easily extend and contract the selected
- text range.
-
- The selection mode specifies whether the selection is updated on a per character or a per word
- basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
-
- \list
- \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
- the previous cursor position) to the specified position.
- \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
- words between the specified position and the previous cursor position. Words partially in the
- range are included.
- \endlist
-
- For example, take this sequence of calls:
-
- \code
- cursorPosition = 5
- moveCursorSelection(9, TextEdit.SelectCharacters)
- moveCursorSelection(7, TextEdit.SelectCharacters)
- \endcode
-
- This moves the cursor to position 5, extend the selection end from 5 to 9
- and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
- selected (the 6th and 7th characters).
-
- The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
- before or on position 5 and extend the selection end to a word boundary on or past position 9.
-*/
-void QQuickTextEdit::moveCursorSelection(int pos)
-{
- //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
- Q_D(QQuickTextEdit);
- QTextCursor cursor = d->control->textCursor();
- if (cursor.position() == pos)
- return;
- cursor.setPosition(pos, QTextCursor::KeepAnchor);
- d->control->setTextCursor(cursor);
-}
-
-void QQuickTextEdit::moveCursorSelection(int pos, SelectionMode mode)
-{
- Q_D(QQuickTextEdit);
- QTextCursor cursor = d->control->textCursor();
- if (cursor.position() == pos)
- return;
- if (mode == SelectCharacters) {
- cursor.setPosition(pos, QTextCursor::KeepAnchor);
- } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
- if (cursor.anchor() > cursor.position()) {
- cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
- if (cursor.position() == cursor.anchor())
- cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor);
- else
- cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
- } else {
- cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
- }
-
- cursor.setPosition(pos, QTextCursor::KeepAnchor);
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
- if (cursor.position() != pos)
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
- if (cursor.anchor() < cursor.position()) {
- cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
- } else {
- cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- if (cursor.position() != cursor.anchor()) {
- cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
- }
- }
-
- cursor.setPosition(pos, QTextCursor::KeepAnchor);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- if (cursor.position() != pos) {
- cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
- }
- }
- d->control->setTextCursor(cursor);
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::cursorVisible
- If true the text edit shows a cursor.
-
- This property is set and unset when the text edit gets active focus, but it can also
- be set directly (useful, for example, if a KeyProxy might forward keys to it).
-*/
-bool QQuickTextEdit::isCursorVisible() const
-{
- Q_D(const QQuickTextEdit);
- return d->cursorVisible;
-}
-
-void QQuickTextEdit::setCursorVisible(bool on)
-{
- Q_D(QQuickTextEdit);
- if (d->cursorVisible == on)
- return;
- d->cursorVisible = on;
- QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
- if (!on && !d->persistentSelection)
- d->control->setCursorIsFocusIndicator(true);
- d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
- emit cursorVisibleChanged(d->cursorVisible);
-}
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::cursorPosition
- The position of the cursor in the TextEdit.
-*/
-int QQuickTextEdit::cursorPosition() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->textCursor().position();
-}
-
-void QQuickTextEdit::setCursorPosition(int pos)
-{
- Q_D(QQuickTextEdit);
- if (pos < 0 || pos > d->text.length())
- return;
- QTextCursor cursor = d->control->textCursor();
- if (cursor.position() == pos && cursor.anchor() == pos)
- return;
- cursor.setPosition(pos);
- d->control->setTextCursor(cursor);
-}
-
-/*!
- \qmlproperty Component QtQuick2::TextEdit::cursorDelegate
- The delegate for the cursor in the TextEdit.
-
- If you set a cursorDelegate for a TextEdit, this delegate will be used for
- drawing the cursor instead of the standard cursor. An instance of the
- delegate will be created and managed by the text edit when a cursor is
- needed, and the x and y properties of delegate instance will be set so as
- to be one pixel before the top left of the current character.
-
- Note that the root item of the delegate component must be a QDeclarativeItem or
- QDeclarativeItem derived item.
-*/
-QDeclarativeComponent* QQuickTextEdit::cursorDelegate() const
-{
- Q_D(const QQuickTextEdit);
- return d->cursorComponent;
-}
-
-void QQuickTextEdit::setCursorDelegate(QDeclarativeComponent* c)
-{
- Q_D(QQuickTextEdit);
- if (d->cursorComponent) {
- if (d->cursor) {
- d->control->setCursorWidth(-1);
- updateCursor();
- delete d->cursor;
- d->cursor = 0;
- }
- }
- d->cursorComponent = c;
- if (c && c->isReady()) {
- loadCursorDelegate();
- } else {
- if (c)
- connect(c, SIGNAL(statusChanged()),
- this, SLOT(loadCursorDelegate()));
- }
-
- emit cursorDelegateChanged();
-}
-
-void QQuickTextEdit::loadCursorDelegate()
-{
- Q_D(QQuickTextEdit);
- if (d->cursorComponent->isLoading())
- return;
- QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
- QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
- d->cursor = qobject_cast<QQuickItem*>(object);
- if (d->cursor) {
- d->control->setCursorWidth(0);
- updateCursor();
- QDeclarative_setParent_noEvent(d->cursor, this);
- d->cursor->setParentItem(this);
- d->cursor->setHeight(QFontMetrics(d->font).height());
- moveCursorDelegate();
- }else{
- delete object;
- qmlInfo(this) << "Error loading cursor delegate.";
- }
-}
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::selectionStart
-
- The cursor position before the first character in the current selection.
-
- This property is read-only. To change the selection, use select(start,end),
- selectAll(), or selectWord().
-
- \sa selectionEnd, cursorPosition, selectedText
-*/
-int QQuickTextEdit::selectionStart() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->textCursor().selectionStart();
-}
-
-/*!
- \qmlproperty int QtQuick2::TextEdit::selectionEnd
-
- The cursor position after the last character in the current selection.
-
- This property is read-only. To change the selection, use select(start,end),
- selectAll(), or selectWord().
-
- \sa selectionStart, cursorPosition, selectedText
-*/
-int QQuickTextEdit::selectionEnd() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->textCursor().selectionEnd();
-}
-
-/*!
- \qmlproperty string QtQuick2::TextEdit::selectedText
-
- This read-only property provides the text currently selected in the
- text edit.
-
- It is equivalent to the following snippet, but is faster and easier
- to use.
- \code
- //myTextEdit is the id of the TextEdit
- myTextEdit.text.toString().substring(myTextEdit.selectionStart,
- myTextEdit.selectionEnd);
- \endcode
-*/
-QString QQuickTextEdit::selectedText() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->textCursor().selectedText();
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::activeFocusOnPress
-
- Whether the TextEdit should gain active focus on a mouse press. By default this is
- set to true.
-*/
-bool QQuickTextEdit::focusOnPress() const
-{
- Q_D(const QQuickTextEdit);
- return d->focusOnPress;
-}
-
-void QQuickTextEdit::setFocusOnPress(bool on)
-{
- Q_D(QQuickTextEdit);
- if (d->focusOnPress == on)
- return;
- d->focusOnPress = on;
- emit activeFocusOnPressChanged(d->focusOnPress);
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::persistentSelection
-
- Whether the TextEdit should keep the selection visible when it loses active focus to another
- item in the scene. By default this is set to true;
-*/
-bool QQuickTextEdit::persistentSelection() const
-{
- Q_D(const QQuickTextEdit);
- return d->persistentSelection;
-}
-
-void QQuickTextEdit::setPersistentSelection(bool on)
-{
- Q_D(QQuickTextEdit);
- if (d->persistentSelection == on)
- return;
- d->persistentSelection = on;
- emit persistentSelectionChanged(d->persistentSelection);
-}
-
-/*
- \qmlproperty real QtQuick2::TextEdit::textMargin
-
- The margin, in pixels, around the text in the TextEdit.
-*/
-qreal QQuickTextEdit::textMargin() const
-{
- Q_D(const QQuickTextEdit);
- return d->textMargin;
-}
-
-void QQuickTextEdit::setTextMargin(qreal margin)
-{
- Q_D(QQuickTextEdit);
- if (d->textMargin == margin)
- return;
- d->textMargin = margin;
- d->document->setDocumentMargin(d->textMargin);
- emit textMarginChanged(d->textMargin);
-}
-
-void QQuickTextEdit::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
-{
- if (newGeometry.width() != oldGeometry.width())
- updateSize();
- QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
-}
-
-/*!
- Ensures any delayed caching or data loading the class
- needs to performed is complete.
-*/
-void QQuickTextEdit::componentComplete()
-{
- Q_D(QQuickTextEdit);
- QQuickImplicitSizeItem::componentComplete();
-
- if (d->richText)
- d->useImageFallback = qmlEnableImageCache();
-
- if (d->dirty) {
- d->determineHorizontalAlignment();
- d->updateDefaultTextOption();
- updateSize();
- d->dirty = false;
- }
-
-}
-/*!
- \qmlproperty bool QtQuick2::TextEdit::selectByMouse
-
- Defaults to false.
-
- If true, the user can use the mouse to select text in some
- platform-specific way. Note that for some platforms this may
- not be an appropriate interaction (eg. may conflict with how
- the text needs to behave inside a Flickable.
-*/
-bool QQuickTextEdit::selectByMouse() const
-{
- Q_D(const QQuickTextEdit);
- return d->selectByMouse;
-}
-
-void QQuickTextEdit::setSelectByMouse(bool on)
-{
- Q_D(QQuickTextEdit);
- if (d->selectByMouse != on) {
- d->selectByMouse = on;
- setKeepMouseGrab(on);
- if (on)
- setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
- else
- setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
- emit selectByMouseChanged(on);
- }
-}
-
-/*!
- \qmlproperty enum QtQuick2::TextEdit::mouseSelectionMode
-
- Specifies how text should be selected using a mouse.
-
- \list
- \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
- \o TextEdit.SelectWords - The selection is updated with whole words.
- \endlist
-
- This property only applies when \l selectByMouse is true.
-*/
-QQuickTextEdit::SelectionMode QQuickTextEdit::mouseSelectionMode() const
-{
- Q_D(const QQuickTextEdit);
- return d->mouseSelectionMode;
-}
-
-void QQuickTextEdit::setMouseSelectionMode(SelectionMode mode)
-{
- Q_D(QQuickTextEdit);
- if (d->mouseSelectionMode != mode) {
- d->mouseSelectionMode = mode;
- d->control->setWordSelectionEnabled(mode == SelectWords);
- emit mouseSelectionModeChanged(mode);
- }
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::readOnly
-
- Whether the user can interact with the TextEdit item. If this
- property is set to true the text cannot be edited by user interaction.
-
- By default this property is false.
-*/
-void QQuickTextEdit::setReadOnly(bool r)
-{
- Q_D(QQuickTextEdit);
- if (r == isReadOnly())
- return;
-
- setFlag(QQuickItem::ItemAcceptsInputMethod, !r);
- Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
- if (d->selectByMouse)
- flags = flags | Qt::TextSelectableByMouse;
- if (!r)
- flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
- d->control->setTextInteractionFlags(flags);
- if (!r)
- d->control->moveCursor(QTextCursor::End);
-
- emit readOnlyChanged(r);
-}
-
-bool QQuickTextEdit::isReadOnly() const
-{
- Q_D(const QQuickTextEdit);
- return !(d->control->textInteractionFlags() & Qt::TextEditable);
-}
-
-/*!
- Sets how the text edit should interact with user input to the given
- \a flags.
-*/
-void QQuickTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
-{
- Q_D(QQuickTextEdit);
- d->control->setTextInteractionFlags(flags);
-}
-
-/*!
- Returns the flags specifying how the text edit should interact
- with user input.
-*/
-Qt::TextInteractionFlags QQuickTextEdit::textInteractionFlags() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->textInteractionFlags();
-}
-
-/*!
- \qmlproperty rectangle QtQuick2::TextEdit::cursorRectangle
-
- The rectangle where the text cursor is rendered
- within the text edit. Read-only.
-*/
-QRect QQuickTextEdit::cursorRectangle() const
-{
- Q_D(const QQuickTextEdit);
- return d->control->cursorRect().toRect().translated(0,d->yoff);
-}
-
-bool QQuickTextEdit::event(QEvent *event)
-{
- Q_D(QQuickTextEdit);
- if (event->type() == QEvent::ShortcutOverride) {
- d->control->processEvent(event, QPointF(0, -d->yoff));
- return event->isAccepted();
- }
- return QQuickImplicitSizeItem::event(event);
-}
-
-/*!
-\overload
-Handles the given key \a event.
-*/
-void QQuickTextEdit::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (!event->isAccepted())
- QQuickImplicitSizeItem::keyPressEvent(event);
-}
-
-/*!
-\overload
-Handles the given key \a event.
-*/
-void QQuickTextEdit::keyReleaseEvent(QKeyEvent *event)
-{
- Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (!event->isAccepted())
- QQuickImplicitSizeItem::keyReleaseEvent(event);
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::deselect()
-
- Removes active text selection.
-*/
-void QQuickTextEdit::deselect()
-{
- Q_D(QQuickTextEdit);
- QTextCursor c = d->control->textCursor();
- c.clearSelection();
- d->control->setTextCursor(c);
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::selectAll()
-
- Causes all text to be selected.
-*/
-void QQuickTextEdit::selectAll()
-{
- Q_D(QQuickTextEdit);
- d->control->selectAll();
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::selectWord()
-
- Causes the word closest to the current cursor position to be selected.
-*/
-void QQuickTextEdit::selectWord()
-{
- Q_D(QQuickTextEdit);
- QTextCursor c = d->control->textCursor();
- c.select(QTextCursor::WordUnderCursor);
- d->control->setTextCursor(c);
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::select(int start, int end)
-
- Causes the text from \a start to \a end to be selected.
-
- If either start or end is out of range, the selection is not changed.
-
- After calling this, selectionStart will become the lesser
- and selectionEnd will become the greater (regardless of the order passed
- to this method).
-
- \sa selectionStart, selectionEnd
-*/
-void QQuickTextEdit::select(int start, int end)
-{
- Q_D(QQuickTextEdit);
- if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
- return;
- QTextCursor cursor = d->control->textCursor();
- cursor.beginEditBlock();
- cursor.setPosition(start, QTextCursor::MoveAnchor);
- cursor.setPosition(end, QTextCursor::KeepAnchor);
- cursor.endEditBlock();
- d->control->setTextCursor(cursor);
-
- // QTBUG-11100
- updateSelectionMarkers();
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::isRightToLeft(int start, int end)
-
- Returns true if the natural reading direction of the editor text
- found between positions \a start and \a end is right to left.
-*/
-bool QQuickTextEdit::isRightToLeft(int start, int end)
-{
- Q_D(QQuickTextEdit);
- if (start > end) {
- qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
- return false;
- } else {
- return d->text.mid(start, end - start).isRightToLeft();
- }
-}
-
-#ifndef QT_NO_CLIPBOARD
-/*!
- \qmlmethod QtQuick2::TextEdit::cut()
-
- Moves the currently selected text to the system clipboard.
-*/
-void QQuickTextEdit::cut()
-{
- Q_D(QQuickTextEdit);
- d->control->cut();
-}
-
-/*!
- \qmlmethod QtQuick2::TextEdit::copy()
-
- Copies the currently selected text to the system clipboard.
-*/
-void QQuickTextEdit::copy()
-{
- Q_D(QQuickTextEdit);
- d->control->copy();
-}
-
-/*!
- \qmlmethod QtQuick2::TextEdit::paste()
-
- Replaces the currently selected text by the contents of the system clipboard.
-*/
-void QQuickTextEdit::paste()
-{
- Q_D(QQuickTextEdit);
- d->control->paste();
-}
-#endif // QT_NO_CLIPBOARD
-
-/*!
-\overload
-Handles the given mouse \a event.
-*/
-void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextEdit);
- if (d->focusOnPress){
- bool hadActiveFocus = hasActiveFocus();
- forceActiveFocus();
- // re-open input panel on press if already focused
- if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
- openSoftwareInputPanel();
- }
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (!event->isAccepted())
- QQuickImplicitSizeItem::mousePressEvent(event);
-}
-
-/*!
-\overload
-Handles the given mouse \a event.
-*/
-void QQuickTextEdit::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
-
- if (!event->isAccepted())
- QQuickImplicitSizeItem::mouseReleaseEvent(event);
-}
-
-/*!
-\overload
-Handles the given mouse \a event.
-*/
-void QQuickTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (!event->isAccepted())
- QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
-}
-
-/*!
-\overload
-Handles the given mouse \a event.
-*/
-void QQuickTextEdit::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (!event->isAccepted())
- QQuickImplicitSizeItem::mouseMoveEvent(event);
-}
-
-/*!
-\overload
-Handles the given input method \a event.
-*/
-void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
-{
- Q_D(QQuickTextEdit);
- const bool wasComposing = isInputMethodComposing();
- d->control->processEvent(event, QPointF(0, -d->yoff));
- if (wasComposing != isInputMethodComposing())
- emit inputMethodComposingChanged();
-}
-
-void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
-{
- if (change == ItemActiveFocusHasChanged) {
- setCursorVisible(value.boolValue); // ### refactor: focus handling && d->canvas && d->canvas->hasFocus());
- }
- QQuickItem::itemChange(change, value);
-}
-
-/*!
-\overload
-Returns the value of the given \a property.
-*/
-QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
-{
- Q_D(const QQuickTextEdit);
-
- QVariant v;
- switch (property) {
- case Qt::ImEnabled:
- v = (bool)(flags() & ItemAcceptsInputMethod);
- break;
- case Qt::ImHints:
- v = (int)inputMethodHints();
- break;
- default:
- v = d->control->inputMethodQuery(property);
- break;
- }
- return v;
-
-}
-
-void QQuickTextEdit::updateImageCache(const QRectF &)
-{
- Q_D(QQuickTextEdit);
-
- // Do we really need the image cache?
- if (!d->richText || !d->useImageFallback) {
- if (!d->pixmapCache.isNull())
- d->pixmapCache = QPixmap();
- return;
- }
-
- if (width() != d->pixmapCache.width() || height() != d->pixmapCache.height())
- d->pixmapCache = QPixmap(width(), height());
-
- if (d->pixmapCache.isNull())
- return;
-
- // ### Use supplied rect, clear area and update only this part (for cursor updates)
- QRectF bounds = QRectF(0, 0, width(), height());
- d->pixmapCache.fill(Qt::transparent);
- {
- QPainter painter(&d->pixmapCache);
-
- painter.setRenderHint(QPainter::TextAntialiasing);
- painter.translate(0, d->yoff);
-
- d->control->drawContents(&painter, bounds);
- }
-
-}
-
-QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
-{
- Q_UNUSED(updatePaintNodeData);
- Q_D(QQuickTextEdit);
-
- QSGNode *currentNode = oldNode;
- if (d->richText && d->useImageFallback) {
- QSGImageNode *node = 0;
- if (oldNode == 0 || d->nodeType != QQuickTextEditPrivate::NodeIsTexture) {
- delete oldNode;
- node = QQuickItemPrivate::get(this)->sceneGraphContext()->createImageNode();
- d->texture = new QSGPlainTexture();
- d->nodeType = QQuickTextEditPrivate::NodeIsTexture;
- currentNode = node;
- } else {
- node = static_cast<QSGImageNode *>(oldNode);
- }
-
- qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->pixmapCache.toImage());
- node->setTexture(0);
- node->setTexture(d->texture);
-
- node->setTargetRect(QRectF(0, 0, d->pixmapCache.width(), d->pixmapCache.height()));
- node->setSourceRect(QRectF(0, 0, 1, 1));
- node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- node->setVerticalWrapMode(QSGTexture::ClampToEdge);
- node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that..
- node->update();
-
- } else if (oldNode == 0 || d->documentDirty) {
- d->documentDirty = false;
-
-#if defined(Q_OS_MAC)
- // Make sure document is relayouted in the paint node on Mac
- // to avoid crashes due to the font engines created in the
- // shaping process
- d->document->markContentsDirty(0, d->document->characterCount());
-#endif
-
- QQuickTextNode *node = 0;
- if (oldNode == 0 || d->nodeType != QQuickTextEditPrivate::NodeIsText) {
- delete oldNode;
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
- d->nodeType = QQuickTextEditPrivate::NodeIsText;
- currentNode = node;
- } else {
- node = static_cast<QQuickTextNode *>(oldNode);
- }
-
- node->deleteContent();
- node->setMatrix(QMatrix4x4());
-
- QRectF bounds = boundingRect();
-
- QColor selectionColor = d->control->palette().color(QPalette::Highlight);
- QColor selectedTextColor = d->control->palette().color(QPalette::HighlightedText);
- node->addTextDocument(bounds.topLeft(), d->document, d->color, QQuickText::Normal, QColor(),
- selectionColor, selectedTextColor, selectionStart(),
- selectionEnd() - 1); // selectionEnd() returns first char after
- // selection
-
-#if defined(Q_OS_MAC)
- // We also need to make sure the document layout is redone when
- // control is returned to the main thread, as all the font engines
- // are now owned by the rendering thread
- d->document->markContentsDirty(0, d->document->characterCount());
-#endif
- }
-
- if (d->nodeType == QQuickTextEditPrivate::NodeIsText && d->cursorComponent == 0 && !isReadOnly()) {
- QQuickTextNode *node = static_cast<QQuickTextNode *>(currentNode);
-
- QColor color = (!d->cursorVisible || !d->control->cursorOn())
- ? QColor(0, 0, 0, 0)
- : d->color;
-
- if (node->cursorNode() == 0) {
- node->setCursor(cursorRectangle(), color);
- } else {
- node->cursorNode()->setRect(cursorRectangle());
- node->cursorNode()->setColor(color);
- }
-
- }
-
- return currentNode;
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::smooth
-
- This property holds whether the text is smoothly scaled or transformed.
-
- Smooth filtering gives better visual quality, but is slower. If
- the item is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the item is stationary on
- the screen. A common pattern when animating an item is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::canPaste
-
- Returns true if the TextEdit is writable and the content of the clipboard is
- suitable for pasting into the TextEdit.
-*/
-bool QQuickTextEdit::canPaste() const
-{
- Q_D(const QQuickTextEdit);
- return d->canPaste;
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextEdit::inputMethodComposing
-
-
- This property holds whether the TextEdit has partial text input from an
- input method.
-
- While it is composing an input method may rely on mouse or key events from
- the TextEdit to edit or commit the partial text. This property can be used
- to determine when to disable events handlers that may interfere with the
- correct operation of an input method.
-*/
-bool QQuickTextEdit::isInputMethodComposing() const
-{
- Q_D(const QQuickTextEdit);
- if (QTextLayout *layout = d->control->textCursor().block().layout())
- return layout->preeditAreaText().length() > 0;
- return false;
-}
-
-void QQuickTextEditPrivate::init()
-{
- Q_Q(QQuickTextEdit);
-
- q->setSmooth(smooth);
- q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setFlag(QQuickItem::ItemAcceptsInputMethod);
- q->setFlag(QQuickItem::ItemHasContents);
-
- control = new QTextControl(q);
- control->setIgnoreUnusedNavigationEvents(true);
- control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable);
- control->setDragEnabled(false);
-
- // By default, QTextControl will issue both a updateCursorRequest() and an updateRequest()
- // when the cursor needs to be repainted. We need the signals to be separate to be able to
- // distinguish the cursor updates so that we can avoid updating the whole subtree when the
- // cursor blinks.
- if (!QObject::disconnect(control, SIGNAL(updateCursorRequest(QRectF)),
- control, SIGNAL(updateRequest(QRectF)))) {
- qWarning("QQuickTextEditPrivate::init: Failed to disconnect updateCursorRequest and updateRequest");
- }
-
- // QTextControl follows the default text color
- // defined by the platform, declarative text
- // should be black by default
- QPalette pal = control->palette();
- if (pal.color(QPalette::Text) != color) {
- pal.setColor(QPalette::Text, color);
- control->setPalette(pal);
- }
-
- QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateDocument()));
- QObject::connect(control, SIGNAL(updateCursorRequest()), q, SLOT(updateCursor()));
- QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
- QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
- QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
- QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
- QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
- QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
- QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
-#ifndef QT_NO_CLIPBOARD
- QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
- QObject::connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
- canPaste = control->canPaste();
-#endif
-
- document = control->document();
- document->setDefaultFont(font);
- document->setDocumentMargin(textMargin);
- document->setUndoRedoEnabled(false); // flush undo buffer.
- document->setUndoRedoEnabled(true);
- updateDefaultTextOption();
-}
-
-void QQuickTextEdit::q_textChanged()
-{
- Q_D(QQuickTextEdit);
- d->text = text();
- d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft();
- d->determineHorizontalAlignment();
- d->updateDefaultTextOption();
- updateSize();
- updateTotalLines();
- emit textChanged(d->text);
-}
-
-void QQuickTextEdit::moveCursorDelegate()
-{
- Q_D(QQuickTextEdit);
- d->determineHorizontalAlignment();
- updateMicroFocus();
- emit cursorRectangleChanged();
- if (!d->cursor)
- return;
- QRectF cursorRect = cursorRectangle();
- d->cursor->setX(cursorRect.x());
- d->cursor->setY(cursorRect.y());
-}
-
-void QQuickTextEditPrivate::updateSelection()
-{
- Q_Q(QQuickTextEdit);
- QTextCursor cursor = control->textCursor();
- bool startChange = (lastSelectionStart != cursor.selectionStart());
- bool endChange = (lastSelectionEnd != cursor.selectionEnd());
- cursor.beginEditBlock();
- cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
- cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
- cursor.endEditBlock();
- control->setTextCursor(cursor);
- if (startChange)
- q->selectionStartChanged();
- if (endChange)
- q->selectionEndChanged();
-}
-
-void QQuickTextEdit::updateSelectionMarkers()
-{
- Q_D(QQuickTextEdit);
- if (d->lastSelectionStart != d->control->textCursor().selectionStart()) {
- d->lastSelectionStart = d->control->textCursor().selectionStart();
- emit selectionStartChanged();
- }
- if (d->lastSelectionEnd != d->control->textCursor().selectionEnd()) {
- d->lastSelectionEnd = d->control->textCursor().selectionEnd();
- emit selectionEndChanged();
- }
-}
-
-QRectF QQuickTextEdit::boundingRect() const
-{
- Q_D(const QQuickTextEdit);
- QRectF r = QQuickImplicitSizeItem::boundingRect();
- int cursorWidth = 1;
- if (d->cursor)
- cursorWidth = d->cursor->width();
- if (!d->document->isEmpty())
- cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
-
- // Could include font max left/right bearings to either side of rectangle.
-
- r.setRight(r.right() + cursorWidth);
- return r.translated(0,d->yoff);
-}
-
-qreal QQuickTextEditPrivate::getImplicitWidth() const
-{
- Q_Q(const QQuickTextEdit);
- if (!requireImplicitWidth) {
- // We don't calculate implicitWidth unless it is required.
- // We need to force a size update now to ensure implicitWidth is calculated
- const_cast<QQuickTextEditPrivate*>(this)->requireImplicitWidth = true;
- const_cast<QQuickTextEdit*>(q)->updateSize();
- }
- return implicitWidth;
-}
-
-//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
-// need to do all the calculations each time
-void QQuickTextEdit::updateSize()
-{
- Q_D(QQuickTextEdit);
- if (isComponentComplete()) {
- qreal naturalWidth = d->implicitWidth;
- // ### assumes that if the width is set, the text will fill to edges
- // ### (unless wrap is false, then clipping will occur)
- if (widthValid()) {
- if (!d->requireImplicitWidth) {
- emit implicitWidthChanged();
- // if the implicitWidth is used, then updateSize() has already been called (recursively)
- if (d->requireImplicitWidth)
- return;
- }
- if (d->requireImplicitWidth) {
- d->document->setTextWidth(-1);
- naturalWidth = d->document->idealWidth();
- }
- if (d->document->textWidth() != width())
- d->document->setTextWidth(width());
- } else {
- d->document->setTextWidth(-1);
- }
- QFontMetrics fm = QFontMetrics(d->font);
- int dy = height();
- dy -= (int)d->document->size().height();
-
- int nyoff;
- if (heightValid()) {
- if (d->vAlign == AlignBottom)
- nyoff = dy;
- else if (d->vAlign == AlignVCenter)
- nyoff = dy/2;
- else
- nyoff = 0;
- } else {
- nyoff = 0;
- }
- if (nyoff != d->yoff)
- d->yoff = nyoff;
- setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
-
- //### need to comfirm cost of always setting these
- int newWidth = qCeil(d->document->idealWidth());
- if (!widthValid() && d->document->textWidth() != newWidth)
- 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())
- iWidth = newWidth;
- else if (d->requireImplicitWidth)
- iWidth = naturalWidth;
- qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
- if (iWidth > -1)
- setImplicitSize(iWidth, newHeight);
- else
- setImplicitHeight(newHeight);
-
- d->paintedSize = QSize(newWidth, newHeight);
- emit paintedSizeChanged();
- } else {
- d->dirty = true;
- }
- updateDocument();
-}
-
-void QQuickTextEdit::updateDocument()
-{
- Q_D(QQuickTextEdit);
- d->documentDirty = true;
-
- if (isComponentComplete()) {
- updateImageCache();
- update();
- }
-}
-
-void QQuickTextEdit::updateCursor()
-{
- Q_D(QQuickTextEdit);
- if (isComponentComplete()) {
- updateImageCache(d->control->cursorRect());
- update();
- }
-}
-
-void QQuickTextEdit::updateTotalLines()
-{
- Q_D(QQuickTextEdit);
-
- int subLines = 0;
-
- for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
- QTextLayout *layout = it.layout();
- if (!layout)
- continue;
- subLines += layout->lineCount()-1;
- }
-
- int newTotalLines = d->document->lineCount() + subLines;
- if (d->lineCount != newTotalLines) {
- d->lineCount = newTotalLines;
- emit lineCountChanged();
- }
-}
-
-void QQuickTextEditPrivate::updateDefaultTextOption()
-{
- Q_Q(QQuickTextEdit);
- QTextOption opt = document->defaultTextOption();
- int oldAlignment = opt.alignment();
-
- QQuickTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
- if (rightToLeftText) {
- if (horizontalAlignment == QQuickTextEdit::AlignLeft)
- horizontalAlignment = QQuickTextEdit::AlignRight;
- else if (horizontalAlignment == QQuickTextEdit::AlignRight)
- horizontalAlignment = QQuickTextEdit::AlignLeft;
- }
- opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
-
- QTextOption::WrapMode oldWrapMode = opt.wrapMode();
- opt.setWrapMode(QTextOption::WrapMode(wrapMode));
-
- bool oldUseDesignMetrics = opt.useDesignMetrics();
- bool useDesignMetrics = !qmlDisableDistanceField();
- opt.setUseDesignMetrics(useDesignMetrics);
-
- if (oldWrapMode == opt.wrapMode()
- && oldAlignment == opt.alignment()
- && oldUseDesignMetrics == useDesignMetrics) {
- return;
- }
- document->setDefaultTextOption(opt);
-}
-
-
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::openSoftwareInputPanel()
-
- Opens software input panels like virtual keyboards for typing, useful for
- customizing when you want the input keyboard to be shown and hidden in
- your application.
-
- By default the opening of input panels follows the platform style. Input panels are
- always closed if no editor has active focus.
-
- You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
- and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
- the behavior you want.
-
- Only relevant on platforms, which provide virtual keyboards.
-
- \code
- import QtQuick 1.0
- TextEdit {
- id: textEdit
- text: "Hello world!"
- activeFocusOnPress: false
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (!textEdit.activeFocus) {
- textEdit.forceActiveFocus();
- textEdit.openSoftwareInputPanel();
- } else {
- textEdit.focus = false;
- }
- }
- onPressAndHold: textEdit.closeSoftwareInputPanel();
- }
- }
- \endcode
-*/
-void QQuickTextEdit::openSoftwareInputPanel()
-{
- if (qGuiApp)
- qGuiApp->inputPanel()->show();
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::closeSoftwareInputPanel()
-
- Closes a software input panel like a virtual keyboard shown on the screen, useful
- for customizing when you want the input keyboard to be shown and hidden in
- your application.
-
- By default the opening of input panels follows the platform style. Input panels are
- always closed if no editor has active focus.
-
- You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
- and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
- the behavior you want.
-
- Only relevant on platforms, which provide virtual keyboards.
-
- \code
- import QtQuick 1.0
- TextEdit {
- id: textEdit
- text: "Hello world!"
- activeFocusOnPress: false
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (!textEdit.activeFocus) {
- textEdit.forceActiveFocus();
- textEdit.openSoftwareInputPanel();
- } else {
- textEdit.focus = false;
- }
- }
- onPressAndHold: textEdit.closeSoftwareInputPanel();
- }
- }
- \endcode
-*/
-void QQuickTextEdit::closeSoftwareInputPanel()
-{
- if (qGuiApp)
- qGuiApp->inputPanel()->hide();
-}
-
-void QQuickTextEdit::focusInEvent(QFocusEvent *event)
-{
- Q_D(const QQuickTextEdit);
- if (d->focusOnPress && !isReadOnly())
- openSoftwareInputPanel();
- QQuickImplicitSizeItem::focusInEvent(event);
-}
-
-void QQuickTextEdit::q_canPasteChanged()
-{
- Q_D(QQuickTextEdit);
- bool old = d->canPaste;
- d->canPaste = d->control->canPaste();
- if (old!=d->canPaste)
- emit canPasteChanged();
-}
-
-/*!
- \qmlmethod string QtQuick2::TextEdit::getText(int start, int end)
-
- Returns the section of text that is between the \a start and \a end positions.
-
- The returned text does not include any rich text formatting.
-*/
-
-QString QQuickTextEdit::getText(int start, int end) const
-{
- Q_D(const QQuickTextEdit);
- start = qBound(0, start, d->document->characterCount() - 1);
- end = qBound(0, end, d->document->characterCount() - 1);
- QTextCursor cursor(d->document);
- cursor.setPosition(start, QTextCursor::MoveAnchor);
- cursor.setPosition(end, QTextCursor::KeepAnchor);
- return cursor.selectedText();
-}
-
-/*!
- \qmlmethod string QtQuick2::TextEdit::getFormattedText(int start, int end)
-
- Returns the section of text that is between the \a start and \a end positions.
-
- The returned text will be formatted according the \l textFormat property.
-*/
-
-QString QQuickTextEdit::getFormattedText(int start, int end) const
-{
- Q_D(const QQuickTextEdit);
-
- start = qBound(0, start, d->document->characterCount() - 1);
- end = qBound(0, end, d->document->characterCount() - 1);
-
- QTextCursor cursor(d->document);
- cursor.setPosition(start, QTextCursor::MoveAnchor);
- cursor.setPosition(end, QTextCursor::KeepAnchor);
-
- if (d->richText) {
-#ifndef QT_NO_TEXTHTMLPARSER
- return cursor.selection().toHtml();
-#else
- return cursor.selection().toPlainText();
-#endif
- } else {
- return cursor.selection().toPlainText();
- }
-}
-
-/*!
- \qmlmethod void QtQuick2::TextEdit::insert(int position, string text)
-
- Inserts \a text into the TextEdit at position.
-*/
-void QQuickTextEdit::insert(int position, const QString &text)
-{
- Q_D(QQuickTextEdit);
- if (position < 0 || position >= d->document->characterCount())
- return;
- QTextCursor cursor(d->document);
- cursor.setPosition(position);
- d->richText = d->richText || (d->format == AutoText && Qt::mightBeRichText(text));
- if (d->richText) {
-#ifndef QT_NO_TEXTHTMLPARSER
- cursor.insertHtml(text);
-#else
- cursor.insertText(text);
-#endif
- } else {
- cursor.insertText(text);
- }
-}
-
-/*!
- \qmlmethod string QtQuick2::TextEdit::getText(int start, int end)
-
- Removes the section of text that is between the \a start and \a end positions from the TextEdit.
-*/
-
-void QQuickTextEdit::remove(int start, int end)
-{
- Q_D(QQuickTextEdit);
- start = qBound(0, start, d->document->characterCount() - 1);
- end = qBound(0, end, d->document->characterCount() - 1);
- QTextCursor cursor(d->document);
- cursor.setPosition(start, QTextCursor::MoveAnchor);
- cursor.setPosition(end, QTextCursor::KeepAnchor);
- cursor.removeSelectedText();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquicktextedit_p.h b/src/declarative/items/qquicktextedit_p.h
deleted file mode 100644
index 25988959f6..0000000000
--- a/src/declarative/items/qquicktextedit_p.h
+++ /dev/null
@@ -1,314 +0,0 @@
-// Commit: 27e4302b7f45f22180693d26747f419177c81e27
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKTEXTEDIT_P_H
-#define QQUICKTEXTEDIT_P_H
-
-#include "qquickimplicitsizeitem_p.h"
-
-#include <QtGui/qtextoption.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickTextEditPrivate;
-class Q_AUTOTEST_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
-{
- Q_OBJECT
- Q_ENUMS(VAlignment)
- Q_ENUMS(HAlignment)
- Q_ENUMS(TextFormat)
- Q_ENUMS(WrapMode)
- Q_ENUMS(SelectionMode)
-
- Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
- Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
- Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
- Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
- Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
- Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
- Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
- Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
- Q_PROPERTY(int length READ length NOTIFY textChanged)
- Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
- Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
- Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
- Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
- Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
- Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
- Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
- Q_PROPERTY(QDeclarativeComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
- Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
- Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
- Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
- Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
- Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged)
- Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged)
- Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
- Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
- Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
- Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
- Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
-
-public:
- QQuickTextEdit(QQuickItem *parent=0);
-
- enum HAlignment {
- AlignLeft = Qt::AlignLeft,
- AlignRight = Qt::AlignRight,
- AlignHCenter = Qt::AlignHCenter,
- AlignJustify = Qt::AlignJustify
- };
-
- enum VAlignment {
- AlignTop = Qt::AlignTop,
- AlignBottom = Qt::AlignBottom,
- AlignVCenter = Qt::AlignVCenter
- };
-
- enum TextFormat {
- PlainText = Qt::PlainText,
- RichText = Qt::RichText,
- AutoText = Qt::AutoText
- };
-
- enum WrapMode { NoWrap = QTextOption::NoWrap,
- WordWrap = QTextOption::WordWrap,
- WrapAnywhere = QTextOption::WrapAnywhere,
- WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
- Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
- };
-
- enum SelectionMode {
- SelectCharacters,
- SelectWords
- };
-
- Q_INVOKABLE void openSoftwareInputPanel();
- Q_INVOKABLE void closeSoftwareInputPanel();
-
- QString text() const;
- void setText(const QString &);
-
- TextFormat textFormat() const;
- void setTextFormat(TextFormat format);
-
- QFont font() const;
- void setFont(const QFont &font);
-
- QColor color() const;
- void setColor(const QColor &c);
-
- QColor selectionColor() const;
- void setSelectionColor(const QColor &c);
-
- QColor selectedTextColor() const;
- void setSelectedTextColor(const QColor &c);
-
- HAlignment hAlign() const;
- void setHAlign(HAlignment align);
- void resetHAlign();
- HAlignment effectiveHAlign() const;
-
- VAlignment vAlign() const;
- void setVAlign(VAlignment align);
-
- WrapMode wrapMode() const;
- void setWrapMode(WrapMode w);
-
- int lineCount() const;
-
- int length() const;
-
- bool isCursorVisible() const;
- void setCursorVisible(bool on);
-
- int cursorPosition() const;
- void setCursorPosition(int pos);
-
- QDeclarativeComponent* cursorDelegate() const;
- void setCursorDelegate(QDeclarativeComponent*);
-
- int selectionStart() const;
- int selectionEnd() const;
-
- QString selectedText() const;
-
- bool focusOnPress() const;
- void setFocusOnPress(bool on);
-
- bool persistentSelection() const;
- void setPersistentSelection(bool on);
-
- qreal textMargin() const;
- void setTextMargin(qreal margin);
-
- bool selectByMouse() const;
- void setSelectByMouse(bool);
-
- SelectionMode mouseSelectionMode() const;
- void setMouseSelectionMode(SelectionMode mode);
-
- bool canPaste() const;
-
- virtual void componentComplete();
-
- /* FROM EDIT */
- void setReadOnly(bool);
- bool isReadOnly() const;
-
- void setTextInteractionFlags(Qt::TextInteractionFlags flags);
- Qt::TextInteractionFlags textInteractionFlags() const;
-
- QRect cursorRectangle() const;
-
- QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
-
- qreal paintedWidth() const;
- qreal paintedHeight() const;
-
- Q_INVOKABLE QRectF positionToRectangle(int) const;
- Q_INVOKABLE int positionAt(int x, int y) const;
- Q_INVOKABLE void moveCursorSelection(int pos);
- Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
-
- QRectF boundingRect() const;
-
- bool isInputMethodComposing() const;
-
- Q_INVOKABLE QString getText(int start, int end) const;
- Q_INVOKABLE QString getFormattedText(int start, int end) const;
-
-Q_SIGNALS:
- void textChanged(const QString &);
- void paintedSizeChanged();
- void cursorPositionChanged();
- void cursorRectangleChanged();
- void selectionStartChanged();
- void selectionEndChanged();
- void selectionChanged();
- void colorChanged(const QColor &color);
- void selectionColorChanged(const QColor &color);
- void selectedTextColorChanged(const QColor &color);
- void fontChanged(const QFont &font);
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
- void wrapModeChanged();
- void lineCountChanged();
- void textFormatChanged(TextFormat textFormat);
- void readOnlyChanged(bool isReadOnly);
- void cursorVisibleChanged(bool isCursorVisible);
- void cursorDelegateChanged();
- void activeFocusOnPressChanged(bool activeFocusOnPressed);
- void persistentSelectionChanged(bool isPersistentSelection);
- void textMarginChanged(qreal textMargin);
- void selectByMouseChanged(bool selectByMouse);
- void mouseSelectionModeChanged(SelectionMode mode);
- void linkActivated(const QString &link);
- void canPasteChanged();
- void inputMethodComposingChanged();
- void effectiveHorizontalAlignmentChanged();
-
-public Q_SLOTS:
- void selectAll();
- void selectWord();
- void select(int start, int end);
- void deselect();
- bool isRightToLeft(int start, int end);
-#ifndef QT_NO_CLIPBOARD
- void cut();
- void copy();
- void paste();
-#endif
- void insert(int position, const QString &text);
- void remove(int start, int end);
-
-private Q_SLOTS:
- void q_textChanged();
- void updateSelectionMarkers();
- void moveCursorDelegate();
- void loadCursorDelegate();
- void q_canPasteChanged();
- void updateDocument();
- void updateCursor();
-
-private:
- void updateSize();
- void updateTotalLines();
- void updateImageCache(const QRectF &rect = QRectF());
-
-protected:
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
-
- bool event(QEvent *);
- void keyPressEvent(QKeyEvent *);
- void keyReleaseEvent(QKeyEvent *);
- void focusInEvent(QFocusEvent *event);
-
- // mouse filter?
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void inputMethodEvent(QInputMethodEvent *e);
- virtual void itemChange(ItemChange, const ItemChangeData &);
-
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
-
-private:
- Q_DISABLE_COPY(QQuickTextEdit)
- Q_DECLARE_PRIVATE(QQuickTextEdit)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickTextEdit)
-
-QT_END_HEADER
-
-#endif // QQUICKTEXTEDIT_P_H
diff --git a/src/declarative/items/qquicktextinput.cpp b/src/declarative/items/qquicktextinput.cpp
deleted file mode 100644
index f3cdc8835a..0000000000
--- a/src/declarative/items/qquicktextinput.cpp
+++ /dev/null
@@ -1,2007 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquicktextinput_p.h"
-#include "qquicktextinput_p_p.h"
-#include "qquickcanvas.h"
-
-#include <private/qdeclarativeglobal_p.h>
-
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qevent.h>
-#include <QTextBoundaryFinder>
-#include "qquicktextnode_p.h"
-#include <qsgsimplerectnode.h>
-
-#include <QtGui/qstylehints.h>
-#include <QtGui/qinputpanel.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-/*!
- \qmlclass TextInput QQuickTextInput
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The TextInput item displays an editable line of text.
- \inherits Item
-
- The TextInput element displays a single line of editable plain text.
-
- TextInput is used to accept a line of text input. Input constraints
- can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
- and setting \l echoMode to an appropriate value enables TextInput to be used for
- a password input field.
-
- On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
- If you want such bindings (on any platform), you will need to construct them in QML.
-
- \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
-*/
-QQuickTextInput::QQuickTextInput(QQuickItem* parent)
-: QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
-{
- Q_D(QQuickTextInput);
- d->init();
-}
-
-QQuickTextInput::~QQuickTextInput()
-{
-}
-
-/*!
- \qmlproperty string QtQuick2::TextInput::text
-
- The text in the TextInput.
-*/
-QString QQuickTextInput::text() const
-{
- Q_D(const QQuickTextInput);
- return d->control->text();
-}
-
-void QQuickTextInput::setText(const QString &s)
-{
- Q_D(QQuickTextInput);
- if (s == text())
- return;
- d->control->setText(s);
-}
-
-/*!
- \qmlproperty string QtQuick2::TextInput::font.family
-
- Sets the family name of the font.
-
- The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
- If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
- If the family isn't available a family will be set using the font matching algorithm.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::font.bold
-
- Sets whether the font weight is bold.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::TextInput::font.weight
-
- Sets the font's weight.
-
- The weight can be one of:
- \list
- \o Font.Light
- \o Font.Normal - the default
- \o Font.DemiBold
- \o Font.Bold
- \o Font.Black
- \endlist
-
- \qml
- TextInput { text: "Hello"; font.weight: Font.DemiBold }
- \endqml
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::font.italic
-
- Sets whether the font has an italic style.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::font.underline
-
- Sets whether the text is underlined.
-*/
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::font.strikeout
-
- Sets whether the font has a strikeout style.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextInput::font.pointSize
-
- Sets the font size in points. The point size must be greater than zero.
-*/
-
-/*!
- \qmlproperty int QtQuick2::TextInput::font.pixelSize
-
- Sets the font size in pixels.
-
- Using this function makes the font device dependent.
- Use \c pointSize to set the size of the font in a device independent manner.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextInput::font.letterSpacing
-
- Sets the letter spacing for the font.
-
- Letter spacing changes the default spacing between individual letters in the font.
- A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
-*/
-
-/*!
- \qmlproperty real QtQuick2::TextInput::font.wordSpacing
-
- Sets the word spacing for the font.
-
- Word spacing changes the default spacing between individual words.
- A positive value increases the word spacing by a corresponding amount of pixels,
- while a negative value decreases the inter-word spacing accordingly.
-*/
-
-/*!
- \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
-
- Sets the capitalization for the text.
-
- \list
- \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
- \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
- \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
- \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
- \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
- \endlist
-
- \qml
- TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
- \endqml
-*/
-
-QFont QQuickTextInput::font() const
-{
- Q_D(const QQuickTextInput);
- return d->sourceFont;
-}
-
-void QQuickTextInput::setFont(const QFont &font)
-{
- Q_D(QQuickTextInput);
- if (d->sourceFont == font)
- return;
-
- d->sourceFont = font;
- QFont oldFont = d->font;
- d->font = font;
- if (d->font.pointSizeF() != -1) {
- // 0.5pt resolution
- qreal size = qRound(d->font.pointSizeF()*2.0);
- d->font.setPointSizeF(size/2.0);
- }
- if (oldFont != d->font) {
- d->control->setFont(d->font);
- updateSize();
- updateCursorRectangle();
- if (d->cursorItem) {
- d->cursorItem->setHeight(QFontMetrics(d->font).height());
- }
- }
- emit fontChanged(d->sourceFont);
-}
-
-/*!
- \qmlproperty color QtQuick2::TextInput::color
-
- The text color.
-*/
-QColor QQuickTextInput::color() const
-{
- Q_D(const QQuickTextInput);
- return d->color;
-}
-
-void QQuickTextInput::setColor(const QColor &c)
-{
- Q_D(QQuickTextInput);
- if (c != d->color) {
- d->color = c;
- update();
- emit colorChanged(c);
- }
-}
-
-
-/*!
- \qmlproperty color QtQuick2::TextInput::selectionColor
-
- The text highlight color, used behind selections.
-*/
-QColor QQuickTextInput::selectionColor() const
-{
- Q_D(const QQuickTextInput);
- return d->selectionColor;
-}
-
-void QQuickTextInput::setSelectionColor(const QColor &color)
-{
- Q_D(QQuickTextInput);
- if (d->selectionColor == color)
- return;
-
- d->selectionColor = color;
- QPalette p = d->control->palette();
- p.setColor(QPalette::Highlight, d->selectionColor);
- d->control->setPalette(p);
- if (d->control->hasSelectedText())
- update();
- emit selectionColorChanged(color);
-}
-/*!
- \qmlproperty color QtQuick2::TextInput::selectedTextColor
-
- The highlighted text color, used in selections.
-*/
-QColor QQuickTextInput::selectedTextColor() const
-{
- Q_D(const QQuickTextInput);
- return d->selectedTextColor;
-}
-
-void QQuickTextInput::setSelectedTextColor(const QColor &color)
-{
- Q_D(QQuickTextInput);
- if (d->selectedTextColor == color)
- return;
-
- d->selectedTextColor = color;
- QPalette p = d->control->palette();
- p.setColor(QPalette::HighlightedText, d->selectedTextColor);
- d->control->setPalette(p);
- if (d->control->hasSelectedText())
- update();
- emit selectedTextColorChanged(color);
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
- \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
-
- Sets the horizontal alignment of the text within the TextInput item's
- width and height. By default, the text alignment follows the natural alignment
- of the text, for example text that is read from left to right will be aligned to
- the left.
-
- TextInput does not have vertical alignment, as the natural height is
- exactly the height of the single line of text. If you set the height
- manually to something larger, TextInput will always be top aligned
- vertically. You can use anchors to align it however you want within
- another item.
-
- The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
- \c TextInput.AlignHCenter.
-
- When using the attached property LayoutMirroring::enabled to mirror application
- layouts, the horizontal alignment of text will also be mirrored. However, the property
- \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
- of TextInput, use the read-only property \c effectiveHorizontalAlignment.
-*/
-QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
-{
- Q_D(const QQuickTextInput);
- return d->hAlign;
-}
-
-void QQuickTextInput::setHAlign(HAlignment align)
-{
- Q_D(QQuickTextInput);
- bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
- d->hAlignImplicit = false;
- if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
- updateCursorRectangle();
- }
-}
-
-void QQuickTextInput::resetHAlign()
-{
- Q_D(QQuickTextInput);
- d->hAlignImplicit = true;
- if (d->determineHorizontalAlignment() && isComponentComplete()) {
- updateCursorRectangle();
- }
-}
-
-QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
-{
- Q_D(const QQuickTextInput);
- QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
- if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
- switch (d->hAlign) {
- case QQuickTextInput::AlignLeft:
- effectiveAlignment = QQuickTextInput::AlignRight;
- break;
- case QQuickTextInput::AlignRight:
- effectiveAlignment = QQuickTextInput::AlignLeft;
- break;
- default:
- break;
- }
- }
- return effectiveAlignment;
-}
-
-bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
-{
- Q_Q(QQuickTextInput);
- if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
- QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
- hAlign = alignment;
- emit q->horizontalAlignmentChanged(alignment);
- if (oldEffectiveHAlign != q->effectiveHAlign())
- emit q->effectiveHorizontalAlignmentChanged();
- return true;
- }
- return false;
-}
-
-bool QQuickTextInputPrivate::determineHorizontalAlignment()
-{
- if (hAlignImplicit) {
- // if no explicit alignment has been set, follow the natural layout direction of the text
- QString text = control->text();
- if (text.isEmpty())
- text = control->preeditAreaText();
- bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
- return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
- }
- return false;
-}
-
-void QQuickTextInputPrivate::mirrorChange()
-{
- Q_Q(QQuickTextInput);
- if (q->isComponentComplete()) {
- if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
- q->updateCursorRectangle();
- emit q->effectiveHorizontalAlignmentChanged();
- }
- }
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::readOnly
-
- Sets whether user input can modify the contents of the TextInput.
-
- If readOnly is set to true, then user input will not affect the text
- property. Any bindings or attempts to set the text property will still
- work.
-*/
-bool QQuickTextInput::isReadOnly() const
-{
- Q_D(const QQuickTextInput);
- return d->control->isReadOnly();
-}
-
-void QQuickTextInput::setReadOnly(bool ro)
-{
- Q_D(QQuickTextInput);
- if (d->control->isReadOnly() == ro)
- return;
-
- setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
- d->control->setReadOnly(ro);
- if (!ro)
- d->control->setCursorPosition(d->control->end());
-
- emit readOnlyChanged(ro);
-}
-
-/*!
- \qmlproperty int QtQuick2::TextInput::maximumLength
- The maximum permitted length of the text in the TextInput.
-
- If the text is too long, it is truncated at the limit.
-
- By default, this property contains a value of 32767.
-*/
-int QQuickTextInput::maxLength() const
-{
- Q_D(const QQuickTextInput);
- return d->control->maxLength();
-}
-
-void QQuickTextInput::setMaxLength(int ml)
-{
- Q_D(QQuickTextInput);
- if (d->control->maxLength() == ml)
- return;
-
- d->control->setMaxLength(ml);
-
- emit maximumLengthChanged(ml);
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::cursorVisible
- Set to true when the TextInput shows a cursor.
-
- This property is set and unset when the TextInput gets active focus, so that other
- properties can be bound to whether the cursor is currently showing. As it
- gets set and unset automatically, when you set the value yourself you must
- keep in mind that your value may be overwritten.
-
- It can be set directly in script, for example if a KeyProxy might
- forward keys to it and you desire it to look active when this happens
- (but without actually giving it active focus).
-
- It should not be set directly on the element, like in the below QML,
- as the specified value will be overridden an lost on focus changes.
-
- \code
- TextInput {
- text: "Text"
- cursorVisible: false
- }
- \endcode
-
- In the above snippet the cursor will still become visible when the
- TextInput gains active focus.
-*/
-bool QQuickTextInput::isCursorVisible() const
-{
- Q_D(const QQuickTextInput);
- return d->cursorVisible;
-}
-
-void QQuickTextInput::setCursorVisible(bool on)
-{
- Q_D(QQuickTextInput);
- if (d->cursorVisible == on)
- return;
- d->cursorVisible = on;
- d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
- QRect r = d->control->cursorRect();
- if (d->control->inputMask().isEmpty())
- updateRect(r);
- else
- updateRect();
- emit cursorVisibleChanged(d->cursorVisible);
-}
-
-/*!
- \qmlproperty int QtQuick2::TextInput::cursorPosition
- The position of the cursor in the TextInput.
-*/
-int QQuickTextInput::cursorPosition() const
-{
- Q_D(const QQuickTextInput);
- return d->control->cursor();
-}
-void QQuickTextInput::setCursorPosition(int cp)
-{
- Q_D(QQuickTextInput);
- if (cp < 0 || cp > d->control->text().length())
- return;
- d->control->moveCursor(cp);
-}
-
-/*!
- Returns a Rect which encompasses the cursor, but which may be larger than is
- required. Ignores custom cursor delegates.
-*/
-QRect QQuickTextInput::cursorRectangle() const
-{
- Q_D(const QQuickTextInput);
- QRect r = d->control->cursorRect();
- // Scroll and make consistent with TextEdit
- // QLineControl inexplicably adds 1 to the height and horizontal padding
- // for unicode direction markers.
- r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
- return r;
-}
-/*!
- \qmlproperty int QtQuick2::TextInput::selectionStart
-
- The cursor position before the first character in the current selection.
-
- This property is read-only. To change the selection, use select(start,end),
- selectAll(), or selectWord().
-
- \sa selectionEnd, cursorPosition, selectedText
-*/
-int QQuickTextInput::selectionStart() const
-{
- Q_D(const QQuickTextInput);
- return d->lastSelectionStart;
-}
-/*!
- \qmlproperty int QtQuick2::TextInput::selectionEnd
-
- The cursor position after the last character in the current selection.
-
- This property is read-only. To change the selection, use select(start,end),
- selectAll(), or selectWord().
-
- \sa selectionStart, cursorPosition, selectedText
-*/
-int QQuickTextInput::selectionEnd() const
-{
- Q_D(const QQuickTextInput);
- return d->lastSelectionEnd;
-}
-/*!
- \qmlmethod void QtQuick2::TextInput::select(int start, int end)
-
- Causes the text from \a start to \a end to be selected.
-
- If either start or end is out of range, the selection is not changed.
-
- After calling this, selectionStart will become the lesser
- and selectionEnd will become the greater (regardless of the order passed
- to this method).
-
- \sa selectionStart, selectionEnd
-*/
-void QQuickTextInput::select(int start, int end)
-{
- Q_D(QQuickTextInput);
- if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
- return;
- d->control->setSelection(start, end-start);
-}
-
-/*!
- \qmlproperty string QtQuick2::TextInput::selectedText
-
- This read-only property provides the text currently selected in the
- text input.
-
- It is equivalent to the following snippet, but is faster and easier
- to use.
-
- \js
- myTextInput.text.toString().substring(myTextInput.selectionStart,
- myTextInput.selectionEnd);
- \endjs
-*/
-QString QQuickTextInput::selectedText() const
-{
- Q_D(const QQuickTextInput);
- return d->control->selectedText();
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
-
- Whether the TextInput should gain active focus on a mouse press. By default this is
- set to true.
-*/
-bool QQuickTextInput::focusOnPress() const
-{
- Q_D(const QQuickTextInput);
- return d->focusOnPress;
-}
-
-void QQuickTextInput::setFocusOnPress(bool b)
-{
- Q_D(QQuickTextInput);
- if (d->focusOnPress == b)
- return;
-
- d->focusOnPress = b;
-
- emit activeFocusOnPressChanged(d->focusOnPress);
-}
-/*!
- \qmlproperty bool QtQuick2::TextInput::autoScroll
-
- Whether the TextInput should scroll when the text is longer than the width. By default this is
- set to true.
-*/
-bool QQuickTextInput::autoScroll() const
-{
- Q_D(const QQuickTextInput);
- return d->autoScroll;
-}
-
-void QQuickTextInput::setAutoScroll(bool b)
-{
- Q_D(QQuickTextInput);
- if (d->autoScroll == b)
- return;
-
- d->autoScroll = b;
- //We need to repaint so that the scrolling is taking into account.
- updateSize(true);
- updateCursorRectangle();
- emit autoScrollChanged(d->autoScroll);
-}
-
-#ifndef QT_NO_VALIDATOR
-
-/*!
- \qmlclass IntValidator QIntValidator
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
-
- This element provides a validator for integer values.
-
- IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
- will accept locale specific digits, group separators, and positive and negative signs. In
- addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
- locale.
-*/
-/*!
- \qmlproperty int QtQuick2::IntValidator::top
-
- This property holds the validator's highest acceptable value.
- By default, this property's value is derived from the highest signed integer available (typically 2147483647).
-*/
-/*!
- \qmlproperty int QtQuick2::IntValidator::bottom
-
- This property holds the validator's lowest acceptable value.
- By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
-*/
-
-/*!
- \qmlclass DoubleValidator QDoubleValidator
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
-
- This element provides a validator for non-integer numbers.
-*/
-
-/*!
- \qmlproperty real QtQuick2::DoubleValidator::top
-
- This property holds the validator's maximum acceptable value.
- By default, this property contains a value of infinity.
-*/
-/*!
- \qmlproperty real QtQuick2::DoubleValidator::bottom
-
- This property holds the validator's minimum acceptable value.
- By default, this property contains a value of -infinity.
-*/
-/*!
- \qmlproperty int QtQuick2::DoubleValidator::decimals
-
- This property holds the validator's maximum number of digits after the decimal point.
- By default, this property contains a value of 1000.
-*/
-/*!
- \qmlproperty enumeration QtQuick2::DoubleValidator::notation
- This property holds the notation of how a string can describe a number.
-
- The possible values for this property are:
-
- \list
- \o DoubleValidator.StandardNotation
- \o DoubleValidator.ScientificNotation (default)
- \endlist
-
- If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
-*/
-
-/*!
- \qmlclass RegExpValidator QRegExpValidator
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
-
- This element provides a validator, which counts as valid any string which
- matches a specified regular expression.
-*/
-/*!
- \qmlproperty regExp QtQuick2::RegExpValidator::regExp
-
- This property holds the regular expression used for validation.
-
- Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
- matching "a".
-
- By default, this property contains a regular expression with the pattern .* that matches any string.
-*/
-
-/*!
- \qmlproperty Validator QtQuick2::TextInput::validator
-
- Allows you to set a validator on the TextInput. When a validator is set
- the TextInput will only accept input which leaves the text property in
- an acceptable or intermediate state. The accepted signal will only be sent
- if the text is in an acceptable state when enter is pressed.
-
- Currently supported validators are IntValidator, DoubleValidator and
- RegExpValidator. An example of using validators is shown below, which allows
- input of integers between 11 and 31 into the text input:
-
- \code
- import QtQuick 1.0
- TextInput{
- validator: IntValidator{bottom: 11; top: 31;}
- focus: true
- }
- \endcode
-
- \sa acceptableInput, inputMask
-*/
-
-QValidator* QQuickTextInput::validator() const
-{
- Q_D(const QQuickTextInput);
- //###const cast isn't good, but needed for property system?
- return const_cast<QValidator*>(d->control->validator());
-}
-
-void QQuickTextInput::setValidator(QValidator* v)
-{
- Q_D(QQuickTextInput);
- if (d->control->validator() == v)
- return;
-
- d->control->setValidator(v);
- if (!d->control->hasAcceptableInput()) {
- d->oldValidity = false;
- emit acceptableInputChanged();
- }
-
- emit validatorChanged();
-}
-#endif // QT_NO_VALIDATOR
-
-/*!
- \qmlproperty string QtQuick2::TextInput::inputMask
-
- Allows you to set an input mask on the TextInput, restricting the allowable
- text inputs. See QLineEdit::inputMask for further details, as the exact
- same mask strings are used by TextInput.
-
- \sa acceptableInput, validator
-*/
-QString QQuickTextInput::inputMask() const
-{
- Q_D(const QQuickTextInput);
- return d->control->inputMask();
-}
-
-void QQuickTextInput::setInputMask(const QString &im)
-{
- Q_D(QQuickTextInput);
- if (d->control->inputMask() == im)
- return;
-
- d->control->setInputMask(im);
- emit inputMaskChanged(d->control->inputMask());
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::acceptableInput
-
- This property is always true unless a validator or input mask has been set.
- If a validator or input mask has been set, this property will only be true
- if the current text is acceptable to the validator or input mask as a final
- string (not as an intermediate string).
-*/
-bool QQuickTextInput::hasAcceptableInput() const
-{
- Q_D(const QQuickTextInput);
- return d->control->hasAcceptableInput();
-}
-
-/*!
- \qmlsignal QtQuick2::TextInput::onAccepted()
-
- This handler is called when the Return or Enter key is pressed.
- Note that if there is a \l validator or \l inputMask set on the text
- input, the handler will only be emitted if the input is in an acceptable
- state.
-*/
-
-void QQuickTextInputPrivate::updateInputMethodHints()
-{
- Q_Q(QQuickTextInput);
- Qt::InputMethodHints hints = inputMethodHints;
- uint echo = control->echoMode();
- if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
- hints |= Qt::ImhHiddenText;
- else if (echo == QQuickTextInput::PasswordEchoOnEdit)
- hints &= ~Qt::ImhHiddenText;
- if (echo != QQuickTextInput::Normal)
- hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- q->setInputMethodHints(hints);
-}
-/*!
- \qmlproperty enumeration QtQuick2::TextInput::echoMode
-
- Specifies how the text should be displayed in the TextInput.
- \list
- \o TextInput.Normal - Displays the text as it is. (Default)
- \o TextInput.Password - Displays asterisks instead of characters.
- \o TextInput.NoEcho - Displays nothing.
- \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
- while editing, otherwise displays asterisks.
- \endlist
-*/
-QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
-{
- Q_D(const QQuickTextInput);
- return (QQuickTextInput::EchoMode)d->control->echoMode();
-}
-
-void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
-{
- Q_D(QQuickTextInput);
- if (echoMode() == echo)
- return;
- d->control->setEchoMode((QLineControl::EchoMode)echo);
- d->updateInputMethodHints();
- q_textChanged();
- emit echoModeChanged(echoMode());
-}
-
-Qt::InputMethodHints QQuickTextInput::imHints() const
-{
- Q_D(const QQuickTextInput);
- return d->inputMethodHints;
-}
-
-void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
-{
- Q_D(QQuickTextInput);
- if (d->inputMethodHints == hints)
- return;
- d->inputMethodHints = hints;
- d->updateInputMethodHints();
-}
-
-/*!
- \qmlproperty Component QtQuick2::TextInput::cursorDelegate
- The delegate for the cursor in the TextInput.
-
- If you set a cursorDelegate for a TextInput, this delegate will be used for
- drawing the cursor instead of the standard cursor. An instance of the
- delegate will be created and managed by the TextInput when a cursor is
- needed, and the x property of delegate instance will be set so as
- to be one pixel before the top left of the current character.
-
- Note that the root item of the delegate component must be a QDeclarativeItem or
- QDeclarativeItem derived item.
-*/
-QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
-{
- Q_D(const QQuickTextInput);
- return d->cursorComponent;
-}
-
-void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
-{
- Q_D(QQuickTextInput);
- if (d->cursorComponent == c)
- return;
-
- d->cursorComponent = c;
- if (!c) {
- //note that the components are owned by something else
- delete d->cursorItem;
- } else {
- d->startCreatingCursor();
- }
-
- emit cursorDelegateChanged();
-}
-
-void QQuickTextInputPrivate::startCreatingCursor()
-{
- Q_Q(QQuickTextInput);
- if (cursorComponent->isReady()) {
- q->createCursor();
- } else if (cursorComponent->isLoading()) {
- q->connect(cursorComponent, SIGNAL(statusChanged(int)),
- q, SLOT(createCursor()));
- } else { // isError
- qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
- }
-}
-
-void QQuickTextInput::createCursor()
-{
- Q_D(QQuickTextInput);
- if (d->cursorComponent->isError()) {
- qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
- return;
- }
-
- if (!d->cursorComponent->isReady())
- return;
-
- if (d->cursorItem)
- delete d->cursorItem;
- QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
- QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
- d->cursorItem = qobject_cast<QQuickItem*>(object);
- if (!d->cursorItem) {
- delete object;
- qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
- return;
- }
-
- QDeclarative_setParent_noEvent(d->cursorItem, this);
- d->cursorItem->setParentItem(this);
- d->cursorItem->setX(d->control->cursorToX());
- d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
-}
-
-/*!
- \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
-
- This function takes a character position and returns the rectangle that the
- cursor would occupy, if it was placed at that character position.
-
- This is similar to setting the cursorPosition, and then querying the cursor
- rectangle, but the cursorPosition is not changed.
-*/
-QRectF QQuickTextInput::positionToRectangle(int pos) const
-{
- Q_D(const QQuickTextInput);
- if (pos > d->control->cursorPosition())
- pos += d->control->preeditAreaText().length();
- return QRectF(d->control->cursorToX(pos)-d->hscroll,
- 0.0,
- d->control->cursorWidth(),
- cursorRectangle().height());
-}
-
-/*!
- \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
-
- This function returns the character position at
- x pixels from the left of the textInput. Position 0 is before the
- first character, position 1 is after the first character but before the second,
- and so on until position text.length, which is after all characters.
-
- This means that for all x values before the first character this function returns 0,
- and for all x values after the last character this function returns text.length.
-
- The cursor position type specifies how the cursor position should be resolved.
-
- \list
- \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
- \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
- \endlist
-*/
-int QQuickTextInput::positionAt(int x) const
-{
- return positionAt(x, CursorBetweenCharacters);
-}
-
-int QQuickTextInput::positionAt(int x, CursorPosition position) const
-{
- Q_D(const QQuickTextInput);
- int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
- const int cursor = d->control->cursor();
- if (pos > cursor) {
- const int preeditLength = d->control->preeditAreaText().length();
- pos = pos > cursor + preeditLength
- ? pos - preeditLength
- : cursor;
- }
- return pos;
-}
-
-void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
-{
- Q_D(QQuickTextInput);
- // Don't allow MacOSX up/down support, and we don't allow a completer.
- bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
- if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
- // Ignore when moving off the end unless there is a selection,
- // because then moving will do something (deselect).
- int cursorPosition = d->control->cursor();
- if (cursorPosition == 0)
- ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
- if (cursorPosition == d->control->text().length())
- ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
- }
- if (ignore) {
- ev->ignore();
- } else {
- d->control->processKeyEvent(ev);
- }
- if (!ev->isAccepted())
- QQuickImplicitSizeItem::keyPressEvent(ev);
-}
-
-void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
-{
- Q_D(QQuickTextInput);
- const bool wasComposing = d->control->preeditAreaText().length() > 0;
- if (d->control->isReadOnly()) {
- ev->ignore();
- } else {
- d->control->processInputMethodEvent(ev);
- }
- if (!ev->isAccepted())
- QQuickImplicitSizeItem::inputMethodEvent(ev);
-
- if (wasComposing != (d->control->preeditAreaText().length() > 0))
- emit inputMethodComposingChanged();
-}
-
-void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextInput);
-
- if (d->selectByMouse && event->button() == Qt::LeftButton) {
- d->control->commitPreedit();
- int cursor = d->xToPos(event->localPos().x());
- d->control->selectWordAtPos(cursor);
- event->setAccepted(true);
- if (!d->hasPendingTripleClick()) {
- d->tripleClickStartPoint = event->localPos().toPoint();
- d->tripleClickTimer.start();
- }
- } else {
- if (d->sendMouseEventToInputContext(event))
- return;
- QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
- }
-}
-
-void QQuickTextInput::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextInput);
-
- d->pressPos = event->localPos();
-
- if (d->focusOnPress) {
- bool hadActiveFocus = hasActiveFocus();
- forceActiveFocus();
- // re-open input panel on press if already focused
- if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
- openSoftwareInputPanel();
- }
- if (d->selectByMouse) {
- setKeepMouseGrab(false);
- d->selectPressed = true;
- QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
- if (d->hasPendingTripleClick()
- && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
- event->setAccepted(true);
- selectAll();
- return;
- }
- }
-
- if (d->sendMouseEventToInputContext(event))
- return;
-
- bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
- int cursor = d->xToPos(event->localPos().x());
- d->control->moveCursor(cursor, mark);
- event->setAccepted(true);
-}
-
-void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextInput);
-
- if (d->selectPressed) {
- if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
- setKeepMouseGrab(true);
-
- if (d->control->composeMode()) {
- // start selection
- int startPos = d->xToPos(d->pressPos.x());
- int currentPos = d->xToPos(event->localPos().x());
- if (startPos != currentPos)
- d->control->setSelection(startPos, currentPos - startPos);
- } else {
- moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
- }
- event->setAccepted(true);
- } else {
- QQuickImplicitSizeItem::mouseMoveEvent(event);
- }
-}
-
-void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickTextInput);
- if (d->sendMouseEventToInputContext(event))
- return;
- if (d->selectPressed) {
- d->selectPressed = false;
- setKeepMouseGrab(false);
- }
- d->control->processEvent(event);
- if (!event->isAccepted())
- QQuickImplicitSizeItem::mouseReleaseEvent(event);
-}
-
-bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
-{
-#if !defined QT_NO_IM
- if (control->composeMode()) {
- int tmp_cursor = xToPos(event->localPos().x());
- int mousePos = tmp_cursor - control->cursor();
- if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
- if (event->type() == QEvent::MouseButtonRelease) {
- qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
- }
- return true;
- }
- }
-#else
- Q_UNUSED(event);
- Q_UNUSED(eventType)
-#endif
-
- return false;
-}
-
-void QQuickTextInput::mouseUngrabEvent()
-{
- Q_D(QQuickTextInput);
- d->selectPressed = false;
- setKeepMouseGrab(false);
-}
-
-bool QQuickTextInput::event(QEvent* ev)
-{
- Q_D(QQuickTextInput);
- //Anything we don't deal with ourselves, pass to the control
- bool handled = false;
- switch (ev->type()) {
- case QEvent::KeyPress:
- case QEvent::KeyRelease://###Should the control be doing anything with release?
- case QEvent::InputMethod:
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- break;
- default:
- handled = d->control->processEvent(ev);
- }
- if (!handled)
- handled = QQuickImplicitSizeItem::event(ev);
- return handled;
-}
-
-void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
-{
- if (newGeometry.width() != oldGeometry.width()) {
- updateSize();
- updateCursorRectangle();
- }
- QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
-}
-
-int QQuickTextInputPrivate::calculateTextWidth()
-{
- return qRound(control->naturalTextWidth());
-}
-
-void QQuickTextInputPrivate::updateHorizontalScroll()
-{
- Q_Q(QQuickTextInput);
- const int preeditLength = control->preeditAreaText().length();
- const int width = q->width();
- int widthUsed = calculateTextWidth();
-
- if (!autoScroll || widthUsed <= width) {
- QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
- // text fits in br; use hscroll for alignment
- switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
- case Qt::AlignRight:
- hscroll = widthUsed - width;
- break;
- case Qt::AlignHCenter:
- hscroll = (widthUsed - width) / 2;
- break;
- default:
- // Left
- hscroll = 0;
- break;
- }
- } else {
- int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
- if (cix - hscroll >= width) {
- // text doesn't fit, cursor is to the right of br (scroll right)
- hscroll = cix - width;
- } else if (cix - hscroll < 0 && hscroll < widthUsed) {
- // text doesn't fit, cursor is to the left of br (scroll left)
- hscroll = cix;
- } else if (widthUsed - hscroll < width) {
- // text doesn't fit, text document is to the left of br; align
- // right
- hscroll = widthUsed - width;
- }
- if (preeditLength > 0) {
- // check to ensure long pre-edit text doesn't push the cursor
- // off to the left
- cix = qRound(control->cursorToX(
- control->cursor() + qMax(0, control->preeditCursor() - 1)));
- if (cix < hscroll)
- hscroll = cix;
- }
- }
-}
-
-QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
-{
- Q_UNUSED(data);
- Q_D(QQuickTextInput);
-
- QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
- if (node == 0)
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
- d->textNode = node;
-
- if (!d->textLayoutDirty) {
- QSGSimpleRectNode *cursorNode = node->cursorNode();
- if (cursorNode != 0 && !isReadOnly()) {
- QFontMetrics fm = QFontMetrics(d->font);
- // the y offset is there to keep the baseline constant in case we have script changes in the text.
- QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
- offset.rx() += d->control->cursorToX();
-
- QRect br(boundingRect().toRect());
- cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
-
- if (!d->cursorVisible
- || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
- d->hideCursor();
- } else {
- d->showCursor();
- }
- }
- } else {
- node->deleteContent();
- node->setMatrix(QMatrix4x4());
-
- QPoint offset = QPoint(0,0);
- QFontMetrics fm = QFontMetrics(d->font);
- QRect br(boundingRect().toRect());
- if (d->autoScroll) {
- // the y offset is there to keep the baseline constant in case we have script changes in the text.
- offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
- } else {
- offset = QPoint(d->hscroll, 0);
- }
-
- QTextLayout *textLayout = d->control->textLayout();
- if (!textLayout->text().isEmpty()) {
- node->addTextLayout(offset, textLayout, d->color,
- QQuickText::Normal, QColor(),
- d->selectionColor, d->selectedTextColor,
- d->control->selectionStart(),
- d->control->selectionEnd() - 1); // selectionEnd() returns first char after
- // selection
- }
-
- if (!isReadOnly() && d->cursorItem == 0) {
- offset.rx() += d->control->cursorToX();
- node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
- if (!d->cursorVisible
- || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
- d->hideCursor();
- } else {
- d->showCursor();
- }
- }
-
- d->textLayoutDirty = false;
- }
-
- return node;
-}
-
-QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
-{
- Q_D(const QQuickTextInput);
- switch (property) {
- case Qt::ImEnabled:
- return QVariant((bool)(flags() & ItemAcceptsInputMethod));
- case Qt::ImHints:
- return QVariant((int)inputMethodHints());
- case Qt::ImCursorRectangle:
- return cursorRectangle();
- case Qt::ImFont:
- return font();
- case Qt::ImCursorPosition:
- return QVariant(d->control->cursor());
- case Qt::ImSurroundingText:
- if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
- && !d->control->passwordEchoEditing()) {
- return QVariant(displayText());
- } else {
- return QVariant(d->control->realText());
- }
- case Qt::ImCurrentSelection:
- return QVariant(selectedText());
- case Qt::ImMaximumTextLength:
- return QVariant(maxLength());
- case Qt::ImAnchorPosition:
- if (d->control->selectionStart() == d->control->selectionEnd())
- return QVariant(d->control->cursor());
- else if (d->control->selectionStart() == d->control->cursor())
- return QVariant(d->control->selectionEnd());
- else
- return QVariant(d->control->selectionStart());
- default:
- return QVariant();
- }
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::deselect()
-
- Removes active text selection.
-*/
-void QQuickTextInput::deselect()
-{
- Q_D(QQuickTextInput);
- d->control->deselect();
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::selectAll()
-
- Causes all text to be selected.
-*/
-void QQuickTextInput::selectAll()
-{
- Q_D(QQuickTextInput);
- d->control->setSelection(0, d->control->text().length());
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
-
- Returns true if the natural reading direction of the editor text
- found between positions \a start and \a end is right to left.
-*/
-bool QQuickTextInput::isRightToLeft(int start, int end)
-{
- Q_D(QQuickTextInput);
- if (start > end) {
- qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
- return false;
- } else {
- return d->control->text().mid(start, end - start).isRightToLeft();
- }
-}
-
-#ifndef QT_NO_CLIPBOARD
-/*!
- \qmlmethod QtQuick2::TextInput::cut()
-
- Moves the currently selected text to the system clipboard.
-*/
-void QQuickTextInput::cut()
-{
- Q_D(QQuickTextInput);
- d->control->copy();
- d->control->del();
-}
-
-/*!
- \qmlmethod QtQuick2::TextInput::copy()
-
- Copies the currently selected text to the system clipboard.
-*/
-void QQuickTextInput::copy()
-{
- Q_D(QQuickTextInput);
- d->control->copy();
-}
-
-/*!
- \qmlmethod QtQuick2::TextInput::paste()
-
- Replaces the currently selected text by the contents of the system clipboard.
-*/
-void QQuickTextInput::paste()
-{
- Q_D(QQuickTextInput);
- if (!d->control->isReadOnly())
- d->control->paste();
-}
-#endif // QT_NO_CLIPBOARD
-
-/*!
- \qmlmethod void QtQuick2::TextInput::selectWord()
-
- Causes the word closest to the current cursor position to be selected.
-*/
-void QQuickTextInput::selectWord()
-{
- Q_D(QQuickTextInput);
- d->control->selectWordAtPos(d->control->cursor());
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::smooth
-
- This property holds whether the text is smoothly scaled or transformed.
-
- Smooth filtering gives better visual quality, but is slower. If
- the item is displayed at its natural size, this property has no visual or
- performance effect.
-
- \note Generally scaling artifacts are only visible if the item is stationary on
- the screen. A common pattern when animating an item is to disable smooth
- filtering at the beginning of the animation and reenable it at the conclusion.
-*/
-
-/*!
- \qmlproperty string QtQuick2::TextInput::passwordCharacter
-
- This is the character displayed when echoMode is set to Password or
- PasswordEchoOnEdit. By default it is an asterisk.
-
- If this property is set to a string with more than one character,
- the first character is used. If the string is empty, the value
- is ignored and the property is not set.
-*/
-QString QQuickTextInput::passwordCharacter() const
-{
- Q_D(const QQuickTextInput);
- return QString(d->control->passwordCharacter());
-}
-
-void QQuickTextInput::setPasswordCharacter(const QString &str)
-{
- Q_D(QQuickTextInput);
- if (str.length() < 1)
- return;
- d->control->setPasswordCharacter(str.constData()[0]);
- EchoMode echoMode_ = echoMode();
- if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
- updateSize();
- }
- emit passwordCharacterChanged();
-}
-
-/*!
- \qmlproperty string QtQuick2::TextInput::displayText
-
- This is the text displayed in the TextInput.
-
- If \l echoMode is set to TextInput::Normal, this holds the
- same value as the TextInput::text property. Otherwise,
- this property holds the text visible to the user, while
- the \l text property holds the actual entered text.
-*/
-QString QQuickTextInput::displayText() const
-{
- Q_D(const QQuickTextInput);
- return d->control->displayText();
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::selectByMouse
-
- Defaults to false.
-
- If true, the user can use the mouse to select text in some
- platform-specific way. Note that for some platforms this may
- not be an appropriate interaction (eg. may conflict with how
- the text needs to behave inside a Flickable.
-*/
-bool QQuickTextInput::selectByMouse() const
-{
- Q_D(const QQuickTextInput);
- return d->selectByMouse;
-}
-
-void QQuickTextInput::setSelectByMouse(bool on)
-{
- Q_D(QQuickTextInput);
- if (d->selectByMouse != on) {
- d->selectByMouse = on;
- emit selectByMouseChanged(on);
- }
-}
-
-/*!
- \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
-
- Specifies how text should be selected using a mouse.
-
- \list
- \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
- \o TextInput.SelectWords - The selection is updated with whole words.
- \endlist
-
- This property only applies when \l selectByMouse is true.
-*/
-
-QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
-{
- Q_D(const QQuickTextInput);
- return d->mouseSelectionMode;
-}
-
-void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
-{
- Q_D(QQuickTextInput);
- if (d->mouseSelectionMode != mode) {
- d->mouseSelectionMode = mode;
- emit mouseSelectionModeChanged(mode);
- }
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::canPaste
-
- Returns true if the TextInput is writable and the content of the clipboard is
- suitable for pasting into the TextEdit.
-*/
-bool QQuickTextInput::canPaste() const
-{
- Q_D(const QQuickTextInput);
- return d->canPaste;
-}
-
-void QQuickTextInput::moveCursorSelection(int position)
-{
- Q_D(QQuickTextInput);
- d->control->moveCursor(position, true);
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
-
- Moves the cursor to \a position and updates the selection according to the optional \a mode
- parameter. (To only move the cursor, set the \l cursorPosition property.)
-
- When this method is called it additionally sets either the
- selectionStart or the selectionEnd (whichever was at the previous cursor position)
- to the specified position. This allows you to easily extend and contract the selected
- text range.
-
- The selection mode specifies whether the selection is updated on a per character or a per word
- basis. If not specified the selection mode will default to TextInput.SelectCharacters.
-
- \list
- \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
- the previous cursor position) to the specified position.
- \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
- words between the specified position and the previous cursor position. Words partially in the
- range are included.
- \endlist
-
- For example, take this sequence of calls:
-
- \code
- cursorPosition = 5
- moveCursorSelection(9, TextInput.SelectCharacters)
- moveCursorSelection(7, TextInput.SelectCharacters)
- \endcode
-
- This moves the cursor to position 5, extend the selection end from 5 to 9
- and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
- selected (the 6th and 7th characters).
-
- The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
- before or on position 5 and extend the selection end to a word boundary on or past position 9.
-*/
-void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
-{
- Q_D(QQuickTextInput);
-
- if (mode == SelectCharacters) {
- d->control->moveCursor(pos, true);
- } else if (pos != d->control->cursor()){
- const int cursor = d->control->cursor();
- int anchor;
- if (!d->control->hasSelectedText())
- anchor = d->control->cursor();
- else if (d->control->selectionStart() == d->control->cursor())
- anchor = d->control->selectionEnd();
- else
- anchor = d->control->selectionStart();
-
- if (anchor < pos || (anchor == pos && cursor < pos)) {
- const QString text = d->control->text();
- QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
- finder.setPosition(anchor);
-
- const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
- if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
- || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
- finder.toPreviousBoundary();
- }
- anchor = finder.position() != -1 ? finder.position() : 0;
-
- finder.setPosition(pos);
- if (pos > 0 && !finder.boundaryReasons())
- finder.toNextBoundary();
- const int cursor = finder.position() != -1 ? finder.position() : text.length();
-
- d->control->setSelection(anchor, cursor - anchor);
- } else if (anchor > pos || (anchor == pos && cursor > pos)) {
- const QString text = d->control->text();
- QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
- finder.setPosition(anchor);
-
- const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
- if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
- || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
- finder.toNextBoundary();
- }
-
- anchor = finder.position() != -1 ? finder.position() : text.length();
-
- finder.setPosition(pos);
- if (pos < text.length() && !finder.boundaryReasons())
- finder.toPreviousBoundary();
- const int cursor = finder.position() != -1 ? finder.position() : 0;
-
- d->control->setSelection(anchor, cursor - anchor);
- }
- }
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
-
- Opens software input panels like virtual keyboards for typing, useful for
- customizing when you want the input keyboard to be shown and hidden in
- your application.
-
- By default the opening of input panels follows the platform style. Input panels are
- always closed if no editor has active focus.
-
- You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
- and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
- the behavior you want.
-
- Only relevant on platforms, which provide virtual keyboards.
-
- \qml
- import QtQuick 1.0
- TextInput {
- id: textInput
- text: "Hello world!"
- activeFocusOnPress: false
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (!textInput.activeFocus) {
- textInput.forceActiveFocus()
- textInput.openSoftwareInputPanel();
- } else {
- textInput.focus = false;
- }
- }
- onPressAndHold: textInput.closeSoftwareInputPanel();
- }
- }
- \endqml
-*/
-void QQuickTextInput::openSoftwareInputPanel()
-{
- if (qGuiApp)
- qGuiApp->inputPanel()->show();
-}
-
-/*!
- \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
-
- Closes a software input panel like a virtual keyboard shown on the screen, useful
- for customizing when you want the input keyboard to be shown and hidden in
- your application.
-
- By default the opening of input panels follows the platform style. Input panels are
- always closed if no editor has active focus.
-
- You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
- and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
- the behavior you want.
-
- Only relevant on platforms, which provide virtual keyboards.
-
- \qml
- import QtQuick 1.0
- TextInput {
- id: textInput
- text: "Hello world!"
- activeFocusOnPress: false
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (!textInput.activeFocus) {
- textInput.forceActiveFocus();
- textInput.openSoftwareInputPanel();
- } else {
- textInput.focus = false;
- }
- }
- onPressAndHold: textInput.closeSoftwareInputPanel();
- }
- }
- \endqml
-*/
-void QQuickTextInput::closeSoftwareInputPanel()
-{
- if (qGuiApp)
- qGuiApp->inputPanel()->hide();
-}
-
-void QQuickTextInput::focusInEvent(QFocusEvent *event)
-{
- Q_D(const QQuickTextInput);
- if (d->focusOnPress && !isReadOnly())
- openSoftwareInputPanel();
- QQuickImplicitSizeItem::focusInEvent(event);
-}
-
-void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
-{
- Q_D(QQuickTextInput);
- if (change == ItemActiveFocusHasChanged) {
- bool hasFocus = value.boolValue;
- d->focused = hasFocus;
- setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
- if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
- d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
- if (!hasFocus)
- d->control->deselect();
- }
- QQuickItem::itemChange(change, value);
-}
-
-/*!
- \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
-
-
- This property holds whether the TextInput has partial text input from an
- input method.
-
- While it is composing an input method may rely on mouse or key events from
- the TextInput to edit or commit the partial text. This property can be
- used to determine when to disable events handlers that may interfere with
- the correct operation of an input method.
-*/
-bool QQuickTextInput::isInputMethodComposing() const
-{
- Q_D(const QQuickTextInput);
- return d->control->preeditAreaText().length() > 0;
-}
-
-void QQuickTextInputPrivate::init()
-{
- Q_Q(QQuickTextInput);
- control->setParent(q);//Now mandatory due to accessibility changes
- control->setCursorWidth(1);
- control->setPasswordCharacter(QLatin1Char('*'));
- q->setSmooth(smooth);
- q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setFlag(QQuickItem::ItemAcceptsInputMethod);
- q->setFlag(QQuickItem::ItemHasContents);
- q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(cursorPosChanged()));
- q->connect(control, SIGNAL(selectionChanged()),
- q, SLOT(selectionChanged()));
- q->connect(control, SIGNAL(textChanged(QString)),
- q, SLOT(q_textChanged()));
- q->connect(control, SIGNAL(accepted()),
- q, SIGNAL(accepted()));
- q->connect(control, SIGNAL(updateNeeded(QRect)),
- q, SLOT(updateRect(QRect)));
-#ifndef QT_NO_CLIPBOARD
- q->connect(q, SIGNAL(readOnlyChanged(bool)),
- q, SLOT(q_canPasteChanged()));
- q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
- q, SLOT(q_canPasteChanged()));
- canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
-#endif // QT_NO_CLIPBOARD
- q->connect(control, SIGNAL(updateMicroFocus()),
- q, SLOT(updateCursorRectangle()));
- q->connect(control, SIGNAL(displayTextChanged(QString)),
- q, SLOT(updateRect()));
- q->updateSize();
- imHints &= ~Qt::ImhMultiLine;
- oldValidity = control->hasAcceptableInput();
- lastSelectionStart = 0;
- lastSelectionEnd = 0;
- QPalette p = control->palette();
- selectedTextColor = p.color(QPalette::HighlightedText);
- selectionColor = p.color(QPalette::Highlight);
- determineHorizontalAlignment();
-
- if (!qmlDisableDistanceField()) {
- QTextOption option = control->textLayout()->textOption();
- option.setUseDesignMetrics(true);
- control->textLayout()->setTextOption(option);
- }
-}
-
-void QQuickTextInput::cursorPosChanged()
-{
- Q_D(QQuickTextInput);
- updateCursorRectangle();
- emit cursorPositionChanged();
- // XXX todo - not in 4.8?
-#if 0
- d->control->resetCursorBlinkTimer();
-#endif
-
- if (!d->control->hasSelectedText()) {
- if (d->lastSelectionStart != d->control->cursor()) {
- d->lastSelectionStart = d->control->cursor();
- emit selectionStartChanged();
- }
- if (d->lastSelectionEnd != d->control->cursor()) {
- d->lastSelectionEnd = d->control->cursor();
- emit selectionEndChanged();
- }
- }
-}
-
-void QQuickTextInput::updateCursorRectangle()
-{
- Q_D(QQuickTextInput);
- d->determineHorizontalAlignment();
- d->updateHorizontalScroll();
- updateRect();//TODO: Only update rect between pos's
- updateMicroFocus();
- emit cursorRectangleChanged();
- if (d->cursorItem)
- d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
-}
-
-void QQuickTextInput::selectionChanged()
-{
- Q_D(QQuickTextInput);
- updateRect();//TODO: Only update rect in selection
- emit selectedTextChanged();
-
- if (d->lastSelectionStart != d->control->selectionStart()) {
- d->lastSelectionStart = d->control->selectionStart();
- if (d->lastSelectionStart == -1)
- d->lastSelectionStart = d->control->cursor();
- emit selectionStartChanged();
- }
- if (d->lastSelectionEnd != d->control->selectionEnd()) {
- d->lastSelectionEnd = d->control->selectionEnd();
- if (d->lastSelectionEnd == -1)
- d->lastSelectionEnd = d->control->cursor();
- emit selectionEndChanged();
- }
-}
-
-void QQuickTextInput::q_textChanged()
-{
- Q_D(QQuickTextInput);
- emit textChanged();
- emit displayTextChanged();
- updateSize();
- d->determineHorizontalAlignment();
- d->updateHorizontalScroll();
- updateMicroFocus();
- if (hasAcceptableInput() != d->oldValidity) {
- d->oldValidity = hasAcceptableInput();
- emit acceptableInputChanged();
- }
-}
-
-void QQuickTextInputPrivate::showCursor()
-{
- if (textNode != 0 && textNode->cursorNode() != 0)
- textNode->cursorNode()->setColor(color);
-}
-
-void QQuickTextInputPrivate::hideCursor()
-{
- if (textNode != 0 && textNode->cursorNode() != 0)
- textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
-}
-
-void QQuickTextInput::updateRect(const QRect &r)
-{
- Q_D(QQuickTextInput);
- if (!isComponentComplete())
- return;
-
- if (r.isEmpty()) {
- d->textLayoutDirty = true;
- }
-
- update();
-}
-
-QRectF QQuickTextInput::boundingRect() const
-{
- Q_D(const QQuickTextInput);
- QRectF r = QQuickImplicitSizeItem::boundingRect();
-
- int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
-
- // Could include font max left/right bearings to either side of rectangle.
-
- r.setRight(r.right() + cursorWidth);
- return r;
-}
-
-void QQuickTextInput::updateSize(bool needsRedraw)
-{
- Q_D(QQuickTextInput);
- int w = width();
- int h = height();
- setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
- if (w==width() && h==height() && needsRedraw)
- update();
-}
-
-void QQuickTextInput::q_canPasteChanged()
-{
- Q_D(QQuickTextInput);
- bool old = d->canPaste;
-#ifndef QT_NO_CLIPBOARD
- d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
-#endif
- if (d->canPaste != old)
- emit canPasteChanged();
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/items/qquicktextinput_p.h b/src/declarative/items/qquicktextinput_p.h
deleted file mode 100644
index 493788ec84..0000000000
--- a/src/declarative/items/qquicktextinput_p.h
+++ /dev/null
@@ -1,302 +0,0 @@
-// Commit: 2f173e4945dd8414636c1061acfaf9c2d8b718d8
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKTEXTINPUT_P_H
-#define QQUICKTEXTINPUT_P_H
-
-#include "qquickimplicitsizeitem_p.h"
-#include <QtGui/qvalidator.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickTextInputPrivate;
-class QValidator;
-class Q_AUTOTEST_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
-{
- Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(EchoMode)
- Q_ENUMS(SelectionMode)
-
- Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
- Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
- Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
- Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
- Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
-
- Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
- Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
- Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
- Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
- Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
- Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
- Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
- Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
-
- Q_PROPERTY(int maximumLength READ maxLength WRITE setMaxLength NOTIFY maximumLengthChanged)
-#ifndef QT_NO_VALIDATOR
- Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
-#endif
- Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
- Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ imHints WRITE setIMHints)
-
- Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
- Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
- Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
- Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged)
- Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged)
- Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged)
- Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
- Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
- Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
- Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
-
-public:
- QQuickTextInput(QQuickItem * parent=0);
- ~QQuickTextInput();
-
- enum EchoMode {//To match QLineEdit::EchoMode
- Normal,
- NoEcho,
- Password,
- PasswordEchoOnEdit
- };
-
- enum HAlignment {
- AlignLeft = Qt::AlignLeft,
- AlignRight = Qt::AlignRight,
- AlignHCenter = Qt::AlignHCenter
- };
-
- enum SelectionMode {
- SelectCharacters,
- SelectWords
- };
-
- enum CursorPosition {
- CursorBetweenCharacters,
- CursorOnCharacter
- };
-
- //Auxilliary functions needed to control the TextInput from QML
- Q_INVOKABLE int positionAt(int x) const;
- Q_INVOKABLE int positionAt(int x, CursorPosition position) const;
- Q_INVOKABLE QRectF positionToRectangle(int pos) const;
- Q_INVOKABLE void moveCursorSelection(int pos);
- Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
-
- Q_INVOKABLE void openSoftwareInputPanel();
- Q_INVOKABLE void closeSoftwareInputPanel();
-
- QString text() const;
- void setText(const QString &);
-
- QFont font() const;
- void setFont(const QFont &font);
-
- QColor color() const;
- void setColor(const QColor &c);
-
- QColor selectionColor() const;
- void setSelectionColor(const QColor &c);
-
- QColor selectedTextColor() const;
- void setSelectedTextColor(const QColor &c);
-
- HAlignment hAlign() const;
- void setHAlign(HAlignment align);
- void resetHAlign();
- HAlignment effectiveHAlign() const;
-
- bool isReadOnly() const;
- void setReadOnly(bool);
-
- bool isCursorVisible() const;
- void setCursorVisible(bool on);
-
- int cursorPosition() const;
- void setCursorPosition(int cp);
-
- QRect cursorRectangle() const;
-
- int selectionStart() const;
- int selectionEnd() const;
-
- QString selectedText() const;
-
- int maxLength() const;
- void setMaxLength(int ml);
-
-#ifndef QT_NO_VALIDATOR
- QValidator * validator() const;
- void setValidator(QValidator* v);
-#endif
- QString inputMask() const;
- void setInputMask(const QString &im);
-
- EchoMode echoMode() const;
- void setEchoMode(EchoMode echo);
-
- QString passwordCharacter() const;
- void setPasswordCharacter(const QString &str);
-
- QString displayText() const;
-
- QDeclarativeComponent* cursorDelegate() const;
- void setCursorDelegate(QDeclarativeComponent*);
-
- bool focusOnPress() const;
- void setFocusOnPress(bool);
-
- bool autoScroll() const;
- void setAutoScroll(bool);
-
- bool selectByMouse() const;
- void setSelectByMouse(bool);
-
- SelectionMode mouseSelectionMode() const;
- void setMouseSelectionMode(SelectionMode mode);
-
- bool hasAcceptableInput() const;
-
- QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
-
- QRectF boundingRect() const;
- bool canPaste() const;
-
- bool isInputMethodComposing() const;
-
- Qt::InputMethodHints imHints() const;
- void setIMHints(Qt::InputMethodHints hints);
-
-Q_SIGNALS:
- void textChanged();
- void cursorPositionChanged();
- void cursorRectangleChanged();
- void selectionStartChanged();
- void selectionEndChanged();
- void selectedTextChanged();
- void accepted();
- void acceptableInputChanged();
- void colorChanged(const QColor &color);
- void selectionColorChanged(const QColor &color);
- void selectedTextColorChanged(const QColor &color);
- void fontChanged(const QFont &font);
- void horizontalAlignmentChanged(HAlignment alignment);
- void readOnlyChanged(bool isReadOnly);
- void cursorVisibleChanged(bool isCursorVisible);
- void cursorDelegateChanged();
- void maximumLengthChanged(int maximumLength);
- void validatorChanged();
- void inputMaskChanged(const QString &inputMask);
- void echoModeChanged(EchoMode echoMode);
- void passwordCharacterChanged();
- void displayTextChanged();
- void activeFocusOnPressChanged(bool activeFocusOnPress);
- void autoScrollChanged(bool autoScroll);
- void selectByMouseChanged(bool selectByMouse);
- void mouseSelectionModeChanged(SelectionMode mode);
- void canPasteChanged();
- void inputMethodComposingChanged();
- void effectiveHorizontalAlignmentChanged();
-
-protected:
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
-
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- void keyPressEvent(QKeyEvent* ev);
- void inputMethodEvent(QInputMethodEvent *);
- void mouseUngrabEvent();
- bool event(QEvent *e);
- void focusInEvent(QFocusEvent *event);
- virtual void itemChange(ItemChange, const ItemChangeData &);
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
-
-public Q_SLOTS:
- void selectAll();
- void selectWord();
- void select(int start, int end);
- void deselect();
- bool isRightToLeft(int start, int end);
-#ifndef QT_NO_CLIPBOARD
- void cut();
- void copy();
- void paste();
-#endif
-
-private Q_SLOTS:
- void updateSize(bool needsRedraw = true);
- void q_textChanged();
- void selectionChanged();
- void createCursor();
- void cursorPosChanged();
- void updateCursorRectangle();
- void updateRect(const QRect &r = QRect());
- void q_canPasteChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickTextInput)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickTextInput)
-#ifndef QT_NO_VALIDATOR
-QML_DECLARE_TYPE(QValidator)
-QML_DECLARE_TYPE(QIntValidator)
-QML_DECLARE_TYPE(QDoubleValidator)
-QML_DECLARE_TYPE(QRegExpValidator)
-#endif
-
-QT_END_HEADER
-
-#endif // QQUICKTEXTINPUT_P_H
diff --git a/src/declarative/items/qquicktextnode.cpp b/src/declarative/items/qquicktextnode.cpp
deleted file mode 100644
index 56c3b54cd7..0000000000
--- a/src/declarative/items/qquicktextnode.cpp
+++ /dev/null
@@ -1,1344 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquicktextnode_p.h"
-#include "qsgsimplerectnode.h"
-#include <private/qsgadaptationlayer_p.h>
-#include <private/qsgdistancefieldglyphnode_p.h>
-
-#include <private/qsgcontext_p.h>
-
-#include <QtCore/qpoint.h>
-#include <qmath.h>
-#include <qtextdocument.h>
-#include <qtextlayout.h>
-#include <qabstracttextdocumentlayout.h>
-#include <qxmlstream.h>
-#include <qrawfont.h>
-#include <qtexttable.h>
-#include <qtextlist.h>
-#include <private/qdeclarativestyledtext_p.h>
-#include <private/qfont_p.h>
-#include <private/qfontengine_p.h>
-#include <private/qrawfont_p.h>
-#include <private/qtextimagehandler_p.h>
-#include <private/qtextdocumentlayout_p.h>
-#include <qhash.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- Creates an empty QQuickTextNode
-*/
-QQuickTextNode::QQuickTextNode(QSGContext *context)
- : m_context(context), m_cursorNode(0)
-{
-#if defined(QML_RUNTIME_TESTING)
- description = QLatin1String("text");
-#endif
-}
-
-QQuickTextNode::~QQuickTextNode()
-{
- qDeleteAll(m_textures);
-}
-
-#if 0
-void QQuickTextNode::setColor(const QColor &color)
-{
- if (m_usePixmapCache) {
- setUpdateFlag(UpdateNodes);
- } else {
- for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
- if (childNode->subType() == GlyphNodeSubType) {
- QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
- if (glyphNode->color() == m_color)
- glyphNode->setColor(color);
- } else if (childNode->subType() == SolidRectNodeSubType) {
- QSGSimpleRectNode *solidRectNode = static_cast<QSGSimpleRectNode *>(childNode);
- if (solidRectNode->color() == m_color)
- solidRectNode->setColor(color);
- }
- }
- }
- m_color = color;
-}
-
-void QQuickTextNode::setStyleColor(const QColor &styleColor)
-{
- if (m_textStyle != QQuickTextNode::NormalTextStyle) {
- if (m_usePixmapCache) {
- setUpdateFlag(UpdateNodes);
- } else {
- for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
- if (childNode->subType() == GlyphNodeSubType) {
- QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
- if (glyphNode->color() == m_styleColor)
- glyphNode->setColor(styleColor);
- } else if (childNode->subType() == SolidRectNodeSubType) {
- QSGSimpleRectNode *solidRectNode = static_cast<QSGSimpleRectNode *>(childNode);
- if (solidRectNode->color() == m_styleColor)
- solidRectNode->setColor(styleColor);
- }
- }
- }
- }
- m_styleColor = styleColor;
-}
-#endif
-
-QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
- QQuickText::TextStyle style, const QColor &styleColor,
- QSGNode *parentNode)
-{
- QSGGlyphNode *node = m_context->createGlyphNode();
- node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
- node->setStyle(style);
- node->setStyleColor(styleColor);
- node->setColor(color);
- node->update();
-
- /* We flag the geometry as static, but we never call markVertexDataDirty
- or markIndexDataDirty on them. This is because all text nodes are
- discarded when a change occurs. If we start appending/removing from
- existing geometry, then we also need to start marking the geometry as
- dirty.
- */
- node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
- node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
-
- if (parentNode == 0)
- parentNode = this;
- parentNode->appendChildNode(node);
-
- return node;
-}
-
-void QQuickTextNode::setCursor(const QRectF &rect, const QColor &color)
-{
- if (m_cursorNode != 0)
- delete m_cursorNode;
-
- m_cursorNode = new QSGSimpleRectNode(rect, color);
- appendChildNode(m_cursorNode);
-}
-
-namespace {
-
- struct BinaryTreeNode {
- enum SelectionState {
- Unselected,
- Selected
- };
-
- BinaryTreeNode()
- : selectionState(Unselected)
- , clipNode(0)
- , decorations(QQuickTextNode::NoDecoration)
- , ascent(0.0)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
-
- }
-
- BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a)
- : boundingRect(brect)
- , selectionState(selState)
- , clipNode(0)
- , decorations(QQuickTextNode::NoDecoration)
- , image(i)
- , ascent(a)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
- }
-
- BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
- const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc,
- const QPointF &pos, qreal a)
- : glyphRun(g)
- , boundingRect(brect)
- , selectionState(selState)
- , clipNode(0)
- , decorations(decs)
- , color(c)
- , backgroundColor(bc)
- , position(pos)
- , ascent(a)
- , leftChildIndex(-1)
- , rightChildIndex(-1)
- {
- }
-
- QGlyphRun glyphRun;
- QRectF boundingRect;
- SelectionState selectionState;
- QSGClipNode *clipNode;
- QQuickTextNode::Decorations decorations;
- QColor color;
- QColor backgroundColor;
- QPointF position;
- QImage image;
- qreal ascent;
-
- int leftChildIndex;
- int rightChildIndex;
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const QRectF &rect,
- const QImage &image,
- qreal ascent,
- SelectionState selectionState)
- {
- insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent));
- }
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const QGlyphRun &glyphRun,
- SelectionState selectionState,
- const QColor &textColor,
- const QColor &backgroundColor,
- const QPointF &position)
- {
- QRectF searchRect = glyphRun.boundingRect();
- searchRect.translate(position);
-
- if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
- return;
-
- QQuickTextNode::Decorations decorations = QQuickTextNode::NoDecoration;
- decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration);
- decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration);
- decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration);
- decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
-
- qreal ascent = glyphRun.rawFont().ascent();
- insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
- textColor, backgroundColor, position, ascent));
- }
-
- static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
- const BinaryTreeNode &binaryTreeNode)
- {
- int newIndex = binaryTree->size();
- binaryTree->append(binaryTreeNode);
- if (newIndex == 0)
- return;
-
- int searchIndex = 0;
- forever {
- BinaryTreeNode *node = binaryTree->data() + searchIndex;
- if (binaryTreeNode.boundingRect.left() < node->boundingRect.left()) {
- if (node->leftChildIndex < 0) {
- node->leftChildIndex = newIndex;
- break;
- } else {
- searchIndex = node->leftChildIndex;
- }
- } else {
- if (node->rightChildIndex < 0) {
- node->rightChildIndex = newIndex;
- break;
- } else {
- searchIndex = node->rightChildIndex;
- }
- }
- }
- }
-
- static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
- QVarLengthArray<int> *sortedIndexes,
- int currentIndex = 0)
- {
- Q_ASSERT(currentIndex < binaryTree.size());
-
- const BinaryTreeNode *node = binaryTree.data() + currentIndex;
- if (node->leftChildIndex >= 0)
- inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
-
- sortedIndexes->append(currentIndex);
-
- if (node->rightChildIndex >= 0)
- inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
- }
- };
-
- // Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
- // and rectangle nodes to represent the text, decorations and selection. Will try to minimize
- // number of nodes, and join decorations in neighbouring items
- class SelectionEngine
- {
- public:
- SelectionEngine() : m_hasSelection(false) {}
-
- QTextLine currentLine() const { return m_currentLine; }
-
- void setCurrentLine(const QTextLine &currentLine)
- {
- if (m_currentLine.isValid())
- processCurrentLine();
-
- m_currentLine = currentLine;
- }
-
- void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle,
- const QBrush &borderBrush);
- void addFrameDecorations(QTextDocument *document, QTextFrame *frame);
- void addImage(const QRectF &rect, const QImage &image, qreal ascent,
- BinaryTreeNode::SelectionState selectionState,
- QTextFrameFormat::Position layoutPosition);
- void addTextObject(const QPointF &position, const QTextCharFormat &format,
- BinaryTreeNode::SelectionState selectionState,
- QTextDocument *textDocument, int pos,
- QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
- void addSelectedGlyphs(const QGlyphRun &glyphRun);
- void addUnselectedGlyphs(const QGlyphRun &glyphRun);
- void addGlyphsInRange(int rangeStart, int rangeEnd,
- const QColor &color, const QColor &backgroundColor,
- int selectionStart, int selectionEnd);
- void addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
- int start, int end,
- int selectionStart, int selectionEnd);
-
- void addToSceneGraph(QQuickTextNode *parent,
- QQuickText::TextStyle style = QQuickText::Normal,
- const QColor &styleColor = QColor());
-
- void setSelectionColor(const QColor &selectionColor)
- {
- m_selectionColor = selectionColor;
- }
-
- void setSelectedTextColor(const QColor &selectedTextColor)
- {
- m_selectedTextColor = selectedTextColor;
- }
-
- void setTextColor(const QColor &textColor)
- {
- m_textColor = textColor;
- }
-
- void setPosition(const QPointF &position)
- {
- m_position = position;
- }
-
- private:
- struct TextDecoration
- {
- TextDecoration() : selectionState(BinaryTreeNode::Unselected) {}
- TextDecoration(const BinaryTreeNode::SelectionState &s,
- const QRectF &r,
- const QColor &c)
- : selectionState(s)
- , rect(r)
- , color(c)
- {
- }
-
- BinaryTreeNode::SelectionState selectionState;
- QRectF rect;
- QColor color;
- };
-
- void processCurrentLine();
- void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
- qreal offset, qreal thickness);
-
- QColor m_selectionColor;
- QColor m_textColor;
- QColor m_backgroundColor;
- QColor m_selectedTextColor;
- QPointF m_position;
-
- QTextLine m_currentLine;
- bool m_hasSelection;
-
- QList<QPair<QRectF, QColor> > m_backgrounds;
- QList<QRectF> m_selectionRects;
- QVarLengthArray<BinaryTreeNode> m_currentLineTree;
-
- QList<TextDecoration> m_lines;
- QVector<BinaryTreeNode> m_processedNodes;
-
- QList<QPair<QRectF, QImage> > m_images;
- };
-
- void SelectionEngine::addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
- qreal offset, qreal thickness)
- {
- for (int i=0; i<textDecorations.size(); ++i) {
- TextDecoration textDecoration = textDecorations.at(i);
-
- {
- QRectF &rect = textDecoration.rect;
- rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
- rect.setHeight(thickness);
- }
-
- m_lines.append(textDecoration);
- }
- }
-
- void SelectionEngine::processCurrentLine()
- {
- // No glyphs, do nothing
- if (m_currentLineTree.isEmpty())
- return;
-
- // 1. Go through current line and get correct decoration position for each node based on
- // neighbouring decorations. Add decoration to global list
- // 2. Create clip nodes for all selected text. Try to merge as many as possible within
- // the line.
- // 3. Add QRects to a list of selection rects.
- // 4. Add all nodes to a global processed list
- QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
- BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);
-
- Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());
-
- BinaryTreeNode::SelectionState currentSelectionState = BinaryTreeNode::Unselected;
- QRectF currentRect;
-
- QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
- qreal underlineOffset = 0.0;
- qreal underlineThickness = 0.0;
-
- qreal overlineOffset = 0.0;
- qreal overlineThickness = 0.0;
-
- qreal strikeOutOffset = 0.0;
- qreal strikeOutThickness = 0.0;
-
- QRectF decorationRect = currentRect;
-
- QColor lastColor;
- QColor lastBackgroundColor;
-
- QVarLengthArray<TextDecoration> pendingUnderlines;
- QVarLengthArray<TextDecoration> pendingOverlines;
- QVarLengthArray<TextDecoration> pendingStrikeOuts;
- if (!sortedIndexes.isEmpty()) {
- QSGClipNode *currentClipNode = m_hasSelection ? new QSGClipNode : 0;
- bool currentClipNodeUsed = false;
- for (int i=0; i<=sortedIndexes.size(); ++i) {
- BinaryTreeNode *node = 0;
- if (i < sortedIndexes.size()) {
- int sortedIndex = sortedIndexes.at(i);
- Q_ASSERT(sortedIndex < m_currentLineTree.size());
-
- node = m_currentLineTree.data() + sortedIndex;
- }
-
- if (i == 0)
- currentSelectionState = node->selectionState;
-
- // Update decorations
- if (currentDecorations != QQuickTextNode::NoDecoration) {
- decorationRect.setY(m_position.y() + m_currentLine.y());
- decorationRect.setHeight(m_currentLine.height());
-
- if (node != 0)
- decorationRect.setRight(node->boundingRect.left());
-
- TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
- if (currentDecorations & QQuickTextNode::Underline)
- pendingUnderlines.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::Overline)
- pendingOverlines.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::StrikeOut)
- pendingStrikeOuts.append(textDecoration);
-
- if (currentDecorations & QQuickTextNode::Background)
- m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
- }
-
- // If we've reached an unselected node from a selected node, we add the
- // selection rect to the graph, and we add decoration every time the
- // selection state changes, because that means the text color changes
- if (node == 0 || node->selectionState != currentSelectionState) {
- if (node != 0)
- currentRect.setRight(node->boundingRect.left());
- currentRect.setY(m_position.y() + m_currentLine.y());
- currentRect.setHeight(m_currentLine.height());
-
- // Draw selection all the way up to the left edge of the unselected item
- if (currentSelectionState == BinaryTreeNode::Selected)
- m_selectionRects.append(currentRect);
-
- if (currentClipNode != 0) {
- if (!currentClipNodeUsed) {
- delete currentClipNode;
- } else {
- currentClipNode->setIsRectangular(true);
- currentClipNode->setClipRect(currentRect);
- }
- }
-
- if (node != 0 && m_hasSelection)
- currentClipNode = new QSGClipNode;
- else
- currentClipNode = 0;
- currentClipNodeUsed = false;
-
- if (node != 0) {
- currentSelectionState = node->selectionState;
- currentRect = node->boundingRect;
-
- // Make sure currentRect is valid, otherwise the unite won't work
- if (currentRect.isNull())
- currentRect.setSize(QSizeF(1, 1));
- }
- } else {
- if (currentRect.isNull())
- currentRect = node->boundingRect;
- else
- currentRect = currentRect.united(node->boundingRect);
- }
-
- if (node != 0) {
- node->clipNode = currentClipNode;
- currentClipNodeUsed = true;
-
- decorationRect = node->boundingRect;
-
- // If previous item(s) had underline and current does not, then we add the
- // pending lines to the lists and likewise for overlines and strikeouts
- if (!pendingUnderlines.isEmpty()
- && !(node->decorations & QQuickTextNode::Underline)) {
- addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
-
- pendingUnderlines.clear();
-
- underlineOffset = 0.0;
- underlineThickness = 0.0;
- }
-
- // ### Add pending when overlineOffset/thickness changes to minimize number of
- // nodes
- if (!pendingOverlines.isEmpty()) {
- addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
-
- pendingOverlines.clear();
-
- overlineOffset = 0.0;
- overlineThickness = 0.0;
- }
-
- // ### Add pending when overlineOffset/thickness changes to minimize number of
- // nodes
- if (!pendingStrikeOuts.isEmpty()) {
- addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
-
- pendingStrikeOuts.clear();
-
- strikeOutOffset = 0.0;
- strikeOutThickness = 0.0;
- }
-
- // Merge current values with previous. Prefer greatest thickness
- QRawFont rawFont = node->glyphRun.rawFont();
- if (node->decorations & QQuickTextNode::Underline) {
- if (rawFont.lineThickness() > underlineThickness) {
- underlineThickness = rawFont.lineThickness();
- underlineOffset = rawFont.underlinePosition();
- }
- }
-
- if (node->decorations & QQuickTextNode::Overline) {
- overlineOffset = -rawFont.ascent();
- overlineThickness = rawFont.lineThickness();
- }
-
- if (node->decorations & QQuickTextNode::StrikeOut) {
- strikeOutThickness = rawFont.lineThickness();
- strikeOutOffset = rawFont.ascent() / -3.0;
- }
-
- currentDecorations = node->decorations;
- lastColor = node->color;
- lastBackgroundColor = node->backgroundColor;
- m_processedNodes.append(*node);
- }
- }
-
- if (!pendingUnderlines.isEmpty())
- addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
-
- if (!pendingOverlines.isEmpty())
- addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
-
- if (!pendingStrikeOuts.isEmpty())
- addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
- }
-
- m_currentLineTree.clear();
- m_currentLine = QTextLine();
- m_hasSelection = false;
- }
-
- void SelectionEngine::addImage(const QRectF &rect, const QImage &image, qreal ascent,
- BinaryTreeNode::SelectionState selectionState,
- QTextFrameFormat::Position layoutPosition)
- {
- QRectF searchRect = rect;
- if (layoutPosition == QTextFrameFormat::InFlow) {
- if (m_currentLineTree.isEmpty()) {
- searchRect.moveTopLeft(m_position);
- } else {
- const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1;
- if (lastNode->glyphRun.isRightToLeft()) {
- QPointF lastPos = lastNode->boundingRect.topLeft();
- searchRect.moveTopRight(lastPos - QPointF(0, ascent));
- } else {
- QPointF lastPos = lastNode->boundingRect.topRight();
- searchRect.moveTopLeft(lastPos - QPointF(0, ascent));
- }
- }
- }
-
- BinaryTreeNode::insert(&m_currentLineTree, searchRect, image, ascent, selectionState);
- }
-
- void SelectionEngine::addTextObject(const QPointF &position, const QTextCharFormat &format,
- BinaryTreeNode::SelectionState selectionState,
- QTextDocument *textDocument, int pos,
- QTextFrameFormat::Position layoutPosition)
- {
- QTextObjectInterface *handler = textDocument->documentLayout()->handlerForObject(format.objectType());
- if (handler != 0) {
- QImage image;
- QSizeF size = handler->intrinsicSize(textDocument, pos, format);
-
- if (format.objectType() == QTextFormat::ImageObject) {
- QTextImageFormat imageFormat = format.toImageFormat();
- QTextImageHandler *imageHandler = static_cast<QTextImageHandler *>(handler);
- image = imageHandler->image(textDocument, imageFormat);
- }
-
- if (image.isNull()) {
- image = QImage(size.toSize(), QImage::Format_ARGB32_Premultiplied);
- image.fill(Qt::transparent);
- {
- QPainter painter(&image);
- handler->drawObject(&painter, image.rect(), textDocument, pos, format);
- }
- }
-
- qreal ascent;
- QFontMetrics m(format.font());
- switch (format.verticalAlignment())
- {
- case QTextCharFormat::AlignMiddle:
- ascent = size.height() / 2 - 1;
- break;
- case QTextCharFormat::AlignBaseline:
- ascent = size.height() - m.descent() - 1;
- break;
- default:
- ascent = size.height() - 1;
- }
-
- addImage(QRectF(position, size), image, ascent, selectionState, layoutPosition);
- }
- }
-
- void SelectionEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
- {
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Unselected,
- m_textColor, m_backgroundColor, m_position);
- }
-
- void SelectionEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
- {
- int currentSize = m_currentLineTree.size();
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Selected,
- m_textColor, m_backgroundColor, m_position);
- m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
- }
-
- void SelectionEngine::addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
- int start, int end,
- int selectionStart, int selectionEnd)
- {
- int currentPosition = start;
- int remainingLength = end - start;
- for (int j=0; j<ranges.size(); ++j) {
- const QTextLayout::FormatRange &range = ranges.at(j);
- if (range.start + range.length >= currentPosition
- && range.start < currentPosition + remainingLength) {
-
- if (range.start > currentPosition) {
- addGlyphsInRange(currentPosition, range.start - currentPosition,
- QColor(), QColor(), selectionStart, selectionEnd);
- }
-
- int rangeEnd = qMin(range.start + range.length, currentPosition + remainingLength);
- QColor rangeColor = range.format.hasProperty(QTextFormat::ForegroundBrush)
- ? range.format.foreground().color()
- : QColor();
- QColor rangeBackgroundColor = range.format.hasProperty(QTextFormat::BackgroundBrush)
- ? range.format.background().color()
- : QColor();
-
- addGlyphsInRange(range.start, rangeEnd - range.start,
- rangeColor, rangeBackgroundColor,
- selectionStart, selectionEnd);
-
- currentPosition = range.start + range.length;
- remainingLength = end - currentPosition;
-
- } else if (range.start > currentPosition + remainingLength || remainingLength <= 0) {
- break;
- }
- }
-
- if (remainingLength > 0) {
- addGlyphsInRange(currentPosition, remainingLength, QColor(), QColor(),
- selectionStart, selectionEnd);
- }
-
- }
-
- void SelectionEngine::addGlyphsInRange(int rangeStart, int rangeLength,
- const QColor &color, const QColor &backgroundColor,
- int selectionStart, int selectionEnd)
- {
- QColor oldColor;
- if (color.isValid()) {
- oldColor = m_textColor;
- m_textColor = color;
- }
-
- QColor oldBackgroundColor = m_backgroundColor;
- if (backgroundColor.isValid()) {
- oldBackgroundColor = m_backgroundColor;
- m_backgroundColor = backgroundColor;
- }
-
- bool hasSelection = selectionEnd >= 0
- && selectionStart <= selectionEnd;
-
- QTextLine &line = m_currentLine;
- int rangeEnd = rangeStart + rangeLength;
- if (!hasSelection || (selectionStart > rangeEnd || selectionEnd < rangeStart)) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- } else {
- if (rangeStart < selectionStart) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart,
- qMin(selectionStart - rangeStart,
- rangeLength));
-
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- }
-
- if (rangeEnd > selectionStart) {
- int start = qMax(selectionStart, rangeStart);
- int length = qMin(selectionEnd - start + 1, rangeEnd - start);
- QList<QGlyphRun> glyphRuns = line.glyphRuns(start, length);
-
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addSelectedGlyphs(glyphRun);
- }
- }
-
- if (selectionEnd >= rangeStart && selectionEnd < rangeEnd) {
- QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, rangeEnd - selectionEnd - 1);
- for (int j=0; j<glyphRuns.size(); ++j) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun);
- }
- }
- }
-
- if (backgroundColor.isValid())
- m_backgroundColor = oldBackgroundColor;
-
- if (oldColor.isValid())
- m_textColor = oldColor;
- }
-
- void SelectionEngine::addBorder(const QRectF &rect, qreal border,
- QTextFrameFormat::BorderStyle borderStyle,
- const QBrush &borderBrush)
- {
- QColor color = borderBrush.color();
-
- // Currently we don't support other styles than solid
- Q_UNUSED(borderStyle);
-
- m_backgrounds.append(qMakePair(QRectF(rect.left(), rect.top(), border, rect.height() + border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.top(), rect.width(), border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.right(), rect.top() + border, border, rect.height() - border), color));
- m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.bottom(), rect.width(), border), color));
- }
-
- void SelectionEngine::addFrameDecorations(QTextDocument *document, QTextFrame *frame)
- {
- QTextDocumentLayout *documentLayout = qobject_cast<QTextDocumentLayout *>(document->documentLayout());
- QTextFrameFormat frameFormat = frame->format().toFrameFormat();
-
- QTextTable *table = qobject_cast<QTextTable *>(frame);
- QRectF boundingRect = table == 0
- ? documentLayout->frameBoundingRect(frame)
- : documentLayout->tableBoundingRect(table);
-
- QBrush bg = frame->frameFormat().background();
- if (bg.style() != Qt::NoBrush)
- m_backgrounds.append(qMakePair(boundingRect, bg.color()));
-
- if (!frameFormat.hasProperty(QTextFormat::FrameBorder))
- return;
-
- qreal borderWidth = frameFormat.border();
- if (qFuzzyIsNull(borderWidth))
- return;
-
- QBrush borderBrush = frameFormat.borderBrush();
- QTextFrameFormat::BorderStyle borderStyle = frameFormat.borderStyle();
- if (borderStyle == QTextFrameFormat::BorderStyle_None)
- return;
-
- addBorder(boundingRect.adjusted(frameFormat.leftMargin(), frameFormat.topMargin(),
- -frameFormat.rightMargin(), -frameFormat.bottomMargin()),
- borderWidth, borderStyle, borderBrush);
- if (table != 0) {
- int rows = table->rows();
- int columns = table->columns();
-
- for (int row=0; row<rows; ++row) {
- for (int column=0; column<columns; ++column) {
- QTextTableCell cell = table->cellAt(row, column);
-
- QRectF cellRect = documentLayout->tableCellBoundingRect(table, cell);
- addBorder(cellRect.adjusted(-borderWidth, -borderWidth, 0, 0), borderWidth,
- borderStyle, borderBrush);
- }
- }
- }
- }
-
- void SelectionEngine::addToSceneGraph(QQuickTextNode *parentNode,
- QQuickText::TextStyle style,
- const QColor &styleColor)
- {
- if (m_currentLine.isValid())
- processCurrentLine();
-
-
- for (int i=0; i<m_backgrounds.size(); ++i) {
- const QRectF &rect = m_backgrounds.at(i).first;
- const QColor &color = m_backgrounds.at(i).second;
-
- parentNode->appendChildNode(new QSGSimpleRectNode(rect, color));
- }
-
- // First, prepend all selection rectangles to the tree
- for (int i=0; i<m_selectionRects.size(); ++i) {
- const QRectF &rect = m_selectionRects.at(i);
-
- parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
- }
-
- // Finally, add decorations for each node to the tree.
- for (int i=0; i<m_lines.size(); ++i) {
- const TextDecoration &textDecoration = m_lines.at(i);
-
- QColor color = textDecoration.selectionState == BinaryTreeNode::Selected
- ? m_selectedTextColor
- : textDecoration.color;
-
- parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
- }
-
- // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
- // font, selection state and clip node.
- typedef QPair<QFontEngine *, QPair<QSGClipNode *, QPair<QRgb, int> > > KeyType;
- QHash<KeyType, BinaryTreeNode *> map;
- for (int i=0; i<m_processedNodes.size(); ++i) {
- BinaryTreeNode *node = m_processedNodes.data() + i;
-
- if (node->image.isNull()) {
- QGlyphRun glyphRun = node->glyphRun;
- QRawFont rawFont = glyphRun.rawFont();
- QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
-
- QFontEngine *fontEngine = rawFontD->fontEngine;
-
- KeyType key(qMakePair(fontEngine,
- qMakePair(node->clipNode,
- qMakePair(node->color.rgba(), int(node->selectionState)))));
-
- BinaryTreeNode *otherNode = map.value(key, 0);
- if (otherNode != 0) {
- QGlyphRun &otherGlyphRun = otherNode->glyphRun;
-
- QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
- QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();
-
- otherGlyphIndexes += glyphRun.glyphIndexes();
-
- QVector<QPointF> glyphPositions = glyphRun.positions();
- for (int j=0; j<glyphPositions.size(); ++j) {
- otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
- }
-
- otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
- otherGlyphRun.setPositions(otherGlyphPositions);
-
- } else {
- map.insert(key, node);
- }
- } else {
- parentNode->addImage(node->boundingRect, node->image);
- if (node->selectionState == BinaryTreeNode::Selected) {
- QColor color = m_selectionColor;
- color.setAlpha(128);
- parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color));
- }
- }
- }
-
- // ...and add clip nodes and glyphs to tree.
- QHash<KeyType, BinaryTreeNode *>::const_iterator it = map.constBegin();
- while (it != map.constEnd()) {
-
- BinaryTreeNode *node = it.value();
-
- QSGClipNode *clipNode = node->clipNode;
- if (clipNode != 0 && clipNode->parent() == 0 )
- parentNode->appendChildNode(clipNode);
-
- QColor color = node->selectionState == BinaryTreeNode::Selected
- ? m_selectedTextColor
- : node->color;
-
- parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
-
- ++it;
- }
- }
-}
-
-void QQuickTextNode::mergeFormats(QTextLayout *textLayout,
- QVarLengthArray<QTextLayout::FormatRange> *mergedFormats)
-{
- Q_ASSERT(mergedFormats != 0);
- if (textLayout == 0)
- return;
-
- QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
- for (int i=0; i<additionalFormats.size(); ++i) {
- QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
- if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
- || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)) {
- // Merge overlapping formats
- if (!mergedFormats->isEmpty()) {
- QTextLayout::FormatRange *lastFormat = mergedFormats->data() + mergedFormats->size() - 1;
-
- if (additionalFormat.start < lastFormat->start + lastFormat->length) {
- QTextLayout::FormatRange *mergedRange = 0;
-
- int length = additionalFormat.length;
- if (additionalFormat.start > lastFormat->start) {
- lastFormat->length = additionalFormat.start - lastFormat->start;
- length -= lastFormat->length;
-
- mergedFormats->append(QTextLayout::FormatRange());
- mergedRange = mergedFormats->data() + mergedFormats->size() - 1;
- lastFormat = mergedFormats->data() + mergedFormats->size() - 2;
- } else {
- mergedRange = lastFormat;
- }
-
- mergedRange->format = lastFormat->format;
- mergedRange->format.merge(additionalFormat.format);
- mergedRange->start = additionalFormat.start;
-
- int end = qMin(additionalFormat.start + additionalFormat.length,
- lastFormat->start + lastFormat->length);
-
- mergedRange->length = end - mergedRange->start;
- length -= mergedRange->length;
-
- additionalFormat.start = end;
- additionalFormat.length = length;
- }
- }
-
- if (additionalFormat.length > 0)
- mergedFormats->append(additionalFormat);
- }
- }
-
-}
-
-namespace {
-
- class ProtectedLayoutAccessor: public QAbstractTextDocumentLayout
- {
- public:
- inline QTextCharFormat formatAccessor(int pos)
- {
- return format(pos);
- }
- };
-
-}
-
-void QQuickTextNode::addImage(const QRectF &rect, const QImage &image)
-{
- QSGImageNode *node = m_context->createImageNode();
- QSGTexture *texture = m_context->createTexture(image);
- m_textures.append(texture);
- node->setTargetRect(rect);
- node->setTexture(texture);
- appendChildNode(node);
- node->update();
-}
-
-void QQuickTextNode::addTextDocument(const QPointF &, QTextDocument *textDocument,
- const QColor &textColor,
- QQuickText::TextStyle style, const QColor &styleColor,
- const QColor &selectionColor, const QColor &selectedTextColor,
- int selectionStart, int selectionEnd)
-{
- SelectionEngine engine;
- engine.setTextColor(textColor);
- engine.setSelectedTextColor(selectedTextColor);
- engine.setSelectionColor(selectionColor);
-
- QList<QTextFrame *> frames;
- frames.append(textDocument->rootFrame());
- while (!frames.isEmpty()) {
- QTextFrame *textFrame = frames.takeFirst();
- frames.append(textFrame->childFrames());
-
- engine.addFrameDecorations(textDocument, textFrame);
-
- if (textFrame->firstPosition() > textFrame->lastPosition()
- && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
- const int pos = textFrame->firstPosition() - 1;
- ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(textDocument->documentLayout());
- QTextCharFormat format = a->formatAccessor(pos);
- QRectF rect = a->frameBoundingRect(textFrame);
-
- QTextBlock block = textFrame->firstCursorPosition().block();
- engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- engine.addTextObject(rect.topLeft(), format, BinaryTreeNode::Unselected, textDocument,
- pos, textFrame->frameFormat().position());
- } else {
- QTextFrame::iterator it = textFrame->begin();
-
- while (!it.atEnd()) {
- Q_ASSERT(!engine.currentLine().isValid());
-
- QTextBlock block = it.currentBlock();
- int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
- int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
-
- QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- mergeFormats(block.layout(), &colorChanges);
-
- QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft();
- if (QTextList *textList = block.textList()) {
- QPointF pos = blockPosition;
- QTextLayout *layout = block.layout();
- if (layout->lineCount() > 0) {
- QTextLine firstLine = layout->lineAt(0);
- Q_ASSERT(firstLine.isValid());
-
- engine.setCurrentLine(firstLine);
-
- QRectF textRect = firstLine.naturalTextRect();
- pos += textRect.topLeft();
- if (block.textDirection() == Qt::RightToLeft)
- pos.rx() += textRect.width();
-
- const QTextCharFormat charFormat = block.charFormat();
- QFont font(charFormat.font());
- QFontMetricsF fontMetrics(font);
- QTextListFormat listFormat = textList->format();
-
- QString listItemBullet;
- switch (listFormat.style()) {
- case QTextListFormat::ListCircle:
- listItemBullet = QChar(0x25E6); // White bullet
- break;
- case QTextListFormat::ListSquare:
- listItemBullet = QChar(0x25AA); // Black small square
- break;
- case QTextListFormat::ListDecimal:
- case QTextListFormat::ListLowerAlpha:
- case QTextListFormat::ListUpperAlpha:
- case QTextListFormat::ListLowerRoman:
- case QTextListFormat::ListUpperRoman:
- listItemBullet = textList->itemText(block);
- break;
- default:
- listItemBullet = QChar(0x2022); // Black bullet
- break;
- };
-
- QSizeF size(fontMetrics.width(listItemBullet), fontMetrics.height());
- qreal xoff = fontMetrics.width(QLatin1Char(' '));
- if (block.textDirection() == Qt::LeftToRight)
- xoff = -xoff - size.width();
- engine.setPosition(pos + QPointF(xoff, 0));
-
- QTextLayout layout;
- layout.setFont(font);
- layout.setText(listItemBullet); // Bullet
- layout.beginLayout();
- QTextLine line = layout.createLine();
- line.setPosition(QPointF(0, 0));
- layout.endLayout();
-
- QList<QGlyphRun> glyphRuns = layout.glyphRuns();
- for (int i=0; i<glyphRuns.size(); ++i)
- engine.addUnselectedGlyphs(glyphRuns.at(i));
- }
- }
-
- int textPos = block.position();
- QTextBlock::iterator blockIterator = block.begin();
- while (!blockIterator.atEnd()) {
- QTextFragment fragment = blockIterator.fragment();
- QString text = fragment.text();
- if (text.isEmpty())
- continue;
-
- QTextCharFormat charFormat = fragment.charFormat();
- engine.setPosition(blockPosition);
- if (text.contains(QChar::ObjectReplacementCharacter)) {
- QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
- if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
- BinaryTreeNode::SelectionState selectionState =
- (selectionStart < textPos + text.length()
- && selectionEnd >= textPos)
- ? BinaryTreeNode::Selected
- : BinaryTreeNode::Unselected;
-
- engine.addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos);
- }
- textPos += text.length();
- } else {
- if (charFormat.foreground().style() != Qt::NoBrush)
- engine.setTextColor(charFormat.foreground().color());
- else
- engine.setTextColor(textColor);
-
- int fragmentEnd = textPos + fragment.length();
- if (preeditPosition >= 0
- && preeditPosition >= textPos
- && preeditPosition < fragmentEnd) {
- fragmentEnd += preeditLength;
- }
-
- while (textPos < fragmentEnd) {
- int blockRelativePosition = textPos - block.position();
- QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
- if (!engine.currentLine().isValid()
- || line.lineNumber() != engine.currentLine().lineNumber()) {
- engine.setCurrentLine(line);
- }
-
- Q_ASSERT(line.textLength() > 0);
- int lineEnd = line.textStart() + block.position() + line.textLength();
-
- int len = qMin(lineEnd - textPos, fragmentEnd - textPos);
- Q_ASSERT(len > 0);
-
- int currentStepEnd = textPos + len;
-
- engine.addGlyphsForRanges(colorChanges,
- textPos - block.position(),
- currentStepEnd - block.position(),
- selectionStart - block.position(),
- selectionEnd - block.position());
-
- textPos = currentStepEnd;
- }
- }
-
- ++blockIterator;
- }
-
- engine.setCurrentLine(QTextLine()); // Reset current line because the text layout changed
- ++it;
- }
- }
- }
-
- engine.addToSceneGraph(this, style, styleColor);
-}
-
-void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
- QQuickText::TextStyle style, const QColor &styleColor,
- const QColor &selectionColor, const QColor &selectedTextColor,
- int selectionStart, int selectionEnd)
-{
- SelectionEngine engine;
- engine.setTextColor(color);
- engine.setSelectedTextColor(selectedTextColor);
- engine.setSelectionColor(selectionColor);
- engine.setPosition(position);
-
- int preeditLength = textLayout->preeditAreaText().length();
- int preeditPosition = textLayout->preeditAreaPosition();
-
- QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- mergeFormats(textLayout, &colorChanges);
-
- for (int i=0; i<textLayout->lineCount(); ++i) {
- QTextLine line = textLayout->lineAt(i);
-
- int start = line.textStart();
- int length = line.textLength();
- int end = start + length;
-
- if (preeditPosition >= 0
- && preeditPosition >= start
- && preeditPosition < end) {
- end += preeditLength;
- }
-
- engine.setCurrentLine(line);
- engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
- }
-
- engine.addToSceneGraph(this, style, styleColor);
-}
-
-void QQuickTextNode::deleteContent()
-{
- while (firstChild() != 0)
- delete firstChild();
- m_cursorNode = 0;
-}
-
-#if 0
-void QQuickTextNode::updateNodes()
-{
- return;
- deleteContent();
- if (m_text.isEmpty())
- return;
-
- if (m_usePixmapCache) {
- // ### gunnar: port properly
-// QPixmap pixmap = generatedPixmap();
-// if (pixmap.isNull())
-// return;
-
-// QSGImageNode *pixmapNode = m_context->createImageNode();
-// pixmapNode->setRect(pixmap.rect());
-// pixmapNode->setSourceRect(pixmap.rect());
-// pixmapNode->setOpacity(m_opacity);
-// pixmapNode->setClampToEdge(true);
-// pixmapNode->setLinearFiltering(m_linearFiltering);
-
-// appendChildNode(pixmapNode);
- } else {
- if (m_text.isEmpty())
- return;
-
- // Implement styling by drawing text several times at slight shifts. shiftForStyle
- // contains the sequence of shifted positions at which to draw the text. All except
- // the last will be drawn with styleColor.
- QList<QPointF> shiftForStyle;
- switch (m_textStyle) {
- case OutlineTextStyle:
- // ### Should be made faster by implementing outline material
- shiftForStyle << QPointF(-1, 0);
- shiftForStyle << QPointF(0, -1);
- shiftForStyle << QPointF(1, 0);
- shiftForStyle << QPointF(0, 1);
- break;
- case SunkenTextStyle:
- shiftForStyle << QPointF(0, -1);
- break;
- case RaisedTextStyle:
- shiftForStyle << QPointF(0, 1);
- break;
- default:
- break;
- }
-
- shiftForStyle << QPointF(0, 0); // Regular position
- while (!shiftForStyle.isEmpty()) {
- QPointF shift = shiftForStyle.takeFirst();
-
- // Use styleColor for all but last shift
- if (m_richText) {
- QColor overrideColor = shiftForStyle.isEmpty() ? QColor() : m_styleColor;
-
- QTextFrame *textFrame = m_textDocument->rootFrame();
- QPointF p = m_textDocument->documentLayout()->frameBoundingRect(textFrame).topLeft();
-
- QTextFrame::iterator it = textFrame->begin();
- while (!it.atEnd()) {
- addTextBlock(shift + p, it.currentBlock(), overrideColor);
- ++it;
- }
- } else {
- addTextLayout(shift, m_textLayout, shiftForStyle.isEmpty()
- ? m_color
- : m_styleColor);
- }
- }
- }
-}
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquicktextnode_p.h b/src/declarative/items/qquicktextnode_p.h
deleted file mode 100644
index 16e92e34f3..0000000000
--- a/src/declarative/items/qquicktextnode_p.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKTEXTNODE_P_H
-#define QQUICKTEXTNODE_P_H
-
-#include <qsgnode.h>
-#include "qquicktext_p.h"
-#include <qglyphrun.h>
-
-#include <QtGui/qcolor.h>
-#include <QtGui/qtextlayout.h>
-#include <QtCore/qvarlengtharray.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGGlyphNode;
-class QTextBlock;
-class QColor;
-class QTextDocument;
-class QSGContext;
-class QRawFont;
-class QSGSimpleRectNode;
-class QSGClipNode;
-class QSGTexture;
-
-class QQuickTextNode : public QSGTransformNode
-{
-public:
- enum Decoration {
- NoDecoration = 0x0,
- Underline = 0x1,
- Overline = 0x2,
- StrikeOut = 0x4,
- Background = 0x8
- };
- Q_DECLARE_FLAGS(Decorations, Decoration)
-
- QQuickTextNode(QSGContext *);
- ~QQuickTextNode();
-
- static bool isComplexRichText(QTextDocument *);
-
- void deleteContent();
- void addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color = QColor(),
- QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
- const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
- int selectionStart = -1, int selectionEnd = -1);
- void addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &color = QColor(),
- QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
- const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
- int selectionStart = -1, int selectionEnd = -1);
-
- void setCursor(const QRectF &rect, const QColor &color);
- QSGSimpleRectNode *cursorNode() const { return m_cursorNode; }
-
- QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
- QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
- QSGNode *parentNode = 0);
- void addImage(const QRectF &rect, const QImage &image);
-
-private:
- void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
-
- QSGContext *m_context;
- QSGSimpleRectNode *m_cursorNode;
- QList<QSGTexture *> m_textures;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQUICKTEXTNODE_P_H
diff --git a/src/declarative/items/qquicktranslate_p.h b/src/declarative/items/qquicktranslate_p.h
deleted file mode 100644
index 6c2333df34..0000000000
--- a/src/declarative/items/qquicktranslate_p.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKTRANSLATE_P_H
-#define QQUICKTRANSLATE_P_H
-
-#include "qquickitem.h"
-
-#include <QtGui/qmatrix4x4.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickTranslatePrivate;
-class Q_AUTOTEST_EXPORT QQuickTranslate : public QQuickTransform
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
-
-public:
- QQuickTranslate(QObject *parent = 0);
- ~QQuickTranslate();
-
- qreal x() const;
- void setX(qreal);
-
- qreal y() const;
- void setY(qreal);
-
- void applyTo(QMatrix4x4 *matrix) const;
-
-Q_SIGNALS:
- void xChanged();
- void yChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickTranslate)
- Q_DISABLE_COPY(QQuickTranslate)
-};
-
-class QQuickScalePrivate;
-class Q_AUTOTEST_EXPORT QQuickScale : public QQuickTransform
-{
- Q_OBJECT
-
- Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
- Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged)
- Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged)
- Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged)
-public:
- QQuickScale(QObject *parent = 0);
- ~QQuickScale();
-
- QVector3D origin() const;
- void setOrigin(const QVector3D &point);
-
- qreal xScale() const;
- void setXScale(qreal);
-
- qreal yScale() const;
- void setYScale(qreal);
-
- qreal zScale() const;
- void setZScale(qreal);
-
- void applyTo(QMatrix4x4 *matrix) const;
-
-Q_SIGNALS:
- void originChanged();
- void xScaleChanged();
- void yScaleChanged();
- void zScaleChanged();
- void scaleChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickScale)
-};
-
-class QQuickRotationPrivate;
-class Q_AUTOTEST_EXPORT QQuickRotation : public QQuickTransform
-{
- Q_OBJECT
-
- Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
- Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
- Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
-public:
- QQuickRotation(QObject *parent = 0);
- ~QQuickRotation();
-
- QVector3D origin() const;
- void setOrigin(const QVector3D &point);
-
- qreal angle() const;
- void setAngle(qreal);
-
- QVector3D axis() const;
- void setAxis(const QVector3D &axis);
- void setAxis(Qt::Axis axis);
-
- void applyTo(QMatrix4x4 *matrix) const;
-
-Q_SIGNALS:
- void originChanged();
- void angleChanged();
- void axisChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickRotation)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickTranslate)
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/items/qquickview.cpp b/src/declarative/items/qquickview.cpp
deleted file mode 100644
index 9d431c865a..0000000000
--- a/src/declarative/items/qquickview.cpp
+++ /dev/null
@@ -1,539 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickview.h"
-#include "qquickview_p.h"
-
-#include "qquickcanvas_p.h"
-#include "qquickitem_p.h"
-#include "qquickitemchangelistener_p.h"
-
-#include <private/qdeclarativedebugtrace_p.h>
-#include <private/qdeclarativeinspectorservice_p.h>
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <private/qdeclarativeengine_p.h>
-#include <QtCore/qbasictimer.h>
-
-
-QT_BEGIN_NAMESPACE
-
-void QQuickViewPrivate::init()
-{
- Q_Q(QQuickView);
-
- engine.setIncubationController(q->incubationController());
-
- if (QDeclarativeDebugService::isDebuggingEnabled())
- QDeclarativeInspectorService::instance()->addView(q);
-}
-
-QQuickViewPrivate::QQuickViewPrivate()
- : root(0), component(0), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0)
-{
-}
-
-QQuickViewPrivate::~QQuickViewPrivate()
-{
- if (QDeclarativeDebugService::isDebuggingEnabled())
- QDeclarativeInspectorService::instance()->removeView(q_func());
-
- delete root;
-}
-
-void QQuickViewPrivate::execute()
-{
- Q_Q(QQuickView);
- if (root) {
- delete root;
- root = 0;
- }
- if (component) {
- delete component;
- component = 0;
- }
- if (!source.isEmpty()) {
- component = new QDeclarativeComponent(&engine, source, q);
- if (!component->isLoading()) {
- q->continueExecute();
- } else {
- QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
- q, SLOT(continueExecute()));
- }
- }
-}
-
-void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_Q(QQuickView);
- if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) {
- // wait for both width and height to be changed
- resizetimer.start(0,q);
- }
- QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
-}
-
-/*!
- \class QQuickView
- \since QtQuick 2.0
- \brief The QQuickView class provides a window for displaying a Qt Quick user interface.
-
- This is a convenience subclass of QQuickCanvas which
- will automatically load and display a QML scene when given the URL of the main source file. Alternatively,
- you can instantiate your own objects using QDeclarativeComponent and place them in a manually setup QQuickCanvas.
-
- Typical usage:
-
- \code
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
- view->show();
- \endcode
-
- To receive errors related to loading and executing QML with QQuickView,
- you can connect to the statusChanged() signal and monitor for QQuickView::Error.
- The errors are available via QQuickView::errors().
-
- \sa {Using QML Bindings in C++ Applications}
-*/
-
-
-/*! \fn void QQuickView::sceneResized(QSize size)
- This signal is emitted when the view is resized to \a size.
-*/
-
-/*! \fn void QQuickView::statusChanged(QQuickView::Status status)
- This signal is emitted when the component's current \a status changes.
-*/
-
-/*! \fn void QQuickView::initialSizeChanged(QSize size)
- \internal
-*/
-
-/*!
- \fn QQuickView::QQuickView(QWindow *parent)
-
- Constructs a QQuickView with the given \a parent.
-*/
-QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
-: QQuickCanvas(*(new QQuickViewPrivate), parent)
-{
- setWindowFlags(f);
- d_func()->init();
-}
-
-/*!
- \fn QQuickView::QQuickView(const QUrl &source, QWidget *parent)
-
- Constructs a QQuickView with the given QML \a source and \a parent.
-*/
-QQuickView::QQuickView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
-: QQuickCanvas(*(new QQuickViewPrivate), parent)
-{
- setWindowFlags(f);
- d_func()->init();
- setSource(source);
-}
-
-QQuickView::~QQuickView()
-{
-}
-
-/*! \property QQuickView::source
- \brief The URL of the source of the QML component.
-
- Changing this property causes the QML component to be reloaded.
-
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
- */
-
-/*!
- Sets the source to the \a url, loads the QML component and instantiates it.
-
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
-
- Calling this methods multiple times with the same url will result
- in the QML being reloaded.
- */
-void QQuickView::setSource(const QUrl& url)
-{
- Q_D(QQuickView);
- d->source = url;
- d->execute();
-}
-
-/*!
- Returns the source URL, if set.
-
- \sa setSource()
- */
-QUrl QQuickView::source() const
-{
- Q_D(const QQuickView);
- return d->source;
-}
-
-/*!
- Returns a pointer to the QDeclarativeEngine used for instantiating
- QML Components.
- */
-QDeclarativeEngine* QQuickView::engine() const
-{
- Q_D(const QQuickView);
- return const_cast<QDeclarativeEngine *>(&d->engine);
-}
-
-/*!
- This function returns the root of the context hierarchy. Each QML
- component is instantiated in a QDeclarativeContext. QDeclarativeContext's are
- essential for passing data to QML components. In QML, contexts are
- arranged hierarchically and this hierarchy is managed by the
- QDeclarativeEngine.
- */
-QDeclarativeContext* QQuickView::rootContext() const
-{
- Q_D(const QQuickView);
- return d->engine.rootContext();
-}
-
-/*!
- \enum QQuickView::Status
- Specifies the loading status of the QQuickView.
-
- \value Null This QQuickView has no source set.
- \value Ready This QQuickView has loaded and created the QML component.
- \value Loading This QQuickView is loading network data.
- \value Error One or more errors has occurred. Call errors() to retrieve a list
- of errors.
-*/
-
-/*! \enum QQuickView::ResizeMode
-
- This enum specifies how to resize the view.
-
- \value SizeViewToRootObject The view resizes with the root item in the QML.
- \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
-*/
-
-/*!
- \property QQuickView::status
- The component's current \l{QQuickView::Status} {status}.
-*/
-
-QQuickView::Status QQuickView::status() const
-{
- Q_D(const QQuickView);
- if (!d->component)
- return QQuickView::Null;
-
- return QQuickView::Status(d->component->status());
-}
-
-/*!
- Return the list of errors that occurred during the last compile or create
- operation. When the status is not Error, an empty list is returned.
-*/
-QList<QDeclarativeError> QQuickView::errors() const
-{
- Q_D(const QQuickView);
- if (d->component)
- return d->component->errors();
- return QList<QDeclarativeError>();
-}
-
-/*!
- \property QQuickView::resizeMode
- \brief whether the view should resize the canvas contents
-
- If this property is set to SizeViewToRootObject (the default), the view
- resizes with the root item in the QML.
-
- If this property is set to SizeRootObjectToView, the view will
- automatically resize the root item.
-
- Regardless of this property, the sizeHint of the view
- is the initial size of the root item. Note though that
- since QML may load dynamically, that size may change.
-*/
-
-void QQuickView::setResizeMode(ResizeMode mode)
-{
- Q_D(QQuickView);
- if (d->resizeMode == mode)
- return;
-
- if (d->root) {
- if (d->resizeMode == SizeViewToRootObject) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
- p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
- }
- }
-
- d->resizeMode = mode;
- if (d->root) {
- d->initResize();
- }
-}
-
-void QQuickViewPrivate::initResize()
-{
- if (root) {
- if (resizeMode == QQuickView::SizeViewToRootObject) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(root);
- p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- }
- }
- updateSize();
-}
-
-void QQuickViewPrivate::updateSize()
-{
- Q_Q(QQuickView);
- if (!root)
- return;
-
- if (resizeMode == QQuickView::SizeViewToRootObject) {
- QSize newSize = QSize(root->width(), root->height());
- if (newSize.isValid() && newSize != q->size()) {
- q->resize(newSize);
- }
- } else if (resizeMode == QQuickView::SizeRootObjectToView) {
- if (!qFuzzyCompare(q->width(), root->width()))
- root->setWidth(q->width());
- if (!qFuzzyCompare(q->height(), root->height()))
- root->setHeight(q->height());
- }
-}
-
-QSize QQuickViewPrivate::rootObjectSize() const
-{
- QSize rootObjectSize(0,0);
- int widthCandidate = -1;
- int heightCandidate = -1;
- if (root) {
- widthCandidate = root->width();
- heightCandidate = root->height();
- }
- if (widthCandidate > 0) {
- rootObjectSize.setWidth(widthCandidate);
- }
- if (heightCandidate > 0) {
- rootObjectSize.setHeight(heightCandidate);
- }
- return rootObjectSize;
-}
-
-QQuickView::ResizeMode QQuickView::resizeMode() const
-{
- Q_D(const QQuickView);
- return d->resizeMode;
-}
-
-/*!
- \internal
- */
-void QQuickView::continueExecute()
-{
- Q_D(QQuickView);
- disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute()));
-
- if (d->component->isError()) {
- QList<QDeclarativeError> errorList = d->component->errors();
- foreach (const QDeclarativeError &error, errorList) {
- qWarning() << error;
- }
- emit statusChanged(status());
- return;
- }
-
- QObject *obj = d->component->create();
-
- if (d->component->isError()) {
- QList<QDeclarativeError> errorList = d->component->errors();
- foreach (const QDeclarativeError &error, errorList) {
- qWarning() << error;
- }
- emit statusChanged(status());
- return;
- }
-
- d->setRootObject(obj);
- emit statusChanged(status());
-}
-
-
-/*!
- \internal
-*/
-void QQuickViewPrivate::setRootObject(QObject *obj)
-{
- Q_Q(QQuickView);
- if (root == obj)
- return;
- if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
- root = sgItem;
- sgItem->setParentItem(q->QQuickCanvas::rootItem());
- } else {
- qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
- << endl
- << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
- << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
- << endl
- << "To load files with 'import QtQuick 1.0' with QML 2, specify:" << endl
- << " QMLSCENE_IMPORT_NAME=quick1" << endl
- << "on as an environment variable prior to launching the application." << endl
- << endl
- << "To load files with 'import Qt 4.7' with QML 2, specify:" << endl
- << " QMLSCENE_IMPORT_NAME=qt" << endl
- << "on as an environment variable prior to launching the application." << endl;
- delete obj;
- root = 0;
- }
- if (root) {
- initialSize = rootObjectSize();
- if ((resizeMode == QQuickView::SizeViewToRootObject || !q->width() || !q->height())
- && initialSize != q->size()) {
- q->resize(initialSize);
- }
- initResize();
- }
-}
-
-/*!
- \internal
- If the \l {QTimerEvent} {timer event} \a e is this
- view's resize timer, sceneResized() is emitted.
- */
-void QQuickView::timerEvent(QTimerEvent* e)
-{
- Q_D(QQuickView);
- if (!e || e->timerId() == d->resizetimer.timerId()) {
- d->updateSize();
- d->resizetimer.stop();
- }
-}
-
-/*!
- \internal
- Preferred size follows the root object geometry.
-*/
-QSize QQuickView::sizeHint() const
-{
- Q_D(const QQuickView);
- QSize rootObjectSize = d->rootObjectSize();
- if (rootObjectSize.isEmpty()) {
- return size();
- } else {
- return rootObjectSize;
- }
-}
-
-/*!
- Returns the initial size of the root object
-*/
-QSize QQuickView::initialSize() const
-{
- Q_D(const QQuickView);
- return d->initialSize;
-}
-
-/*!
- Returns the view's root \l {QQuickItem} {item}.
- */
-QQuickItem *QQuickView::rootObject() const
-{
- Q_D(const QQuickView);
- return d->root;
-}
-
-/*!
- \internal
- This function handles the \l {QResizeEvent} {resize event}
- \a e.
- */
-void QQuickView::resizeEvent(QResizeEvent *e)
-{
- Q_D(QQuickView);
- if (d->resizeMode == SizeRootObjectToView)
- d->updateSize();
-
- QQuickCanvas::resizeEvent(e);
-}
-
-void QQuickView::keyPressEvent(QKeyEvent *e)
-{
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
-
- QQuickCanvas::keyPressEvent(e);
-}
-
-void QQuickView::keyReleaseEvent(QKeyEvent *e)
-{
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
-
- QQuickCanvas::keyReleaseEvent(e);
-}
-
-void QQuickView::mouseMoveEvent(QMouseEvent *e)
-{
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
-
- QQuickCanvas::mouseMoveEvent(e);
-}
-
-void QQuickView::mousePressEvent(QMouseEvent *e)
-{
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
-
- QQuickCanvas::mousePressEvent(e);
-}
-
-void QQuickView::mouseReleaseEvent(QMouseEvent *e)
-{
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
-
- QQuickCanvas::mouseReleaseEvent(e);
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/items/qquickview.h b/src/declarative/items/qquickview.h
deleted file mode 100644
index 8321655d63..0000000000
--- a/src/declarative/items/qquickview.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Commit: 0b83a2161261be525f01359397ab1c8c34827749
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKVIEW_H
-#define QQUICKVIEW_H
-
-#include <qquickcanvas.h>
-#include <QtCore/qurl.h>
-#include <QtDeclarative/qdeclarativedebug.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeEngine;
-class QDeclarativeContext;
-class QDeclarativeError;
-class QQuickItem;
-
-class QQuickViewPrivate;
-class Q_DECLARATIVE_EXPORT QQuickView : public QQuickCanvas
-{
- Q_OBJECT
- Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
- Q_PROPERTY(Status status READ status NOTIFY statusChanged)
- Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
- Q_ENUMS(ResizeMode Status)
-public:
- explicit QQuickView(QWindow *parent = 0, Qt::WindowFlags f = 0);
- QQuickView(const QUrl &source, QWindow *parent = 0, Qt::WindowFlags f = 0);
- virtual ~QQuickView();
-
- QUrl source() const;
-
- QDeclarativeEngine* engine() const;
- QDeclarativeContext* rootContext() const;
-
- QQuickItem *rootObject() const;
-
- enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
- ResizeMode resizeMode() const;
- void setResizeMode(ResizeMode);
-
- enum Status { Null, Ready, Loading, Error };
- Status status() const;
-
- QList<QDeclarativeError> errors() const;
-
- QSize sizeHint() const;
- QSize initialSize() const;
-
-public Q_SLOTS:
- void setSource(const QUrl&);
-
-Q_SIGNALS:
- void statusChanged(QQuickView::Status);
-
-private Q_SLOTS:
- void continueExecute();
-
-protected:
- virtual void resizeEvent(QResizeEvent *);
- virtual void timerEvent(QTimerEvent*);
-
- virtual void keyPressEvent(QKeyEvent *);
- virtual void keyReleaseEvent(QKeyEvent *);
- virtual void mousePressEvent(QMouseEvent *);
- virtual void mouseReleaseEvent(QMouseEvent *);
- virtual void mouseMoveEvent(QMouseEvent *);
-private:
- Q_DISABLE_COPY(QQuickView)
- Q_DECLARE_PRIVATE(QQuickView)
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKVIEW_H
diff --git a/src/declarative/items/qquickview_p.h b/src/declarative/items/qquickview_p.h
deleted file mode 100644
index 8c835268f5..0000000000
--- a/src/declarative/items/qquickview_p.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKVIEW_P_H
-#define QQUICKVIEW_P_H
-
-#include "qquickview.h"
-
-#include <QtCore/qurl.h>
-#include <QtCore/qelapsedtimer.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qpointer.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include "qquickcanvas_p.h"
-
-#include "qquickitemchangelistener_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeContext;
-class QDeclarativeError;
-class QQuickItem;
-class QDeclarativeComponent;
-
-class QQuickViewPrivate : public QQuickCanvasPrivate,
- public QQuickItemChangeListener
-{
- Q_DECLARE_PUBLIC(QQuickView)
-public:
- static QQuickViewPrivate* get(QQuickView *view) { return view->d_func(); }
- static const QQuickViewPrivate* get(const QQuickView *view) { return view->d_func(); }
-
- QQuickViewPrivate();
- ~QQuickViewPrivate();
-
- void execute();
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- void initResize();
- void updateSize();
- void setRootObject(QObject *);
-
- void init();
-
- QSize rootObjectSize() const;
-
- QPointer<QQuickItem> root;
-
- QUrl source;
-
- QDeclarativeEngine engine;
- QDeclarativeComponent *component;
- QBasicTimer resizetimer;
-
- QQuickView::ResizeMode resizeMode;
- QSize initialSize;
- QElapsedTimer frameTimer;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQUICKVIEW_P_H
diff --git a/src/declarative/items/qquickvisualdatamodel_p.h b/src/declarative/items/qquickvisualdatamodel_p.h
deleted file mode 100644
index a5a384f67b..0000000000
--- a/src/declarative/items/qquickvisualdatamodel_p.h
+++ /dev/null
@@ -1,242 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKVISUALDATAMODEL_P_H
-#define QQUICKVISUALDATAMODEL_P_H
-
-#include <private/qdeclarativelistcompositor_p.h>
-#include <private/qquickvisualitemmodel_p.h>
-
-
-#include <QtCore/qabstractitemmodel.h>
-#include <QtCore/qstringlist.h>
-
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_HEADER
-
-Q_DECLARE_METATYPE(QModelIndex)
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QDeclarativeChangeSet;
-class QDeclarativeComponent;
-class QDeclarativePackage;
-class QDeclarativeV8Function;
-class QQuickVisualDataGroup;
-class QQuickVisualDataModelAttached;
-class QQuickVisualDataModelPrivate;
-
-
-class Q_DECLARATIVE_EXPORT QQuickVisualDataModel : public QQuickVisualModel, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickVisualDataModel)
-
- Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate)
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
- Q_PROPERTY(QQuickVisualDataGroup *items READ items CONSTANT)
- Q_PROPERTY(QQuickVisualDataGroup *persistedItems READ persistedItems CONSTANT)
- Q_PROPERTY(QDeclarativeListProperty<QQuickVisualDataGroup> groups READ groups CONSTANT)
- Q_PROPERTY(QObject *parts READ parts CONSTANT)
- Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
- Q_INTERFACES(QDeclarativeParserStatus)
-public:
- QQuickVisualDataModel();
- QQuickVisualDataModel(QDeclarativeContext *, QObject *parent=0);
- virtual ~QQuickVisualDataModel();
-
- void classBegin();
- void componentComplete();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- QVariant rootIndex() const;
- void setRootIndex(const QVariant &root);
-
- Q_INVOKABLE QVariant modelIndex(int idx) const;
- Q_INVOKABLE QVariant parentModelIndex() const;
-
- int count() const;
- bool isValid() const { return delegate() != 0; }
- QQuickItem *item(int index, bool asynchronous=false);
- ReleaseFlags release(QQuickItem *item);
- virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
-
- int indexOf(QQuickItem *item, QObject *objectContext) const;
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
-
- QQuickVisualDataGroup *items();
- QQuickVisualDataGroup *persistedItems();
- QDeclarativeListProperty<QQuickVisualDataGroup> groups();
- QObject *parts();
-
- bool event(QEvent *);
-
- static QQuickVisualDataModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void filterGroupChanged();
- void defaultGroupsChanged();
- void rootIndexChanged();
-
-private Q_SLOTS:
- void _q_itemsChanged(int index, int count);
- void _q_itemsInserted(int index, int count);
- void _q_itemsRemoved(int index, int count);
- void _q_itemsMoved(int from, int to, int count);
- void _q_modelReset(int oldCount, int newCount);
-private:
- Q_DISABLE_COPY(QQuickVisualDataModel)
-};
-
-class QQuickVisualDataGroupPrivate;
-class Q_AUTOTEST_EXPORT QQuickVisualDataGroup : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
-public:
- QQuickVisualDataGroup(QObject *parent = 0);
- QQuickVisualDataGroup(const QString &name, QQuickVisualDataModel *model, int compositorType, QObject *parent = 0);
- ~QQuickVisualDataGroup();
-
- QString name() const;
- void setName(const QString &name);
-
- int count() const;
-
- bool defaultInclude() const;
- void setDefaultInclude(bool include);
-
- Q_INVOKABLE QDeclarativeV8Handle get(int index);
- Q_INVOKABLE QObject *create(int index);
-
-public Q_SLOTS:
- void remove(QDeclarativeV8Function *);
- void addGroups(QDeclarativeV8Function *);
- void removeGroups(QDeclarativeV8Function *);
- void setGroups(QDeclarativeV8Function *);
- void move(QDeclarativeV8Function *);
-
-Q_SIGNALS:
- void countChanged();
- void nameChanged();
- void defaultIncludeChanged();
- void changed(const QDeclarativeV8Handle &removed, const QDeclarativeV8Handle &inserted);
-private:
- Q_DECLARE_PRIVATE(QQuickVisualDataGroup)
-};
-
-class QQuickVisualDataModelCacheItem;
-class QQuickVisualDataModelAttachedMetaObject;
-class QQuickVisualDataModelAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQuickVisualDataModel *model READ model NOTIFY modelChanged)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
-public:
- QQuickVisualDataModelAttached(QObject *parent)
- : QObject(parent)
- , m_cacheItem(0)
- , m_previousGroups(0)
- , m_modelChanged(false)
- {}
- ~QQuickVisualDataModelAttached() { attachedProperties.remove(parent()); }
-
- void setCacheItem(QQuickVisualDataModelCacheItem *item);
-
- QQuickVisualDataModel *model() const;
-
- QStringList groups() const;
- void setGroups(const QStringList &groups);
-
- void emitChanges();
-
- static QQuickVisualDataModelAttached *properties(QObject *obj)
- {
- QQuickVisualDataModelAttached *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QQuickVisualDataModelAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
- }
-
-Q_SIGNALS:
- void modelChanged();
- void groupsChanged();
-
-public:
- QQuickVisualDataModelCacheItem *m_cacheItem;
- int m_previousGroups;
- int m_previousIndex[QDeclarativeListCompositor::MaximumGroupCount];
- bool m_modelChanged;
-
- static QHash<QObject*, QQuickVisualDataModelAttached*> attachedProperties;
-
- friend class QQuickVisualDataModelAttachedMetaObject;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickVisualDataModel)
-QML_DECLARE_TYPEINFO(QQuickVisualDataModel, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQuickVisualDataGroup)
-
-QT_END_HEADER
-
-#endif // QQUICKVISUALDATAMODEL_P_H
diff --git a/src/declarative/items/qquickvisualitemmodel_p.h b/src/declarative/items/qquickvisualitemmodel_p.h
deleted file mode 100644
index 3d9610abe9..0000000000
--- a/src/declarative/items/qquickvisualitemmodel_p.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QQUICKVISUALITEMMODEL_P_H
-#define QQUICKVISUALITEMMODEL_P_H
-
-#include <QtDeclarative/qdeclarative.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QDeclarativeChangeSet;
-
-class Q_DECLARATIVE_EXPORT QQuickVisualModel : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-public:
- virtual ~QQuickVisualModel() {}
-
- enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
- Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
-
- virtual int count() const = 0;
- virtual bool isValid() const = 0;
- virtual QQuickItem *item(int index, bool asynchronous=false) = 0;
- virtual ReleaseFlags release(QQuickItem *item) = 0;
- virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
-
- virtual int indexOf(QQuickItem *item, QObject *objectContext) const = 0;
-
-Q_SIGNALS:
- void countChanged();
- void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
- void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
- void destroyingItem(QQuickItem *item);
-
-protected:
- QQuickVisualModel(QObjectPrivate &dd, QObject *parent = 0)
- : QObject(dd, parent) {}
-
-private:
- Q_DISABLE_COPY(QQuickVisualModel)
-};
-
-class QQuickVisualItemModelAttached;
-class QQuickVisualItemModelPrivate;
-class Q_DECLARATIVE_EXPORT QQuickVisualItemModel : public QQuickVisualModel
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickVisualItemModel)
-
- Q_PROPERTY(QDeclarativeListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "children")
-
-public:
- QQuickVisualItemModel(QObject *parent=0);
- virtual ~QQuickVisualItemModel() {}
-
- virtual int count() const;
- virtual bool isValid() const;
- virtual QQuickItem *item(int index, bool asynchronous=false);
- virtual ReleaseFlags release(QQuickItem *item);
- virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray>) {}
-
- virtual int indexOf(QQuickItem *item, QObject *objectContext) const;
-
- QDeclarativeListProperty<QQuickItem> children();
-
- static QQuickVisualItemModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void childrenChanged();
-
-private:
- Q_DISABLE_COPY(QQuickVisualItemModel)
-};
-
-class QQuickVisualItemModelAttached : public QObject
-{
- Q_OBJECT
-
-public:
- QQuickVisualItemModelAttached(QObject *parent)
- : QObject(parent), m_index(0) {}
- ~QQuickVisualItemModelAttached() {
- attachedProperties.remove(parent());
- }
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- int index() const { return m_index; }
- void setIndex(int idx) {
- if (m_index != idx) {
- m_index = idx;
- emit indexChanged();
- }
- }
-
- static QQuickVisualItemModelAttached *properties(QObject *obj) {
- QQuickVisualItemModelAttached *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QQuickVisualItemModelAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
- }
-
-Q_SIGNALS:
- void indexChanged();
-
-public:
- int m_index;
-
- static QHash<QObject*, QQuickVisualItemModelAttached*> attachedProperties;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickVisualModel)
-QML_DECLARE_TYPE(QQuickVisualItemModel)
-QML_DECLARE_TYPEINFO(QQuickVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-
-#endif // QQUICKVISUALITEMMODEL_P_H
diff --git a/src/declarative/items/qquickwindowmodule.cpp b/src/declarative/items/qquickwindowmodule.cpp
deleted file mode 100644
index 7a7f28cb43..0000000000
--- a/src/declarative/items/qquickwindowmodule.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 "qquickwindowmodule_p.h"
-#include <QQuickCanvas>
-
-QT_BEGIN_NAMESPACE
-
-void QQuickWindowModule::defineModule()
-{
- const char* uri = "QtQuick.Window";
-
- qmlRegisterType<QQuickCanvas>(uri, 2, 0, "Window");
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/particles/qquickage_p.h b/src/declarative/particles/qquickage_p.h
deleted file mode 100644
index 0adbddabe9..0000000000
--- a/src/declarative/particles/qquickage_p.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 KILLAFFECTOR_H
-#define KILLAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickAgeAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(int lifeLeft READ lifeLeft WRITE setLifeLeft NOTIFY lifeLeftChanged)
- Q_PROPERTY(bool advancePosition READ advancePosition WRITE setAdvancePosition NOTIFY advancePositionChanged)
-
-public:
- explicit QQuickAgeAffector(QQuickItem *parent = 0);
-
- int lifeLeft() const
- {
- return m_lifeLeft;
- }
-
- bool advancePosition() const
- {
- return m_advancePosition;
- }
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-signals:
- void lifeLeftChanged(int arg);
- void advancePositionChanged(bool arg);
-
-public slots:
- void setLifeLeft(int arg)
- {
- if (m_lifeLeft != arg) {
- m_lifeLeft = arg;
- emit lifeLeftChanged(arg);
- }
- }
-
- void setAdvancePosition(bool arg)
- {
- if (m_advancePosition != arg) {
- m_advancePosition = arg;
- emit advancePositionChanged(arg);
- }
- }
-
-private:
- int m_lifeLeft;
- bool m_advancePosition;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // KILLAFFECTOR_H
diff --git a/src/declarative/particles/qquickangledirection_p.h b/src/declarative/particles/qquickangledirection_p.h
deleted file mode 100644
index 7baf1a6c60..0000000000
--- a/src/declarative/particles/qquickangledirection_p.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQuickANGLEDDIRECTION_H
-#define QQuickANGLEDDIRECTION_H
-#include "qquickdirection_p.h"
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickAngleDirection : public QQuickDirection
-{
- Q_OBJECT
- Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
- Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
- Q_PROPERTY(qreal angleVariation READ angleVariation WRITE setAngleVariation NOTIFY angleVariationChanged)
- Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
-public:
- explicit QQuickAngleDirection(QObject *parent = 0);
- const QPointF sample(const QPointF &from);
- qreal angle() const
- {
- return m_angle;
- }
-
- qreal magnitude() const
- {
- return m_magnitude;
- }
-
- qreal angleVariation() const
- {
- return m_angleVariation;
- }
-
- qreal magnitudeVariation() const
- {
- return m_magnitudeVariation;
- }
-
-signals:
-
- void angleChanged(qreal arg);
-
- void magnitudeChanged(qreal arg);
-
- void angleVariationChanged(qreal arg);
-
- void magnitudeVariationChanged(qreal arg);
-
-public slots:
-void setAngle(qreal arg)
-{
- if (m_angle != arg) {
- m_angle = arg;
- emit angleChanged(arg);
- }
-}
-
-void setMagnitude(qreal arg)
-{
- if (m_magnitude != arg) {
- m_magnitude = arg;
- emit magnitudeChanged(arg);
- }
-}
-
-void setAngleVariation(qreal arg)
-{
- if (m_angleVariation != arg) {
- m_angleVariation = arg;
- emit angleVariationChanged(arg);
- }
-}
-
-void setMagnitudeVariation(qreal arg)
-{
- if (m_magnitudeVariation != arg) {
- m_magnitudeVariation = arg;
- emit magnitudeVariationChanged(arg);
- }
-}
-
-private:
-qreal m_angle;
-qreal m_magnitude;
-qreal m_angleVariation;
-qreal m_magnitudeVariation;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // QQuickANGLEDDIRECTION_H
diff --git a/src/declarative/particles/qquickcumulativedirection_p.h b/src/declarative/particles/qquickcumulativedirection_p.h
deleted file mode 100644
index af657821c2..0000000000
--- a/src/declarative/particles/qquickcumulativedirection_p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQuickCUMULATIVEDIRECTION_P_H
-#define QQuickCUMULATIVEDIRECTION_P_H
-#include "qquickdirection_p.h"
-#include <QDeclarativeListProperty>
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickCumulativeDirection : public QQuickDirection
-{
- Q_OBJECT
- Q_PROPERTY(QDeclarativeListProperty<QQuickDirection> directions READ directions)
- Q_CLASSINFO("DefaultProperty", "directions")
-public:
- explicit QQuickCumulativeDirection(QObject *parent = 0);
- QDeclarativeListProperty<QQuickDirection> directions();
- const QPointF sample(const QPointF &from);
-private:
- QList<QQuickDirection*> m_directions;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQuickCUMULATIVEDIRECTION_P_H
diff --git a/src/declarative/particles/qquickcustomaffector_p.h b/src/declarative/particles/qquickcustomaffector_p.h
deleted file mode 100644
index e347107f50..0000000000
--- a/src/declarative/particles/qquickcustomaffector_p.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 CUSTOMAFFECTOR_H
-#define CUSTOMAFFECTOR_H
-
-#include <QObject>
-#include "qquickparticlesystem_p.h"
-#include "qquickparticleextruder_p.h"
-#include "qquickparticleaffector_p.h"
-#include "qquickdirection_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickCustomAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(bool relative READ relative WRITE setRelative NOTIFY relativeChanged)
- Q_PROPERTY(QQuickDirection *position READ position WRITE setPosition NOTIFY positionChanged RESET positionReset)
- Q_PROPERTY(QQuickDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged RESET speedReset)
- Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged RESET accelerationReset)
-
-public:
- explicit QQuickCustomAffector(QQuickItem *parent = 0);
- virtual void affectSystem(qreal dt);
-
- QQuickDirection * position() const
- {
- return m_position;
- }
-
- QQuickDirection * speed() const
- {
- return m_speed;
- }
-
- QQuickDirection * acceleration() const
- {
- return m_acceleration;
- }
-
- void positionReset()
- {
- m_position = &m_nullVector;
- }
-
- void speedReset()
- {
- m_speed = &m_nullVector;
- }
-
- void accelerationReset()
- {
- m_acceleration = &m_nullVector;
- }
-
- bool relative() const
- {
- return m_relative;
- }
-
-
-signals:
- void affectParticles(QDeclarativeV8Handle particles, qreal dt);
-
- void positionChanged(QQuickDirection * arg);
-
- void speedChanged(QQuickDirection * arg);
-
- void accelerationChanged(QQuickDirection * arg);
-
- void relativeChanged(bool arg);
-
-public slots:
- void setPosition(QQuickDirection * arg)
- {
- if (m_position != arg) {
- m_position = arg;
- emit positionChanged(arg);
- }
- }
-
- void setSpeed(QQuickDirection * arg)
- {
- if (m_speed != arg) {
- m_speed = arg;
- emit speedChanged(arg);
- }
- }
-
- void setAcceleration(QQuickDirection * arg)
- {
- if (m_acceleration != arg) {
- m_acceleration = arg;
- emit accelerationChanged(arg);
- }
- }
-
- void setRelative(bool arg)
- {
- if (m_relative != arg) {
- m_relative = arg;
- emit relativeChanged(arg);
- }
- }
-
-protected:
- bool isAffectConnected();
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-private:
- void affectProperties(const QList<QQuickParticleData*> particles, qreal dt);
- QQuickDirection * m_position;
- QQuickDirection * m_speed;
- QQuickDirection * m_acceleration;
-
- QQuickDirection m_nullVector;
- bool m_relative;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // CUSTOMAFFECTOR_H
diff --git a/src/declarative/particles/qquickcustomparticle.cpp b/src/declarative/particles/qquickcustomparticle.cpp
deleted file mode 100644
index 153dd273b6..0000000000
--- a/src/declarative/particles/qquickcustomparticle.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qquickcustomparticle_p.h"
-#include <private/qquickshadereffectmesh_p.h>
-#include <cstdlib>
-
-QT_BEGIN_NAMESPACE
-
-//Includes comments because the code isn't self explanatory
-static const char qt_particles_template_vertex_code[] =
- "attribute highp vec2 qt_ParticlePos;\n"
- "attribute highp vec2 qt_ParticleTex;\n"
- "attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize\n"
- "attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration\n"
- "attribute highp float qt_ParticleR;\n"
- "uniform highp mat4 qt_Matrix;\n"
- "uniform highp float qt_Timestamp;\n"
- "varying highp vec2 qt_TexCoord0;\n"
- "void defaultMain() {\n"
- " qt_TexCoord0 = qt_ParticleTex;\n"
- " highp float size = qt_ParticleData.z;\n"
- " highp float endSize = qt_ParticleData.w;\n"
- " highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;\n"
- " highp float currentSize = mix(size, endSize, t * t);\n"
- " if (t < 0. || t > 1.)\n"
- " currentSize = 0.;\n"
- " highp vec2 pos = qt_ParticlePos\n"
- " - currentSize / 2. + currentSize * qt_ParticleTex // adjust size\n"
- " + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..\n"
- " + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);\n"
- " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
- "}";
-static const char qt_particles_default_vertex_code[] =
- "void main() { \n"
- " defaultMain(); \n"
- "}";
-
-static const char qt_particles_default_fragment_code[] =
- "uniform sampler2D source; \n"
- "varying highp vec2 qt_TexCoord0; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
- "}";
-
-static QSGGeometry::Attribute PlainParticle_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
- QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
- QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
- QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
- QSGGeometry::Attribute::create(4, 1, GL_FLOAT) // r
-};
-
-static QSGGeometry::AttributeSet PlainParticle_AttributeSet =
-{
- 5, // Attribute Count
- (2 + 2 + 4 + 4 + 1) * sizeof(float),
- PlainParticle_Attributes
-};
-
-struct PlainVertex {
- float x;
- float y;
- float tx;
- float ty;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
- float r;
-};
-
-struct PlainVertices {
- PlainVertex v1;
- PlainVertex v2;
- PlainVertex v3;
- PlainVertex v4;
-};
-
-/*!
- \qmlclass CustomParticle QQuickCustomParticle
- \inqmlmodule QtQuick.Particles 2
- \inherits ParticlePainter
- \brief The CustomParticle element allows you to specify your own shader to paint particles.
-
-*/
-
-QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent)
- : QQuickParticlePainter(parent)
- , m_dirtyData(true)
- , m_material(0)
- , m_rootNode(0)
-{
- setFlag(QQuickItem::ItemHasContents);
-}
-
-class QQuickShaderEffectMaterialObject : public QObject, public QQuickShaderEffectMaterial { };
-
-QQuickCustomParticle::~QQuickCustomParticle()
-{
- if (m_material)
- m_material->deleteLater();
-}
-
-void QQuickCustomParticle::componentComplete()
-{
- reset();
- QQuickParticlePainter::componentComplete();
-}
-
-
-//Trying to keep the shader conventions the same as in qsgshadereffectitem
-/*!
- \qmlproperty string QtQuick.Particles2::CustomParticle::fragmentShader
-
- This property holds the fragment shader's GLSL source code.
- The default shader expects the texture coordinate to be passed from the
- vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
- sampler2D named "source".
-*/
-
-void QQuickCustomParticle::setFragmentShader(const QByteArray &code)
-{
- if (m_source.fragmentCode.constData() == code.constData())
- return;
- m_source.fragmentCode = code;
- if (isComponentComplete()) {
- reset();
- }
- emit fragmentShaderChanged();
-}
-
-/*!
- \qmlproperty string QtQuick.Particles2::CustomParticle::vertexShader
-
- This property holds the vertex shader's GLSL source code.
-
- The default shader passes the texture coordinate along to the fragment
- shader as "varying highp vec2 qt_TexCoord0".
-
- To aid writing a particle vertex shader, the following GLSL code is prepended
- to your vertex shader:
- \code
- attribute highp vec2 qt_ParticlePos;
- attribute highp vec2 qt_ParticleTex;
- attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
- attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration
- attribute highp float qt_ParticleR;
- uniform highp mat4 qt_Matrix;
- uniform highp float qt_Timestamp;
- varying highp vec2 qt_TexCoord0;
- void defaultMain() {
- qt_TexCoord0 = qt_ParticleTex;
- highp float size = qt_ParticleData.z;
- highp float endSize = qt_ParticleData.w;
- highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
- highp float currentSize = mix(size, endSize, t * t);
- if (t < 0. || t > 1.)
- currentSize = 0.;
- highp vec2 pos = qt_ParticlePos
- - currentSize / 2. + currentSize * qt_ParticleTex // adjust size
- + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..
- + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
- gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- }
- \endcode
-
- defaultMain() is the same code as in the default shader, you can call this for basic
- particle functions and then add additional variables for custom effects. Note that
- the vertex shader for particles is responsible for simulating the movement of particles
- over time, the particle data itself only has the starting position and spawn time.
-*/
-
-void QQuickCustomParticle::setVertexShader(const QByteArray &code)
-{
- if (m_source.vertexCode.constData() == code.constData())
- return;
- m_source.vertexCode = code;
- if (isComponentComplete()) {
- reset();
- }
- emit vertexShaderChanged();
-}
-
-void QQuickCustomParticle::reset()
-{
- disconnectPropertySignals();
-
- m_source.attributeNames.clear();
- m_source.uniformNames.clear();
- m_source.respectsOpacity = false;
- m_source.respectsMatrix = false;
- m_source.className = metaObject()->className();
-
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- delete source.mapper;
- if (source.item && source.item->parentItem() == this)
- source.item->setParentItem(0);
- }
- m_sources.clear();
-
- QQuickParticlePainter::reset();
- m_pleaseReset = true;
- update();
-}
-
-
-void QQuickCustomParticle::changeSource(int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
- QVariant v = property(m_sources.at(index).name.constData());
- setSource(v, index);
-}
-
-void QQuickCustomParticle::updateData()
-{
- m_dirtyData = true;
- update();
-}
-
-void QQuickCustomParticle::setSource(const QVariant &var, int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
-
- SourceData &source = m_sources[index];
-
- source.item = 0;
- if (var.isNull()) {
- return;
- } else if (!qVariantCanConvert<QObject *>(var)) {
- qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
- return;
- }
-
- QObject *obj = qVariantValue<QObject *>(var);
- source.item = qobject_cast<QQuickItem *>(obj);
- if (!source.item || !source.item->isTextureProvider()) {
- qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
- source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
- return;
- }
-
- // TODO: Copy better solution in QQuickShaderEffect when they find it.
- // 'source.item' needs a canvas to get a scenegraph node.
- // The easiest way to make sure it gets a canvas is to
- // make it a part of the same item tree as 'this'.
- if (source.item && source.item->parentItem() == 0) {
- source.item->setParentItem(this);
- source.item->setVisible(false);
- }
-}
-
-void QQuickCustomParticle::disconnectPropertySignals()
-{
- disconnect(this, 0, this, SLOT(updateData()));
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- disconnect(this, 0, source.mapper, 0);
- disconnect(source.mapper, 0, this, 0);
- }
-}
-
-void QQuickCustomParticle::connectPropertySignals()
-{
- QSet<QByteArray>::const_iterator it;
- for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
- int pi = metaObject()->indexOfProperty(it->constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- if (!mp.hasNotifySignal())
- qWarning("QQuickCustomParticle: property '%s' does not have notification method!", it->constData());
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().signature());
- connect(this, signalName, this, SLOT(updateData()));
- } else {
- qWarning("QQuickCustomParticle: '%s' does not have a matching property!", it->constData());
- }
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- int pi = metaObject()->indexOfProperty(source.name.constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().signature());
- connect(this, signalName, source.mapper, SLOT(map()));
- source.mapper->setMapping(this, i);
- connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
- } else {
- qWarning("QQuickCustomParticle: '%s' does not have a matching source!", source.name.constData());
- }
- }
-}
-
-void QQuickCustomParticle::updateProperties()
-{
- QByteArray vertexCode = m_source.vertexCode;
- QByteArray fragmentCode = m_source.fragmentCode;
- if (vertexCode.isEmpty())
- vertexCode = qt_particles_default_vertex_code;
- if (fragmentCode.isEmpty())
- fragmentCode = qt_particles_default_fragment_code;
- vertexCode = qt_particles_template_vertex_code + vertexCode;
-
- m_source.attributeNames.clear();
- m_source.attributeNames << "qt_ParticlePos"
- << "qt_ParticleTex"
- << "qt_ParticleData"
- << "qt_ParticleVec"
- << "qt_ParticleR";
-
- lookThroughShaderCode(vertexCode);
- lookThroughShaderCode(fragmentCode);
-
- if (!m_source.respectsMatrix)
- qWarning("QQuickCustomParticle: Missing reference to \'qt_Matrix\'.");
- if (!m_source.respectsOpacity)
- qWarning("QQuickCustomParticle: Missing reference to \'qt_Opacity\'.");
-
- for (int i = 0; i < m_sources.size(); ++i) {
- QVariant v = property(m_sources.at(i).name);
- setSource(v, i);
- }
-
- connectPropertySignals();
-}
-
-void QQuickCustomParticle::lookThroughShaderCode(const QByteArray &code)
-{
- // Regexp for matching attributes and uniforms.
- // In human readable form: attribute|uniform [lowp|mediump|highp] <type> <name>
- static QRegExp re(QLatin1String("\\b(attribute|uniform)\\b\\s*\\b(?:lowp|mediump|highp)?\\b\\s*\\b(\\w+)\\b\\s*\\b(\\w+)"));
- Q_ASSERT(re.isValid());
-
- int pos = -1;
-
- QString wideCode = QString::fromLatin1(code.constData(), code.size());
-
- while ((pos = re.indexIn(wideCode, pos + 1)) != -1) {
- QByteArray decl = re.cap(1).toLatin1(); // uniform or attribute
- QByteArray type = re.cap(2).toLatin1(); // type
- QByteArray name = re.cap(3).toLatin1(); // variable name
-
- if (decl == "attribute") {
- if (!m_source.attributeNames.contains(name))
- qWarning() << "Custom Particle: Unknown attribute " << name;
- } else {
- Q_ASSERT(decl == "uniform");//TODO: Shouldn't assert
-
- if (name == "qt_Matrix") {
- m_source.respectsMatrix = true;
- } else if (name == "qt_Opacity") {
- m_source.respectsOpacity = true;
- } else if (name == "qt_Timestamp") {
- //Not strictly necessary
- } else {
- m_source.uniformNames.insert(name);
- if (type == "sampler2D") {
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.item = 0;
- m_sources.append(d);
- }
- }
- }
- }
-}
-
-QSGNode *QQuickCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- Q_UNUSED(oldNode);
- if (m_pleaseReset){
-
- //delete m_material;//Shader effect item doesn't regen material?
-
- delete m_rootNode;//Automatically deletes children
- m_rootNode = 0;
- m_nodes.clear();
- m_pleaseReset = false;
- m_dirtyData = false;
- }
-
- if (m_system && m_system->isRunning() && !m_system->isPaused()){
- prepareNextFrame();
- if (m_rootNode) {
- update();
- foreach (QSGGeometryNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyGeometry);//done in buildData?
- }
- }
-
- return m_rootNode;
-}
-
-void QQuickCustomParticle::prepareNextFrame(){
- if (!m_rootNode)
- m_rootNode = buildCustomNodes();
- if (!m_rootNode)
- return;
-
- m_lastTime = m_system->systemSync(this) / 1000.;
- if (m_dirtyData || true)//Currently this is how we update timestamp... potentially over expensive.
- buildData();
-}
-
-QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
-{
-#ifdef QT_OPENGL_ES_2
- if (m_count * 4 > 0xffff) {
- printf("CustomParticle: Too many particles... \n");
- return 0;
- }
-#endif
-
- if (m_count <= 0) {
- printf("CustomParticle: Too few particles... \n");
- return 0;
- }
-
- updateProperties();
-
- QQuickShaderEffectProgram s = m_source;
- if (s.fragmentCode.isEmpty())
- s.fragmentCode = qt_particles_default_fragment_code;
- if (s.vertexCode.isEmpty())
- s.vertexCode = qt_particles_default_vertex_code;
-
- if (!m_material) {
- m_material = new QQuickShaderEffectMaterialObject;
- }
-
- s.vertexCode = qt_particles_template_vertex_code + s.vertexCode;
- m_material->setProgramSource(s);
- foreach (const QString &str, m_groups){
- int gIdx = m_system->groupIds[str];
- int count = m_system->groupData[gIdx]->size();
-
- QQuickShaderEffectNode* node = new QQuickShaderEffectNode();
- m_nodes.insert(gIdx, node);
-
- node->setMaterial(m_material);
- node->markDirty(QSGNode::DirtyMaterial);
-
- //Create Particle Geometry
- int vCount = count * 4;
- int iCount = count * 6;
- QSGGeometry *g = new QSGGeometry(PlainParticle_AttributeSet, vCount, iCount);
- g->setDrawingMode(GL_TRIANGLES);
- node->setGeometry(g);
- PlainVertex *vertices = (PlainVertex *) g->vertexData();
- for (int p=0; p < count; ++p) {
- commit(gIdx, p);
- vertices[0].tx = 0;
- vertices[0].ty = 0;
-
- vertices[1].tx = 1;
- vertices[1].ty = 0;
-
- vertices[2].tx = 0;
- vertices[2].ty = 1;
-
- vertices[3].tx = 1;
- vertices[3].ty = 1;
- vertices += 4;
- }
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
- }
- }
- foreach (QQuickShaderEffectNode* node, m_nodes){
- if (node == *(m_nodes.begin()))
- continue;
- (*(m_nodes.begin()))->appendChildNode(node);
- }
-
- return *(m_nodes.begin());
-}
-
-
-void QQuickCustomParticle::buildData()
-{
- if (!m_rootNode)
- return;
- const QByteArray timestampName("qt_Timestamp");
- QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material->textureProviders();
- for (int i = 0; i < oldTextures.size(); ++i) {
- QSGTextureProvider *t = oldTextures.at(i).second;
- if (t)
- foreach (QQuickShaderEffectNode* node, m_nodes)
- disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = source.item->textureProvider();
- textures.append(qMakePair(source.name, t));
- if (t)
- foreach (QQuickShaderEffectNode* node, m_nodes)
- connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
- }
- for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
- it != m_source.uniformNames.end(); ++it) {
- values.append(qMakePair(*it, property(*it)));
- }
- values.append(qMakePair(timestampName, QVariant(m_lastTime)));
- m_material->setUniforms(values);
- m_material->setTextureProviders(textures);
- m_dirtyData = false;
- foreach (QQuickShaderEffectNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyMaterial);
-}
-
-void QQuickCustomParticle::initialize(int gIdx, int pIdx)
-{
- QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
- datum->r = rand()/(qreal)RAND_MAX;
-}
-
-void QQuickCustomParticle::commit(int gIdx, int pIdx)
-{
- if (m_nodes[gIdx] == 0)
- return;
-
- QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
- PlainVertices *particles = (PlainVertices *) m_nodes[gIdx]->geometry()->vertexData();
- PlainVertex *vertices = (PlainVertex *)&particles[pIdx];
- for (int i=0; i<4; ++i) {
- vertices[i].x = datum->x - m_systemOffset.x();
- vertices[i].y = datum->y - m_systemOffset.y();
- vertices[i].t = datum->t;
- vertices[i].lifeSpan = datum->lifeSpan;
- vertices[i].size = datum->size;
- vertices[i].endSize = datum->endSize;
- vertices[i].vx = datum->vx;
- vertices[i].vy = datum->vy;
- vertices[i].ax = datum->ax;
- vertices[i].ay = datum->ay;
- vertices[i].r = datum->r;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qquickcustomparticle_p.h b/src/declarative/particles/qquickcustomparticle_p.h
deleted file mode 100644
index b3cf6d3e42..0000000000
--- a/src/declarative/particles/qquickcustomparticle_p.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 CUSTOM_PARTICLE_H
-#define CUSTOM_PARTICLE_H
-#include "qquickparticlepainter_p.h"
-#include <private/qquickshadereffectnode_p.h>
-#include <QSignalMapper>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGNode;
-struct PlainVertices;
-
-class QQuickShaderEffectMaterialObject;
-
-//Genealogy: Hybrid of UltraParticle and ShaderEffect
-class QQuickCustomParticle : public QQuickParticlePainter
-{
- Q_OBJECT
- Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
- Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
-
-public:
- explicit QQuickCustomParticle(QQuickItem* parent=0);
- ~QQuickCustomParticle();
-
- QByteArray fragmentShader() const { return m_source.fragmentCode; }
- void setFragmentShader(const QByteArray &code);
-
- QByteArray vertexShader() const { return m_source.vertexCode; }
- void setVertexShader(const QByteArray &code);
-public Q_SLOTS:
- void updateData();
- void changeSource(int);
-Q_SIGNALS:
- void fragmentShaderChanged();
- void vertexShaderChanged();
-protected:
- virtual void initialize(int gIdx, int pIdx);
- virtual void commit(int gIdx, int pIdx);
-
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void prepareNextFrame();
- void setSource(const QVariant &var, int index);
- void disconnectPropertySignals();
- void connectPropertySignals();
- void reset();
- void resize(int oldCount, int newCount);
- void updateProperties();
- void lookThroughShaderCode(const QByteArray &code);
- virtual void componentComplete();
- QQuickShaderEffectNode *buildCustomNodes();
- void performPendingResize();
-
-private:
- void buildData();
-
- bool m_dirtyData;
- QQuickShaderEffectProgram m_source;
- struct SourceData
- {
- QSignalMapper *mapper;
- QPointer<QQuickItem> item;
- QByteArray name;
- };
- QVector<SourceData> m_sources;
- QQuickShaderEffectMaterialObject *m_material;
- QQuickShaderEffectNode* m_rootNode;
- QHash<int, QQuickShaderEffectNode*> m_nodes;
- qreal m_lastTime;
-
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif //HEADER_GUARD
diff --git a/src/declarative/particles/qquickdirection_p.h b/src/declarative/particles/qquickdirection_p.h
deleted file mode 100644
index ac2ecdf9c1..0000000000
--- a/src/declarative/particles/qquickdirection_p.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 VARYINGVECTOR_H
-#define VARYINGVECTOR_H
-
-#include <QObject>
-#include <QPointF>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickDirection : public QObject
-{
- Q_OBJECT
-public:
- explicit QQuickDirection(QObject *parent = 0);
-
- virtual const QPointF sample(const QPointF &from);
-signals:
-
-public slots:
-
-protected:
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // VARYINGVECTOR_H
diff --git a/src/declarative/particles/qquickellipseextruder_p.h b/src/declarative/particles/qquickellipseextruder_p.h
deleted file mode 100644
index 08e7e73d18..0000000000
--- a/src/declarative/particles/qquickellipseextruder_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 ELLIPSEEXTRUDER_H
-#define ELLIPSEEXTRUDER_H
-#include "qquickparticleextruder_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickEllipseExtruder : public QQuickParticleExtruder
-{
- Q_OBJECT
- Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)//###Use base class? If it's still box
-public:
- explicit QQuickEllipseExtruder(QObject *parent = 0);
- virtual QPointF extrude(const QRectF &);
- virtual bool contains(const QRectF &bounds, const QPointF &point);
-
- bool fill() const
- {
- return m_fill;
- }
-
-signals:
-
- void fillChanged(bool arg);
-
-public slots:
-
- void setFill(bool arg)
- {
- if (m_fill != arg) {
- m_fill = arg;
- emit fillChanged(arg);
- }
- }
-private:
- bool m_fill;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // ELLIPSEEXTRUDER_H
diff --git a/src/declarative/particles/qquickfriction_p.h b/src/declarative/particles/qquickfriction_p.h
deleted file mode 100644
index c2f227692c..0000000000
--- a/src/declarative/particles/qquickfriction_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 FRICTIONAFFECTOR_H
-#define FRICTIONAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickFrictionAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(qreal factor READ factor WRITE setFactor NOTIFY factorChanged)
- Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged)
-public:
- explicit QQuickFrictionAffector(QQuickItem *parent = 0);
-
- qreal factor() const
- {
- return m_factor;
- }
-
- qreal threshold() const
- {
- return m_threshold;
- }
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-
-signals:
-
- void factorChanged(qreal arg);
- void thresholdChanged(qreal arg);
-
-public slots:
-
- void setFactor(qreal arg)
- {
- if (m_factor != arg) {
- m_factor = arg;
- emit factorChanged(arg);
- }
- }
-
- void setThreshold(qreal arg)
- {
- if (m_threshold != arg) {
- m_threshold = arg;
- emit thresholdChanged(arg);
- }
- }
-
-private:
- qreal m_factor;
- qreal m_threshold;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // FRICTIONAFFECTOR_H
diff --git a/src/declarative/particles/qquickgravity_p.h b/src/declarative/particles/qquickgravity_p.h
deleted file mode 100644
index 65f8e5a19d..0000000000
--- a/src/declarative/particles/qquickgravity_p.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 GRAVITYAFFECTOR_H
-#define GRAVITYAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickGravityAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
- Q_PROPERTY(qreal acceleration READ magnitude WRITE setAcceleration NOTIFY magnitudeChanged)
- Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
-public:
- explicit QQuickGravityAffector(QQuickItem *parent = 0);
- qreal magnitude() const
- {
- return m_magnitude;
- }
-
- qreal angle() const
- {
- return m_angle;
- }
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-signals:
-
- void magnitudeChanged(qreal arg);
-
- void angleChanged(qreal arg);
-
-public slots:
-void setAcceleration(qreal arg)
-{
- qWarning() << "Gravity::acceleration has been renamed Gravity::magnitude";
- if (m_magnitude != arg) {
- m_magnitude = arg;
- m_needRecalc = true;
- emit magnitudeChanged(arg);
- }
-}
-
-void setMagnitude(qreal arg)
-{
- if (m_magnitude != arg) {
- m_magnitude = arg;
- m_needRecalc = true;
- emit magnitudeChanged(arg);
- }
-}
-
-void setAngle(qreal arg)
-{
- if (m_angle != arg) {
- m_angle = arg;
- m_needRecalc = true;
- emit angleChanged(arg);
- }
-}
-
-private:
- qreal m_magnitude;
- qreal m_angle;
-
- bool m_needRecalc;
- qreal m_dx;
- qreal m_dy;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // GRAVITYAFFECTOR_H
diff --git a/src/declarative/particles/qquickgroupgoal_p.h b/src/declarative/particles/qquickgroupgoal_p.h
deleted file mode 100644
index 51ce1ff24e..0000000000
--- a/src/declarative/particles/qquickgroupgoal_p.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 GROUPGOALAFFECTOR_H
-#define GROUPGOALAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickStochasticEngine;
-
-class QQuickGroupGoalAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
- Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
-public:
- explicit QQuickGroupGoalAffector(QQuickItem *parent = 0);
-
- QString goalState() const
- {
- return m_goalState;
- }
-
- bool jump() const
- {
- return m_jump;
- }
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-
-signals:
-
- void goalStateChanged(QString arg);
-
- void jumpChanged(bool arg);
-
-public slots:
-
- void setGoalState(QString arg);
-
- void setJump(bool arg)
- {
- if (m_jump != arg) {
- m_jump = arg;
- emit jumpChanged(arg);
- }
- }
-
-private:
- QString m_goalState;
- bool m_jump;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // GROUPGOALAFFECTOR_H
diff --git a/src/declarative/particles/qquickimageparticle.cpp b/src/declarative/particles/qquickimageparticle.cpp
deleted file mode 100644
index 5f31440441..0000000000
--- a/src/declarative/particles/qquickimageparticle.cpp
+++ /dev/null
@@ -1,1803 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 <private/qsgcontext_p.h>
-#include <private/qsgadaptationlayer_p.h>
-#include <qsgnode.h>
-#include <qsgtexturematerial.h>
-#include <qsgtexture.h>
-#include <QFile>
-#include "qquickimageparticle_p.h"
-#include "qquickparticleemitter_p.h"
-#include <private/qquicksprite_p.h>
-#include <private/qquickspriteengine_p.h>
-#include <QOpenGLFunctions>
-#include <qsgengine.h>
-#include <private/qsgtexture_p.h>
-
-QT_BEGIN_NAMESPACE
-//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
-DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
-
-#ifndef QT_OPENGL_ES_2
-#define SHADER_DEFINES "#version 120\n"
-#else
-#define SHADER_DEFINES ""
-#endif
-
-//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
-#define UNIFORM_ARRAY_SIZE 64
-
-static const char vertexShaderCode[] =
- "attribute highp vec2 vPos;\n"
- "attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize\n"
- "attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration\n"
- "uniform highp float entry;\n"
- "#ifdef COLOR\n"
- "attribute lowp vec4 vColor;\n"
- "#endif\n"
- "#ifdef DEFORM\n"
- "attribute highp vec2 vTex;\n"
- "attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector\n"
- "attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate\n"
- "#endif\n"
- "#ifdef SPRITE\n"
- "attribute highp vec4 vAnimData;// interpolate(bool), duration, frameCount (this anim), timestamp (this anim)\n"
- "attribute highp vec4 vAnimPos;//sheet x,y, width/height of this anim\n"
- "uniform highp vec2 animSheetSize; //width/height of whole sheet\n"
- "#endif\n"
- "\n"
- "uniform highp mat4 qt_Matrix;\n"
- "uniform highp float timestamp;\n"
- "#ifdef TABLE\n"
- "varying lowp vec2 tt;//y is progress if Sprite mode\n"
- "uniform highp float sizetable[64];\n"
- "uniform highp float opacitytable[64];\n"
- "#endif\n"
- "#ifdef SPRITE\n"
- "varying highp vec4 fTexS;\n"
- "#else\n"
- "#ifdef DEFORM\n"
- "varying highp vec2 fTex;\n"
- "#endif\n"
- "#endif\n"
- "#ifdef COLOR\n"
- "varying lowp vec4 fColor;\n"
- "#else\n"
- "varying lowp float fFade;\n"
- "#endif\n"
- "\n"
- "\n"
- "void main() {\n"
- "\n"
- " highp float t = (timestamp - vData.x) / vData.y;\n"
- " if (t < 0. || t > 1.){\n"
- "#ifdef DEFORM //Not point sprites\n"
- " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);\n"
- "#else\n"
- " gl_PointSize = 0.;\n"
- "#endif\n"
- " return;\n"
- " }\n"
- "#ifdef SPRITE\n"
- " //Calculate frame location in texture\n"
- " highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);\n"
- " tt.y = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;\n"
- "\n"
- " frameIndex = floor(frameIndex);\n"
- " fTexS.xy = vec2(((frameIndex + vTex.x) * vAnimPos.z / animSheetSize.x), ((vAnimPos.y + vTex.y * vAnimPos.w) / animSheetSize.y));\n"
- "\n"
- " //Next frame is also passed, for interpolation\n"
- " //### Should the next anim be precalculated to allow for interpolation there?\n"
- " if (vAnimData.x == 1.0 && frameIndex != vAnimData.z - 1.)//Can't do it for the last frame though, this anim may not loop\n"
- " frameIndex = mod(frameIndex+1., vAnimData.z);\n"
- " fTexS.zw = vec2(((frameIndex + vTex.x) * vAnimPos.z / animSheetSize.x), ((vAnimPos.y + vTex.y * vAnimPos.w) / animSheetSize.y));\n"
- "#else\n"
- "#ifdef DEFORM\n"
- " fTex = vTex;\n"
- "#endif\n"
- "#endif\n"
- " highp float currentSize = mix(vData.z, vData.w, t * t);\n"
- " lowp float fade = 1.;\n"
- " highp float fadeIn = min(t * 10., 1.);\n"
- " highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);\n"
- "\n"
- "#ifdef TABLE\n"
- " currentSize = currentSize * sizetable[int(floor(t*64.))];\n"
- " fade = fade * opacitytable[int(floor(t*64.))];\n"
- "#endif\n"
- "\n"
- " if (entry == 1.)\n"
- " fade = fade * fadeIn * fadeOut;\n"
- " else if (entry == 2.)\n"
- " currentSize = currentSize * fadeIn * fadeOut;\n"
- "\n"
- " if (currentSize <= 0.){\n"
- "#ifdef DEFORM //Not point sprites\n"
- " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);\n"
- "#else\n"
- " gl_PointSize = 0.;\n"
- "#endif\n"
- " return;\n"
- " }\n"
- " if (currentSize < 3.)//Sizes too small look jittery as they move\n"
- " currentSize = 3.;\n"
- "\n"
- " highp vec2 pos;\n"
- "#ifdef DEFORM\n"
- " highp float rotation = vRotation.x + vRotation.y * t * vData.y;\n"
- " if (vRotation.z == 1.0){\n"
- " highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;\n"
- " rotation += atan(curVel.y, curVel.x);\n"
- " }\n"
- " highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));\n"
- " highp vec4 deform = vDeformVec * currentSize * (vTex.xxyy - 0.5);\n"
- " highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;\n"
- " rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));\n"
- " /* The readable version:\n"
- " highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);\n"
- " highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);\n"
- " highp vec2 xRotatedDeform;\n"
- " xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;\n"
- " xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;\n"
- " highp vec2 yRotatedDeform;\n"
- " yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;\n"
- " yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;\n"
- " */\n"
- " pos = vPos\n"
- " + rotatedDeform.xy\n"
- " + rotatedDeform.zw\n"
- " + vVec.xy * t * vData.y // apply speed\n"
- " + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration\n"
- "#else\n"
- " pos = vPos\n"
- " + vVec.xy * t * vData.y // apply speed vector..\n"
- " + 0.5 * vVec.zw * pow(t * vData.y, 2.);\n"
- " gl_PointSize = currentSize;\n"
- "#endif\n"
- " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
- "\n"
- "#ifdef COLOR\n"
- " fColor = vColor * fade;\n"
- "#else\n"
- " fFade = fade;\n"
- "#endif\n"
- "#ifdef TABLE\n"
- " tt.x = t;\n"
- "#endif\n"
- "}\n";
-
-static const char fragmentShaderCode[] =
- "uniform sampler2D texture;\n"
- "uniform lowp float qt_Opacity;\n"
- "\n"
- "#ifdef SPRITE\n"
- "varying highp vec4 fTexS;\n"
- "#else\n"
- "#ifdef DEFORM //First non-pointsprite\n"
- "varying highp vec2 fTex;\n"
- "#endif\n"
- "#endif\n"
- "#ifdef COLOR\n"
- "varying lowp vec4 fColor;\n"
- "#else\n"
- "varying lowp float fFade;\n"
- "#endif\n"
- "#ifdef TABLE\n"
- "varying lowp vec2 tt;\n"
- "uniform sampler2D colortable;\n"
- "#endif\n"
- "\n"
- "void main() {\n"
- "#ifdef SPRITE\n"
- " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)\n"
- " * fColor\n"
- " * texture2D(colortable, tt)\n"
- " * qt_Opacity;\n"
- "#else\n"
- "#ifdef TABLE\n"
- " gl_FragColor = texture2D(texture, fTex)\n"
- " * fColor\n"
- " * texture2D(colortable, tt)\n"
- " * qt_Opacity;\n"
- "#else\n"
- "#ifdef DEFORM\n"
- " gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;\n"
- "#else\n"
- "#ifdef COLOR\n"
- " gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;\n"
- "#else\n"
- " gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);\n"
- "#endif //COLOR\n"
- "#endif //DEFORM\n"
- "#endif //TABLE\n"
- "#endif //SPRITE\n"
- "}\n";
-
-const qreal CONV = 0.017453292519943295;
-class ImageMaterialData
-{
- public:
- ImageMaterialData()
- : texture(0), colorTable(0)
- {}
-
- ~ImageMaterialData(){
- delete texture;
- delete colorTable;
- }
-
- QSGTexture *texture;
- QSGTexture *colorTable;
- float sizeTable[UNIFORM_ARRAY_SIZE];
- float opacityTable[UNIFORM_ARRAY_SIZE];
-
- qreal timestamp;
- qreal entry;
- QSizeF animSheetSize;
-};
-
-class TabledMaterialData : public ImageMaterialData {};
-class TabledMaterial : public QSGSimpleMaterialShader<TabledMaterialData>
-{
- QSG_DECLARE_SIMPLE_SHADER(TabledMaterial, TabledMaterialData)
-
-public:
- TabledMaterial()
- {
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
-
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
-
- Q_ASSERT(!m_vertex_code.isNull());
- Q_ASSERT(!m_fragment_code.isNull());
- }
-
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- QList<QByteArray> attributes() const {
- return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
- << "vColor" << "vDeformVec" << "vRotation";
- };
-
- void initialize() {
- QSGSimpleMaterialShader<TabledMaterialData>::initialize();
- program()->bind();
- program()->setUniformValue("texture", 0);
- program()->setUniformValue("colortable", 1);
- glFuncs = QOpenGLContext::currentContext()->functions();
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_entry_id = program()->uniformLocation("entry");
- m_sizetable_id = program()->uniformLocation("sizetable");
- m_opacitytable_id = program()->uniformLocation("opacitytable");
- }
-
- void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
- glFuncs->glActiveTexture(GL_TEXTURE1);
- d->colorTable->bind();
-
- glFuncs->glActiveTexture(GL_TEXTURE0);
- d->texture->bind();
-
- program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
- program()->setUniformValue(m_entry_id, (float) d->entry);
- program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, UNIFORM_ARRAY_SIZE, 1);
- program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
- }
-
- int m_entry_id;
- int m_timestamp_id;
- int m_sizetable_id;
- int m_opacitytable_id;
- QByteArray m_vertex_code;
- QByteArray m_fragment_code;
- QOpenGLFunctions* glFuncs;
-};
-
-class DeformableMaterialData : public ImageMaterialData {};
-class DeformableMaterial : public QSGSimpleMaterialShader<DeformableMaterialData>
-{
- QSG_DECLARE_SIMPLE_SHADER(DeformableMaterial, DeformableMaterialData)
-
-public:
- DeformableMaterial()
- {
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
-
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
-
- Q_ASSERT(!m_vertex_code.isNull());
- Q_ASSERT(!m_fragment_code.isNull());
- }
-
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- QList<QByteArray> attributes() const {
- return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
- << "vColor" << "vDeformVec" << "vRotation";
- };
-
- void initialize() {
- QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
- program()->bind();
- program()->setUniformValue("texture", 0);
- glFuncs = QOpenGLContext::currentContext()->functions();
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_entry_id = program()->uniformLocation("entry");
- }
-
- void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) {
- glFuncs->glActiveTexture(GL_TEXTURE0);
- d->texture->bind();
-
- program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
- program()->setUniformValue(m_entry_id, (float) d->entry);
- }
-
- int m_entry_id;
- int m_timestamp_id;
- QByteArray m_vertex_code;
- QByteArray m_fragment_code;
- QOpenGLFunctions* glFuncs;
-};
-
-class SpriteMaterialData : public ImageMaterialData {};
-class SpriteMaterial : public QSGSimpleMaterialShader<SpriteMaterialData>
-{
- QSG_DECLARE_SIMPLE_SHADER(SpriteMaterial, SpriteMaterialData)
-
-public:
- SpriteMaterial()
- {
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
-
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
-
- Q_ASSERT(!m_vertex_code.isNull());
- Q_ASSERT(!m_fragment_code.isNull());
- }
-
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- QList<QByteArray> attributes() const {
- return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
- << "vColor" << "vDeformVec" << "vRotation" << "vAnimData" << "vAnimPos";
- };
-
- void initialize() {
- QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
- program()->bind();
- program()->setUniformValue("texture", 0);
- program()->setUniformValue("colortable", 1);
- glFuncs = QOpenGLContext::currentContext()->functions();
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_animsize_id = program()->uniformLocation("animSheetSize");
- m_entry_id = program()->uniformLocation("entry");
- m_sizetable_id = program()->uniformLocation("sizetable");
- m_opacitytable_id = program()->uniformLocation("opacitytable");
- }
-
- void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
- glFuncs->glActiveTexture(GL_TEXTURE1);
- d->colorTable->bind();
-
- // make sure we end by setting GL_TEXTURE0 as active texture
- glFuncs->glActiveTexture(GL_TEXTURE0);
- d->texture->bind();
-
- program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
- program()->setUniformValue(m_animsize_id, d->animSheetSize);
- program()->setUniformValue(m_entry_id, (float) d->entry);
- program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, 64, 1);
- program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
- }
-
- int m_timestamp_id;
- int m_animsize_id;
- int m_entry_id;
- int m_sizetable_id;
- int m_opacitytable_id;
- QByteArray m_vertex_code;
- QByteArray m_fragment_code;
- QOpenGLFunctions* glFuncs;
-};
-
-class ColoredMaterialData : public ImageMaterialData {};
-class ColoredMaterial : public QSGSimpleMaterialShader<ColoredMaterialData>
-{
- QSG_DECLARE_SIMPLE_SHADER(ColoredMaterial, ColoredMaterialData)
-
-public:
- ColoredMaterial()
- {
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define COLOR\n")
- + vertexShaderCode;
-
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define COLOR\n")
- + fragmentShaderCode;
-
- Q_ASSERT(!m_vertex_code.isNull());
- Q_ASSERT(!m_fragment_code.isNull());
- }
-
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- void activate() {
- QSGSimpleMaterialShader<ColoredMaterialData>::activate();
-#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
- glEnable(GL_POINT_SPRITE);
- glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
-#endif
- }
-
- void deactivate() {
- QSGSimpleMaterialShader<ColoredMaterialData>::deactivate();
-#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
- glDisable(GL_POINT_SPRITE);
- glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
-#endif
- }
-
- QList<QByteArray> attributes() const {
- return QList<QByteArray>() << "vPos" << "vData" << "vVec" << "vColor";
- }
-
- void initialize() {
- QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
- program()->bind();
- program()->setUniformValue("texture", 0);
- glFuncs = QOpenGLContext::currentContext()->functions();
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_entry_id = program()->uniformLocation("entry");
- }
-
- void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) {
- glFuncs->glActiveTexture(GL_TEXTURE0);
- d->texture->bind();
-
- program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
- program()->setUniformValue(m_entry_id, (float) d->entry);
- }
-
- int m_timestamp_id;
- int m_entry_id;
- QByteArray m_vertex_code;
- QByteArray m_fragment_code;
- QOpenGLFunctions* glFuncs;
-};
-
-class SimpleMaterialData : public ImageMaterialData {};
-class SimpleMaterial : public QSGSimpleMaterialShader<SimpleMaterialData>
-{
- QSG_DECLARE_SIMPLE_SHADER(SimpleMaterial, SimpleMaterialData)
-
-public:
- SimpleMaterial()
- {
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + vertexShaderCode;
-
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + fragmentShaderCode;
-
- Q_ASSERT(!m_vertex_code.isNull());
- Q_ASSERT(!m_fragment_code.isNull());
- }
-
- const char *vertexShader() const { return m_vertex_code.constData(); }
- const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- void activate() {
- QSGSimpleMaterialShader<SimpleMaterialData>::activate();
-#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
- glEnable(GL_POINT_SPRITE);
- glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
-#endif
- }
-
- void deactivate() {
- QSGSimpleMaterialShader<SimpleMaterialData>::deactivate();
-#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
- glDisable(GL_POINT_SPRITE);
- glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
-#endif
- }
-
- QList<QByteArray> attributes() const {
- return QList<QByteArray>() << "vPos" << "vData" << "vVec";
- }
-
- void initialize() {
- QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
- program()->bind();
- program()->setUniformValue("texture", 0);
- glFuncs = QOpenGLContext::currentContext()->functions();
- m_timestamp_id = program()->uniformLocation("timestamp");
- m_entry_id = program()->uniformLocation("entry");
- }
-
- void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) {
- glFuncs->glActiveTexture(GL_TEXTURE0);
- d->texture->bind();
-
- program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
- program()->setUniformValue(m_entry_id, (float) d->entry);
- }
-
- int m_timestamp_id;
- int m_entry_id;
- QByteArray m_vertex_code;
- QByteArray m_fragment_code;
- QOpenGLFunctions* glFuncs;
-};
-
-void fillUniformArrayFromImage(float* array, const QImage& img, int size)
-{
- if (img.isNull()){
- for (int i=0; i<size; i++)
- array[i] = 1.0;
- return;
- }
- QImage scaled = img.scaled(size,1);
- for (int i=0; i<size; i++)
- array[i] = qAlpha(scaled.pixel(i,0))/255.0;
-}
-
-/*!
- \qmlclass ImageParticle QQuickImageParticle
- \inqmlmodule QtQuick.Particles 2
- \inherits ParticlePainter
- \brief The ImageParticle element visualizes logical particles using an image
-
- This element renders a logical particle as an image. The image can be
- \list
- \o colorized
- \o rotated
- \o deformed
- \o a sprite-based animation
- \endlist
-
- ImageParticles implictly share data on particles if multiple ImageParticles are painting
- the same logical particle group. This is broken down along the four capabilities listed
- above. So if one ImageParticle defines data for rendering the particles in one of those
- capabilities, and the other does not, then both will draw the particles the same in that
- aspect automatically. This is primarily useful when there is some random variation on
- the particle which is supposed to stay with it when switching painters. If both ImageParticles
- define how they should appear for that aspect, they diverge and each appears as it is defined.
-
- This sharing of data happens behind the scenes based off of whether properties were implicitly or explicitly
- set. One drawback of the current implementation is that it is only possible to reset the capabilities as a whole.
- So if you explicity set an attribute affecting color, such as redVariation, and then reset it (by setting redVariation
- to undefined), all color data will be reset and it will begin to have an implicit value of any shared color from
- other ImageParticles.
-*/
-/*!
- \qmlproperty url QtQuick.Particles2::ImageParticle::source
-
- The source image to be used.
-
- If the image is a sprite animation, use the sprite property instead.
-*/
-/*!
- \qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
-
- The sprite or sprites used to draw this particle.
-
- Note that the sprite image will be scaled to a square based on the size of
- the particle being rendered.
-*/
-/*!
- \qmlproperty url QtQuick.Particles2::ImageParticle::colorTable
-
- An image whose color will be used as a 1D texture to determine color over life. E.g. when
- the particle is halfway through its lifetime, it will have the color specified halfway
- across the image.
-
- This color is blended with the color property and the color of the source image.
-*/
-/*!
- \qmlproperty url QtQuick.Particles2::ImageParticle::sizeTable
-
- An image whose opacity will be used as a 1D texture to determine size over life.
-
- This property is expected to be removed shortly, in favor of custom easing curves to determine size over life.
-*/
-/*!
- \qmlproperty url QtQuick.Particles2::ImageParticle::opacityTable
-
- An image whose opacity will be used as a 1D texture to determine size over life.
-
- This property is expected to be removed shortly, in favor of custom easing curves to determine opacity over life.
-*/
-/*!
- \qmlproperty color QtQuick.Particles2::ImageParticle::color
-
- If a color is specified, the provided image will be colorized with it.
-
- Default is white (no change).
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::colorVariation
-
- This number represents the color variation applied to individual particles.
- Setting colorVariation is the same as setting redVariation, greenVariation,
- and blueVariation to the same number.
-
- Each channel can vary between particle by up to colorVariation from its usual color.
-
- Color is measured, per channel, from 0.0 to 1.0.
-
- Default is 0.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::redVariation
- The variation in the red color channel between particles.
-
- Color is measured, per channel, from 0.0 to 1.0.
-
- Default is 0.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::greenVariation
- The variation in the green color channel between particles.
-
- Color is measured, per channel, from 0.0 to 1.0.
-
- Default is 0.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::blueVariation
- The variation in the blue color channel between particles.
-
- Color is measured, per channel, from 0.0 to 1.0.
-
- Default is 0.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::alpha
- An alpha to be applied to the image. This value is multiplied by the value in
- the image, and the value in the color property.
-
- Particles have additive blending, so lower alpha on single particles leads
- to stronger effects when multiple particles overlap.
-
- Alpha is measured from 0.0 to 1.0.
-
- Default is 1.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::alphaVariation
- The variation in the alpha channel between particles.
-
- Alpha is measured from 0.0 to 1.0.
-
- Default is 0.0
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::rotation
-
- If set the image will be rotated by this many degrees before it is drawn.
-
- The particle coordinates are not transformed.
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::rotationVariation
-
- If set the rotation of individual particles will vary by up to this much
- between particles.
-
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeed
-
- If set particles will rotate at this speed in degrees/second.
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeedVariation
-
- If set the rotationSpeed of individual particles will vary by up to this much
- between particles.
-
-*/
-/*!
- \qmlproperty bool QtQuick.Particles2::ImageParticle::autoRotation
-
- If set to true then a rotation will be applied on top of the particles rotation, so
- that it faces the direction of travel. So to face away from the direction of travel,
- set autoRotation to true and rotation to 180.
-
- Default is false
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::xVector
-
- Allows you to deform the particle image when drawn. The rectangular image will
- be deformed so that the horizontal sides are in the shape of this vector instead
- of (1,0).
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::yVector
-
- Allows you to deform the particle image when drawn. The rectangular image will
- be deformed so that the vertical sides are in the shape of this vector instead
- of (0,1).
-*/
-/*!
- \qmlproperty EntryEffect QtQuick.Particles2::ImageParticle::entryEffect
-
- This property provides basic and cheap entrance and exit effects for the particles.
- For fine-grained control, see sizeTable and opacityTable.
-
- Acceptable values are
- \list
- \o None: Particles just appear and disappear.
- \o Fade: Particles fade in from 0 opacity at the start of their life, and fade out to 0 at the end.
- \o Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end.
- \endlist
-
- Default value is Fade.
-*/
-/*!
- \qmlproperty bool QtQuick.Particles2::ImageParticle::spritesInterpolate
-
- If set to true, sprite particles will interpolate between sprite frames each rendered frame, making
- the sprites look smoother.
-
- Default is true.
-*/
-
-
-QQuickImageParticle::QQuickImageParticle(QQuickItem* parent)
- : QQuickParticlePainter(parent)
- , m_color_variation(0.0)
- , m_rootNode(0)
- , m_material(0)
- , m_alphaVariation(0.0)
- , m_alpha(1.0)
- , m_redVariation(0.0)
- , m_greenVariation(0.0)
- , m_blueVariation(0.0)
- , m_rotation(0)
- , m_rotationVariation(0)
- , m_rotationSpeed(0)
- , m_rotationSpeedVariation(0)
- , m_autoRotation(false)
- , m_xVector(0)
- , m_yVector(0)
- , m_spriteEngine(0)
- , m_spritesInterpolate(true)
- , m_explicitColor(false)
- , m_explicitRotation(false)
- , m_explicitDeformation(false)
- , m_explicitAnimation(false)
- , m_bloat(false)
- , perfLevel(Unknown)
- , m_lastLevel(Unknown)
- , m_debugMode(false)
- , m_entryEffect(Fade)
-{
- setFlag(ItemHasContents);
- m_debugMode = qmlParticlesDebug();
-}
-
-QQuickImageParticle::~QQuickImageParticle()
-{
-}
-
-QDeclarativeListProperty<QQuickSprite> QQuickImageParticle::sprites()
-{
- return QDeclarativeListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
-}
-
-void QQuickImageParticle::setImage(const QUrl &image)
-{
- if (image == m_image_name)
- return;
- m_image_name = image;
- emit imageChanged();
- reset();
-}
-
-
-void QQuickImageParticle::setColortable(const QUrl &table)
-{
- if (table == m_colortable_name)
- return;
- m_colortable_name = table;
- emit colortableChanged();
- reset();
-}
-
-void QQuickImageParticle::setSizetable(const QUrl &table)
-{
- if (table == m_sizetable_name)
- return;
- m_sizetable_name = table;
- emit sizetableChanged();
- reset();
-}
-
-void QQuickImageParticle::setOpacitytable(const QUrl &table)
-{
- if (table == m_opacitytable_name)
- return;
- m_opacitytable_name = table;
- emit opacitytableChanged();
- reset();
-}
-
-void QQuickImageParticle::setColor(const QColor &color)
-{
- if (color == m_color)
- return;
- m_color = color;
- emit colorChanged();
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setColorVariation(qreal var)
-{
- if (var == m_color_variation)
- return;
- m_color_variation = var;
- emit colorVariationChanged();
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setAlphaVariation(qreal arg)
-{
- if (m_alphaVariation != arg) {
- m_alphaVariation = arg;
- emit alphaVariationChanged(arg);
- }
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setAlpha(qreal arg)
-{
- if (m_alpha != arg) {
- m_alpha = arg;
- emit alphaChanged(arg);
- }
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setRedVariation(qreal arg)
-{
- if (m_redVariation != arg) {
- m_redVariation = arg;
- emit redVariationChanged(arg);
- }
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setGreenVariation(qreal arg)
-{
- if (m_greenVariation != arg) {
- m_greenVariation = arg;
- emit greenVariationChanged(arg);
- }
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setBlueVariation(qreal arg)
-{
- if (m_blueVariation != arg) {
- m_blueVariation = arg;
- emit blueVariationChanged(arg);
- }
- m_explicitColor = true;
- if (perfLevel < Colored)
- reset();
-}
-
-void QQuickImageParticle::setRotation(qreal arg)
-{
- if (m_rotation != arg) {
- m_rotation = arg;
- emit rotationChanged(arg);
- }
- m_explicitRotation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setRotationVariation(qreal arg)
-{
- if (m_rotationVariation != arg) {
- m_rotationVariation = arg;
- emit rotationVariationChanged(arg);
- }
- m_explicitRotation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setRotationSpeed(qreal arg)
-{
- if (m_rotationSpeed != arg) {
- m_rotationSpeed = arg;
- emit rotationSpeedChanged(arg);
- }
- m_explicitRotation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setRotationSpeedVariation(qreal arg)
-{
- if (m_rotationSpeedVariation != arg) {
- m_rotationSpeedVariation = arg;
- emit rotationSpeedVariationChanged(arg);
- }
- m_explicitRotation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setAutoRotation(bool arg)
-{
- if (m_autoRotation != arg) {
- m_autoRotation = arg;
- emit autoRotationChanged(arg);
- }
- m_explicitRotation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setXVector(QQuickDirection* arg)
-{
- if (m_xVector != arg) {
- m_xVector = arg;
- emit xVectorChanged(arg);
- }
- m_explicitDeformation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setYVector(QQuickDirection* arg)
-{
- if (m_yVector != arg) {
- m_yVector = arg;
- emit yVectorChanged(arg);
- }
- m_explicitDeformation = true;
- if (perfLevel < Deformable)
- reset();
-}
-
-void QQuickImageParticle::setSpritesInterpolate(bool arg)
-{
- if (m_spritesInterpolate != arg) {
- m_spritesInterpolate = arg;
- emit spritesInterpolateChanged(arg);
- }
-}
-
-void QQuickImageParticle::setBloat(bool arg)
-{
- if (m_bloat != arg) {
- m_bloat = arg;
- emit bloatChanged(arg);
- }
- if (perfLevel < 9999)
- reset();
-}
-
-void QQuickImageParticle::setEntryEffect(EntryEffect arg)
-{
- if (m_entryEffect != arg) {
- m_entryEffect = arg;
- if (m_material)
- getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
- emit entryEffectChanged(arg);
- }
-}
-
-void QQuickImageParticle::resetColor()
-{
- m_explicitColor = false;
- foreach (const QString &str, m_groups)
- foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
- if (d->colorOwner == this)
- d->colorOwner = 0;
- m_color = QColor();
- m_color_variation = 0.0f;
- m_redVariation = 0.0f;
- m_blueVariation = 0.0f;
- m_greenVariation = 0.0f;
- m_alpha = 1.0f;
- m_alphaVariation = 0.0f;
-}
-
-void QQuickImageParticle::resetRotation()
-{
- m_explicitRotation = false;
- foreach (const QString &str, m_groups)
- foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
- if (d->rotationOwner == this)
- d->rotationOwner = 0;
- m_rotation = 0;
- m_rotationVariation = 0;
- m_rotationSpeed = 0;
- m_rotationSpeedVariation = 0;
- m_autoRotation = false;
-}
-
-void QQuickImageParticle::resetDeformation()
-{
- m_explicitDeformation = false;
- foreach (const QString &str, m_groups)
- foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
- if (d->deformationOwner == this)
- d->deformationOwner = 0;
- if (m_xVector)
- delete m_xVector;
- if (m_yVector)
- delete m_yVector;
- m_xVector = 0;
- m_yVector = 0;
-}
-
-void QQuickImageParticle::reset()
-{
- QQuickParticlePainter::reset();
- m_pleaseReset = true;
- update();
-}
-
-void QQuickImageParticle::createEngine()
-{
- if (m_spriteEngine)
- delete m_spriteEngine;
- if (m_sprites.count()) {
- m_spriteEngine = new QQuickSpriteEngine(m_sprites, this);
- connect(m_spriteEngine, SIGNAL(stateChanged(int)),
- this, SLOT(spriteAdvance(int)));
- m_explicitAnimation = true;
- } else {
- m_spriteEngine = 0;
- m_explicitAnimation = false;
- }
- reset();
-}
-
-static QSGGeometry::Attribute SimpleParticle_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
- QSGGeometry::Attribute::create(1, 4, GL_FLOAT), // Data
- QSGGeometry::Attribute::create(2, 4, GL_FLOAT) // Vectors
-};
-
-static QSGGeometry::AttributeSet SimpleParticle_AttributeSet =
-{
- 3, // Attribute Count
- ( 2 + 4 + 4 ) * sizeof(float),
- SimpleParticle_Attributes
-};
-
-static QSGGeometry::Attribute ColoredParticle_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
- QSGGeometry::Attribute::create(1, 4, GL_FLOAT), // Data
- QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Vectors
- QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE), // Colors
-};
-
-static QSGGeometry::AttributeSet ColoredParticle_AttributeSet =
-{
- 4, // Attribute Count
- ( 2 + 4 + 4 ) * sizeof(float) + 4 * sizeof(uchar),
- ColoredParticle_Attributes
-};
-
-static QSGGeometry::Attribute DeformableParticle_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
- QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
- QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
- QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
- QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // Colors
- QSGGeometry::Attribute::create(5, 4, GL_FLOAT), // DeformationVectors
- QSGGeometry::Attribute::create(6, 3, GL_FLOAT), // Rotation
-};
-
-static QSGGeometry::AttributeSet DeformableParticle_AttributeSet =
-{
- 7, // Attribute Count
- (2 + 2 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
- DeformableParticle_Attributes
-};
-
-static QSGGeometry::Attribute SpriteParticle_Attributes[] = {
- QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
- QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
- QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
- QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
- QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // Colors
- QSGGeometry::Attribute::create(5, 4, GL_FLOAT), // DeformationVectors
- QSGGeometry::Attribute::create(6, 3, GL_FLOAT), // Rotation
- QSGGeometry::Attribute::create(7, 4, GL_FLOAT), // Anim Data
- QSGGeometry::Attribute::create(8, 4, GL_FLOAT) // Anim Pos
-};
-
-static QSGGeometry::AttributeSet SpriteParticle_AttributeSet =
-{
- 9, // Attribute Count
- (2 + 2 + 4 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
- SpriteParticle_Attributes
-};
-
-void QQuickImageParticle::clearShadows()
-{
- foreach (const QVector<QQuickParticleData*> data, m_shadowData)
- qDeleteAll(data);
- m_shadowData.clear();
-}
-
-//Only call if you need to, may initialize the whole array first time
-QQuickParticleData* QQuickImageParticle::getShadowDatum(QQuickParticleData* datum)
-{
- QQuickParticleGroupData* gd = m_system->groupData[datum->group];
- if (!m_shadowData.contains(datum->group)) {
- QVector<QQuickParticleData*> data;
- for (int i=0; i<gd->size(); i++){
- QQuickParticleData* datum = new QQuickParticleData(m_system);
- *datum = *(gd->data[i]);
- data << datum;
- }
- m_shadowData.insert(datum->group, data);
- }
- //### If dynamic resize is added, remember to potentially resize the shadow data on out-of-bounds access request
-
- return m_shadowData[datum->group][datum->index];
-}
-
-QSGGeometryNode* QQuickImageParticle::buildParticleNodes()
-{
-#ifdef QT_OPENGL_ES_2
- if (m_count * 4 > 0xffff) {
- printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort
- return 0;
- }
-#endif
-
- if (count() <= 0)
- return 0;
-
- if (m_sprites.count() || m_bloat) {
- perfLevel = Sprites;
- } else if (!m_colortable_name.isEmpty() || !m_sizetable_name.isEmpty()
- || !m_opacitytable_name.isEmpty()) {
- perfLevel = Tabled;
- } else if (m_autoRotation || m_rotation || m_rotationVariation
- || m_rotationSpeed || m_rotationSpeedVariation
- || m_xVector || m_yVector) {
- perfLevel = Deformable;
- } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid() || m_color_variation
- || m_redVariation || m_blueVariation || m_greenVariation) {
- perfLevel = Colored;
- } else {
- perfLevel = Simple;
- }
-
- foreach (const QString &str, m_groups){//For sharing higher levels, need to have highest used so it renders
- int gIdx = m_system->groupIds[str];
- foreach (QQuickParticlePainter* p, m_system->groupData[gIdx]->painters){
- QQuickImageParticle* other = qobject_cast<QQuickImageParticle*>(p);
- if (other){
- if (other->perfLevel > perfLevel) {
- if (other->perfLevel >= Tabled){//Deformable is the highest level needed for this, anything higher isn't shared (or requires your own sprite)
- if (perfLevel < Deformable)
- perfLevel = Deformable;
- } else {
- perfLevel = other->perfLevel;
- }
- } else if (other->perfLevel < perfLevel) {
- other->reset();
- }
- }
- }
- }
-
- if (perfLevel >= Colored && !m_color.isValid())
- m_color = QColor(Qt::white);//Hidden default, but different from unset
-
- QImage image;
- if (perfLevel >= Sprites){
- if (!m_spriteEngine) {
- qWarning() << "ImageParticle: No sprite engine...";
- return 0;
- }
- image = m_spriteEngine->assembledImage();
- if (image.isNull())//Warning is printed in engine
- return 0;
- } else {
- image = QImage(m_image_name.toLocalFile());
- if (image.isNull()) {
- printf("ImageParticle: loading image failed '%s'\n", qPrintable(m_image_name.toLocalFile()));
- return 0;
- }
- }
-
- clearShadows();
- if (m_material)
- m_material = 0;
-
- //Setup material
- QImage colortable;
- QImage sizetable;
- QImage opacitytable;
- switch (perfLevel) {//Fallthrough intended
- case Sprites:
- m_material = SpriteMaterial::createMaterial();
- getState<ImageMaterialData>(m_material)->animSheetSize = QSizeF(image.size());
- m_spriteEngine->setCount(m_count);
- case Tabled:
- if (!m_material)
- m_material = TabledMaterial::createMaterial();
- colortable = QImage(m_colortable_name.toLocalFile());
- sizetable = QImage(m_sizetable_name.toLocalFile());
- opacitytable = QImage(m_opacitytable_name.toLocalFile());
- if (colortable.isNull()){
- colortable = QImage(1,1,QImage::Format_ARGB32);
- colortable.fill(Qt::white);
- }
- Q_ASSERT(!colortable.isNull());
- getState<ImageMaterialData>(m_material)->colorTable = QSGPlainTexture::fromImage(colortable);
- fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->sizeTable, sizetable, UNIFORM_ARRAY_SIZE);
- fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->opacityTable, opacitytable, UNIFORM_ARRAY_SIZE);
- case Deformable:
- if (!m_material)
- m_material = DeformableMaterial::createMaterial();
- case Colored:
- if (!m_material)
- m_material = ColoredMaterial::createMaterial();
- default://Also Simple
- if (!m_material)
- m_material = SimpleMaterial::createMaterial();
- getState<ImageMaterialData>(m_material)->texture = QSGPlainTexture::fromImage(image);
- getState<ImageMaterialData>(m_material)->texture->setFiltering(QSGTexture::Linear);
- getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
- m_material->setFlag(QSGMaterial::Blending);
- }
-
- foreach (const QString &str, m_groups){
- int gIdx = m_system->groupIds[str];
- int count = m_system->groupData[gIdx]->size();
- QSGGeometryNode* node = new QSGGeometryNode();
- node->setMaterial(m_material);
- node->markDirty(QSGNode::DirtyMaterial);
-
- m_nodes.insert(gIdx, node);
- m_idxStarts.insert(gIdx, m_lastIdxStart);
- m_startsIdx.append(qMakePair<int,int>(m_lastIdxStart, gIdx));
- m_lastIdxStart += count;
-
- //Create Particle Geometry
- int vCount = count * 4;
- int iCount = count * 6;
-
- QSGGeometry *g;
- if (perfLevel == Sprites)
- g = new QSGGeometry(SpriteParticle_AttributeSet, vCount, iCount);
- else if (perfLevel == Tabled)
- g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
- else if (perfLevel == Deformable)
- g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
- else if (perfLevel == Colored)
- g = new QSGGeometry(ColoredParticle_AttributeSet, count, 0);
- else //Simple
- g = new QSGGeometry(SimpleParticle_AttributeSet, count, 0);
-
- node->setGeometry(g);
- if (perfLevel <= Colored){
- g->setDrawingMode(GL_POINTS);
- if (m_debugMode){
- GLfloat pointSizeRange[2];
- glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
- qDebug() << "Using point sprites, GL_ALIASED_POINT_SIZE_RANGE " <<pointSizeRange[0] << ":" << pointSizeRange[1];
- }
- }else
- g->setDrawingMode(GL_TRIANGLES);
-
- for (int p=0; p < count; ++p)
- commit(gIdx, p);//commit sets geometry for the node, has its own perfLevel switch
-
- if (perfLevel == Sprites)
- initTexCoords<SpriteVertex>((SpriteVertex*)g->vertexData(), vCount);
- else if (perfLevel == Tabled)
- initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
- else if (perfLevel == Deformable)
- initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
-
- if (perfLevel > Colored){
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
- }
- }
-
- }
-
- foreach (QSGGeometryNode* node, m_nodes){
- if (node == *(m_nodes.begin()))
- node->setFlag(QSGGeometryNode::OwnsMaterial);//Root node owns the material for memory management purposes
- else
- (*(m_nodes.begin()))->appendChildNode(node);
- }
-
- return *(m_nodes.begin());
-}
-
-QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
-{
- if (m_pleaseReset){
- m_lastLevel = perfLevel;
-
- delete m_rootNode;//Automatically deletes children, and SG manages material lifetime
- m_rootNode = 0;
- m_nodes.clear();
-
- m_idxStarts.clear();
- m_startsIdx.clear();
- m_lastIdxStart = 0;
-
- m_material = 0;
-
- m_pleaseReset = false;
- }
-
- if (m_system && m_system->isRunning() && !m_system->isPaused()){
- prepareNextFrame();
- if (m_rootNode) {
- update();
- foreach (QSGGeometryNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyGeometry);
- }
- }
-
- return m_rootNode;
-}
-
-void QQuickImageParticle::prepareNextFrame()
-{
- if (m_rootNode == 0){//TODO: Staggered loading (as emitted)
- m_rootNode = buildParticleNodes();
- if (m_rootNode == 0)
- return;
- if (m_debugMode) {
- qDebug() << "QQuickImageParticle Feature level: " << perfLevel;
- qDebug() << "QQuickImageParticle Nodes: ";
- int count = 0;
- foreach (int i, m_nodes.keys()) {
- qDebug() << "Group " << i << " (" << m_system->groupData[i]->size() << " particles)";
- count += m_system->groupData[i]->size();
- }
- qDebug() << "Total count: " << count;
- }
- }
- qint64 timeStamp = m_system->systemSync(this);
-
- qreal time = timeStamp / 1000.;
-
- switch (perfLevel){//Fall-through intended
- case Sprites:
- //Advance State
- m_spriteEngine->updateSprites(timeStamp);
- case Tabled:
- case Deformable:
- case Colored:
- case Simple:
- default: //Also Simple
- getState<ImageMaterialData>(m_material)->timestamp = time;
- break;
- }
-
- foreach (QSGGeometryNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyMaterial);
-}
-
-void QQuickImageParticle::spriteAdvance(int spriteIdx)
-{
- if (!m_startsIdx.count())//Probably overly defensive
- return;
-
- int gIdx = -1;
- int i;
- for (i = 0; i<m_startsIdx.count(); i++) {
- if (spriteIdx < m_startsIdx[i].first) {
- gIdx = m_startsIdx[i-1].second;
- break;
- }
- }
- if (gIdx == -1)
- gIdx = m_startsIdx[i-1].second;
- int pIdx = spriteIdx - m_startsIdx[i-1].first;
-
- QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
- QQuickParticleData* d = (datum->animationOwner == this ? datum : getShadowDatum(datum));
-
- d->animIdx = m_spriteEngine->spriteState(spriteIdx);
- Vertices<SpriteVertex>* particles = (Vertices<SpriteVertex> *) m_nodes[gIdx]->geometry()->vertexData();
- Vertices<SpriteVertex> &p = particles[pIdx];
- d->animT = p.v1.animT = p.v2.animT = p.v3.animT = p.v4.animT = m_spriteEngine->spriteStart(spriteIdx)/1000.0;
- d->frameCount = p.v1.frameCount = p.v2.frameCount = p.v3.frameCount = p.v4.frameCount = m_spriteEngine->spriteFrames(spriteIdx);
- d->frameDuration = p.v1.frameDuration = p.v2.frameDuration = p.v3.frameDuration = p.v4.frameDuration = m_spriteEngine->spriteDuration(spriteIdx);
- d->animX = p.v1.animX = p.v2.animX = p.v3.animX = p.v4.animX = m_spriteEngine->spriteX(spriteIdx);
- d->animY = p.v1.animY = p.v2.animY = p.v3.animY = p.v4.animY = m_spriteEngine->spriteY(spriteIdx);
- d->animWidth = p.v1.animWidth = p.v2.animWidth = p.v3.animWidth = p.v4.animWidth = m_spriteEngine->spriteWidth(spriteIdx);
- d->animHeight = p.v1.animHeight = p.v2.animHeight = p.v3.animHeight = p.v4.animHeight = m_spriteEngine->spriteHeight(spriteIdx);
-}
-
-void QQuickImageParticle::reloadColor(const Color4ub &c, QQuickParticleData* d)
-{
- d->color = c;
- //TODO: get index for reload - or make function take an index
-}
-
-void QQuickImageParticle::initialize(int gIdx, int pIdx)
-{
- Color4ub color;
- QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
- qreal redVariation = m_color_variation + m_redVariation;
- qreal greenVariation = m_color_variation + m_greenVariation;
- qreal blueVariation = m_color_variation + m_blueVariation;
- int spriteIdx = 0;
- if (m_spriteEngine) {
- spriteIdx = m_idxStarts[gIdx] + datum->index;
- if (spriteIdx >= m_spriteEngine->count())
- m_spriteEngine->setCount(spriteIdx+1);
- }
-
- float rotation;
- float rotationSpeed;
- float autoRotate;
- switch (perfLevel){//Fall-through is intended on all of them
- case Sprites:
- // Initial Sprite State
- if (m_explicitAnimation){
- if (!datum->animationOwner)
- datum->animationOwner = this;
- QQuickParticleData* writeTo = (datum->animationOwner == this ? datum : getShadowDatum(datum));
- writeTo->animT = writeTo->t;
- //writeTo->animInterpolate = m_spritesInterpolate;
- if (m_spriteEngine){
- m_spriteEngine->start(spriteIdx);
- writeTo->frameCount = m_spriteEngine->spriteFrames(spriteIdx);
- writeTo->frameDuration = m_spriteEngine->spriteDuration(spriteIdx);
- writeTo->animX = m_spriteEngine->spriteX(spriteIdx);
- writeTo->animY = m_spriteEngine->spriteY(spriteIdx);
- writeTo->animWidth = m_spriteEngine->spriteWidth(spriteIdx);
- writeTo->animHeight = m_spriteEngine->spriteHeight(spriteIdx);
- }else{
- writeTo->frameCount = 1;
- writeTo->frameDuration = 9999;
- writeTo->animX = writeTo->animY = 0;
- writeTo->animWidth = writeTo->animHeight = 1;
- }
- }
- case Tabled:
- case Deformable:
- //Initial Rotation
- if (m_explicitDeformation){
- if (!datum->deformationOwner)
- datum->deformationOwner = this;
- if (m_xVector){
- const QPointF &ret = m_xVector->sample(QPointF(datum->x, datum->y));
- if (datum->deformationOwner == this) {
- datum->xx = ret.x();
- datum->xy = ret.y();
- } else {
- getShadowDatum(datum)->xx = ret.x();
- getShadowDatum(datum)->xy = ret.y();
- }
- }
- if (m_yVector){
- const QPointF &ret = m_yVector->sample(QPointF(datum->x, datum->y));
- if (datum->deformationOwner == this) {
- datum->yx = ret.x();
- datum->yy = ret.y();
- } else {
- getShadowDatum(datum)->yx = ret.x();
- getShadowDatum(datum)->yy = ret.y();
- }
- }
- }
-
- if (m_explicitRotation){
- if (!datum->rotationOwner)
- datum->rotationOwner = this;
- rotation =
- (m_rotation + (m_rotationVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationVariation) ) * CONV;
- rotationSpeed =
- (m_rotationSpeed + (m_rotationSpeedVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationSpeedVariation) ) * CONV;
- autoRotate = m_autoRotation?1.0:0.0;
- if (datum->rotationOwner == this) {
- datum->rotation = rotation;
- datum->rotationSpeed = rotationSpeed;
- datum->autoRotate = autoRotate;
- } else {
- getShadowDatum(datum)->rotation = rotation;
- getShadowDatum(datum)->rotationSpeed = rotationSpeed;
- getShadowDatum(datum)->autoRotate = autoRotate;
- }
- }
- case Colored:
- //Color initialization
- // Particle color
- if (m_explicitColor) {
- if (!datum->colorOwner)
- datum->colorOwner = this;
- color.r = m_color.red() * (1 - redVariation) + rand() % 256 * redVariation;
- color.g = m_color.green() * (1 - greenVariation) + rand() % 256 * greenVariation;
- color.b = m_color.blue() * (1 - blueVariation) + rand() % 256 * blueVariation;
- color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + rand() % 256 * m_alphaVariation;
- if (datum->colorOwner == this)
- datum->color = color;
- else
- getShadowDatum(datum)->color = color;
- }
- default:
- break;
- }
-}
-
-void QQuickImageParticle::commit(int gIdx, int pIdx)
-{
- if (m_pleaseReset)
- return;
- QSGGeometryNode *node = m_nodes[gIdx];
- if (!node)
- return;
- QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
- node->setFlag(QSGNode::OwnsGeometry, false);
- SpriteVertex *spriteVertices = (SpriteVertex *) node->geometry()->vertexData();
- DeformableVertex *deformableVertices = (DeformableVertex *) node->geometry()->vertexData();
- ColoredVertex *coloredVertices = (ColoredVertex *) node->geometry()->vertexData();
- SimpleVertex *simpleVertices = (SimpleVertex *) node->geometry()->vertexData();
- switch (perfLevel){//No automatic fall through intended on this one
- case Sprites:
- spriteVertices += pIdx*4;
- for (int i=0; i<4; i++){
- spriteVertices[i].x = datum->x - m_systemOffset.x();
- spriteVertices[i].y = datum->y - m_systemOffset.y();
- spriteVertices[i].t = datum->t;
- spriteVertices[i].lifeSpan = datum->lifeSpan;
- spriteVertices[i].size = datum->size;
- spriteVertices[i].endSize = datum->endSize;
- spriteVertices[i].vx = datum->vx;
- spriteVertices[i].vy = datum->vy;
- spriteVertices[i].ax = datum->ax;
- spriteVertices[i].ay = datum->ay;
- if (m_explicitDeformation && datum->deformationOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- spriteVertices[i].xx = shadow->xx;
- spriteVertices[i].xy = shadow->xy;
- spriteVertices[i].yx = shadow->yx;
- spriteVertices[i].yy = shadow->yy;
- } else {
- spriteVertices[i].xx = datum->xx;
- spriteVertices[i].xy = datum->xy;
- spriteVertices[i].yx = datum->yx;
- spriteVertices[i].yy = datum->yy;
- }
- if (m_explicitRotation && datum->rotationOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- spriteVertices[i].rotation = shadow->rotation;
- spriteVertices[i].rotationSpeed = shadow->rotationSpeed;
- spriteVertices[i].autoRotate = shadow->autoRotate;
- } else {
- spriteVertices[i].rotation = datum->rotation;
- spriteVertices[i].rotationSpeed = datum->rotationSpeed;
- spriteVertices[i].autoRotate = datum->autoRotate;
- }
- spriteVertices[i].animInterpolate = m_spritesInterpolate ? 1.0 : 0.0;//### Shadow? In particleData? Or uniform?
- if (m_explicitAnimation && datum->animationOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- spriteVertices[i].frameDuration = shadow->frameDuration;
- spriteVertices[i].frameCount = shadow->frameCount;
- spriteVertices[i].animT = shadow->animT;
- spriteVertices[i].animX = shadow->animX;
- spriteVertices[i].animY = shadow->animY;
- spriteVertices[i].animWidth = shadow->animWidth;
- spriteVertices[i].animHeight = shadow->animHeight;
- } else {
- spriteVertices[i].frameDuration = datum->frameDuration;
- spriteVertices[i].frameCount = datum->frameCount;
- spriteVertices[i].animT = datum->animT;
- spriteVertices[i].animX = datum->animX;
- spriteVertices[i].animY = datum->animY;
- spriteVertices[i].animWidth = datum->animWidth;
- spriteVertices[i].animHeight = datum->animHeight;
- }
- if (m_explicitColor && datum->colorOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- spriteVertices[i].color.r = shadow->color.r;
- spriteVertices[i].color.g = shadow->color.g;
- spriteVertices[i].color.b = shadow->color.b;
- spriteVertices[i].color.a = shadow->color.a;
- } else {
- spriteVertices[i].color.r = datum->color.r;
- spriteVertices[i].color.g = datum->color.g;
- spriteVertices[i].color.b = datum->color.b;
- spriteVertices[i].color.a = datum->color.a;
- }
- }
- break;
- case Tabled: //Fall through until it has its own vertex class
- case Deformable:
- deformableVertices += pIdx*4;
- for (int i=0; i<4; i++){
- deformableVertices[i].x = datum->x - m_systemOffset.x();
- deformableVertices[i].y = datum->y - m_systemOffset.y();
- deformableVertices[i].t = datum->t;
- deformableVertices[i].lifeSpan = datum->lifeSpan;
- deformableVertices[i].size = datum->size;
- deformableVertices[i].endSize = datum->endSize;
- deformableVertices[i].vx = datum->vx;
- deformableVertices[i].vy = datum->vy;
- deformableVertices[i].ax = datum->ax;
- deformableVertices[i].ay = datum->ay;
- if (m_explicitDeformation && datum->deformationOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- deformableVertices[i].xx = shadow->xx;
- deformableVertices[i].xy = shadow->xy;
- deformableVertices[i].yx = shadow->yx;
- deformableVertices[i].yy = shadow->yy;
- } else {
- deformableVertices[i].xx = datum->xx;
- deformableVertices[i].xy = datum->xy;
- deformableVertices[i].yx = datum->yx;
- deformableVertices[i].yy = datum->yy;
- }
- if (m_explicitRotation && datum->rotationOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- deformableVertices[i].rotation = shadow->rotation;
- deformableVertices[i].rotationSpeed = shadow->rotationSpeed;
- deformableVertices[i].autoRotate = shadow->autoRotate;
- } else {
- deformableVertices[i].rotation = datum->rotation;
- deformableVertices[i].rotationSpeed = datum->rotationSpeed;
- deformableVertices[i].autoRotate = datum->autoRotate;
- }
- if (m_explicitColor && datum->colorOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- deformableVertices[i].color.r = shadow->color.r;
- deformableVertices[i].color.g = shadow->color.g;
- deformableVertices[i].color.b = shadow->color.b;
- deformableVertices[i].color.a = shadow->color.a;
- } else {
- deformableVertices[i].color.r = datum->color.r;
- deformableVertices[i].color.g = datum->color.g;
- deformableVertices[i].color.b = datum->color.b;
- deformableVertices[i].color.a = datum->color.a;
- }
- }
- break;
- case Colored:
- coloredVertices += pIdx*1;
- for (int i=0; i<1; i++){
- coloredVertices[i].x = datum->x - m_systemOffset.x();
- coloredVertices[i].y = datum->y - m_systemOffset.y();
- coloredVertices[i].t = datum->t;
- coloredVertices[i].lifeSpan = datum->lifeSpan;
- coloredVertices[i].size = datum->size;
- coloredVertices[i].endSize = datum->endSize;
- coloredVertices[i].vx = datum->vx;
- coloredVertices[i].vy = datum->vy;
- coloredVertices[i].ax = datum->ax;
- coloredVertices[i].ay = datum->ay;
- if (m_explicitColor && datum->colorOwner != this) {
- QQuickParticleData* shadow = getShadowDatum(datum);
- coloredVertices[i].color.r = shadow->color.r;
- coloredVertices[i].color.g = shadow->color.g;
- coloredVertices[i].color.b = shadow->color.b;
- coloredVertices[i].color.a = shadow->color.a;
- } else {
- coloredVertices[i].color.r = datum->color.r;
- coloredVertices[i].color.g = datum->color.g;
- coloredVertices[i].color.b = datum->color.b;
- coloredVertices[i].color.a = datum->color.a;
- }
- }
- break;
- case Simple:
- simpleVertices += pIdx*1;
- for (int i=0; i<1; i++){
- simpleVertices[i].x = datum->x - m_systemOffset.x();
- simpleVertices[i].y = datum->y - m_systemOffset.y();
- simpleVertices[i].t = datum->t;
- simpleVertices[i].lifeSpan = datum->lifeSpan;
- simpleVertices[i].size = datum->size;
- simpleVertices[i].endSize = datum->endSize;
- simpleVertices[i].vx = datum->vx;
- simpleVertices[i].vy = datum->vy;
- simpleVertices[i].ax = datum->ax;
- simpleVertices[i].ay = datum->ay;
- }
- break;
- default:
- break;
- }
-
- node->setFlag(QSGNode::OwnsGeometry, true);
-}
-
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qquickimageparticle_p.h b/src/declarative/particles/qquickimageparticle_p.h
deleted file mode 100644
index c7da7cfce6..0000000000
--- a/src/declarative/particles/qquickimageparticle_p.h
+++ /dev/null
@@ -1,429 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 ULTRAPARTICLE_H
-#define ULTRAPARTICLE_H
-#include "qquickparticlepainter_p.h"
-#include "qquickdirection_p.h"
-#include <QDeclarativeListProperty>
-#include <qsgsimplematerial.h>
-#include <QtGui/qcolor.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class ImageMaterialData;
-class QSGGeometryNode;
-
-class QQuickSprite;
-class QQuickStochasticEngine;
-
-struct SimpleVertex {
- float x;
- float y;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
-};
-
-struct ColoredVertex {
- float x;
- float y;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
- Color4ub color;
-};
-
-struct DeformableVertex {
- float x;
- float y;
- float tx;
- float ty;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
- Color4ub color;
- float xx;
- float xy;
- float yx;
- float yy;
- float rotation;
- float rotationSpeed;
- float autoRotate;//Assumed that GPUs prefer floats to bools
-};
-
-struct SpriteVertex {
- float x;
- float y;
- float tx;
- float ty;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
- Color4ub color;
- float xx;
- float xy;
- float yx;
- float yy;
- float rotation;
- float rotationSpeed;
- float autoRotate;//Assumed that GPUs prefer floats to bools
- float animInterpolate;
- float frameDuration;
- float frameCount;
- float animT;
- float animX;
- float animY;
- float animWidth;
- float animHeight;
-};
-
-template <typename Vertex>
-struct Vertices {
- Vertex v1;
- Vertex v2;
- Vertex v3;
- Vertex v4;
-};
-
-class QQuickImageParticle : public QQuickParticlePainter
-{
- Q_OBJECT
- Q_PROPERTY(QUrl source READ image WRITE setImage NOTIFY imageChanged)
- Q_PROPERTY(QUrl colorTable READ colortable WRITE setColortable NOTIFY colortableChanged)
- Q_PROPERTY(QUrl sizeTable READ sizetable WRITE setSizetable NOTIFY sizetableChanged)
- Q_PROPERTY(QUrl opacityTable READ opacitytable WRITE setOpacitytable NOTIFY opacitytableChanged)
-
- //###Now just colorize - add a flag for 'solid' color particles(where the img is just a mask?)?
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged RESET resetColor)
- //Stacks (added) with individual colorVariations
- Q_PROPERTY(qreal colorVariation READ colorVariation WRITE setColorVariation NOTIFY colorVariationChanged RESET resetColor)
- Q_PROPERTY(qreal redVariation READ redVariation WRITE setRedVariation NOTIFY redVariationChanged RESET resetColor)
- Q_PROPERTY(qreal greenVariation READ greenVariation WRITE setGreenVariation NOTIFY greenVariationChanged RESET resetColor)
- Q_PROPERTY(qreal blueVariation READ blueVariation WRITE setBlueVariation NOTIFY blueVariationChanged RESET resetColor)
- //Stacks (multiplies) with the Alpha in the color, mostly here so you can use svg color names (which have full alpha)
- Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged RESET resetColor)
- Q_PROPERTY(qreal alphaVariation READ alphaVariation WRITE setAlphaVariation NOTIFY alphaVariationChanged RESET resetColor)
-
- Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged RESET resetRotation)
- Q_PROPERTY(qreal rotationVariation READ rotationVariation WRITE setRotationVariation NOTIFY rotationVariationChanged RESET resetRotation)
- Q_PROPERTY(qreal rotationSpeed READ rotationSpeed WRITE setRotationSpeed NOTIFY rotationSpeedChanged RESET resetRotation)
- Q_PROPERTY(qreal rotationSpeedVariation READ rotationSpeedVariation WRITE setRotationSpeedVariation NOTIFY rotationSpeedVariationChanged RESET resetRotation)
- //If true, then will face the direction of motion. Stacks with rotation, e.g. setting rotation
- //to 180 will lead to facing away from the direction of motion
- Q_PROPERTY(bool autoRotation READ autoRotation WRITE setAutoRotation NOTIFY autoRotationChanged RESET resetRotation)
-
- //###Call i/j? Makes more sense to those with vector calculus experience, and I could even add the cirumflex in QML?
- //xVector is the vector from the top-left point to the top-right point, and is multiplied by current size
- Q_PROPERTY(QQuickDirection* xVector READ xVector WRITE setXVector NOTIFY xVectorChanged RESET resetDeformation)
- //yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
- Q_PROPERTY(QQuickDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged RESET resetDeformation)
- Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
- Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged)
-
- Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
- Q_PROPERTY(bool bloat READ bloat WRITE setBloat NOTIFY bloatChanged)//Just a debugging property to bypass optimizations
- Q_ENUMS(EntryEffect)
-public:
- explicit QQuickImageParticle(QQuickItem *parent = 0);
- virtual ~QQuickImageParticle();
-
-
- QDeclarativeListProperty<QQuickSprite> sprites();
- QQuickStochasticEngine* spriteEngine() {return m_spriteEngine;}
-
- enum EntryEffect {
- None = 0,
- Fade = 1,
- Scale = 2
- };
-
- enum PerformanceLevel{//TODO: Expose?
- Unknown = 0,
- Simple,
- Colored,
- Deformable,
- Tabled,
- Sprites
- };
-
- QUrl image() const { return m_image_name; }
- void setImage(const QUrl &image);
-
- QUrl colortable() const { return m_colortable_name; }
- void setColortable(const QUrl &table);
-
- QUrl sizetable() const { return m_sizetable_name; }
- void setSizetable (const QUrl &table);
-
- QUrl opacitytable() const { return m_opacitytable_name; }
- void setOpacitytable(const QUrl &table);
-
- QColor color() const { return m_color; }
- void setColor(const QColor &color);
-
- qreal colorVariation() const { return m_color_variation; }
- void setColorVariation(qreal var);
-
- qreal alphaVariation() const { return m_alphaVariation; }
-
- qreal alpha() const { return m_alpha; }
-
- qreal redVariation() const { return m_redVariation; }
-
- qreal greenVariation() const { return m_greenVariation; }
-
- qreal blueVariation() const { return m_blueVariation; }
-
- qreal rotation() const { return m_rotation; }
-
- qreal rotationVariation() const { return m_rotationVariation; }
-
- qreal rotationSpeed() const { return m_rotationSpeed; }
-
- qreal rotationSpeedVariation() const { return m_rotationSpeedVariation; }
-
- bool autoRotation() const { return m_autoRotation; }
-
- QQuickDirection* xVector() const { return m_xVector; }
-
- QQuickDirection* yVector() const { return m_yVector; }
-
- bool spritesInterpolate() const { return m_spritesInterpolate; }
-
- bool bloat() const { return m_bloat; }
-
- EntryEffect entryEffect() const { return m_entryEffect; }
-
- void resetColor();
- void resetRotation();
- void resetDeformation();
-
-signals:
-
- void imageChanged();
- void colortableChanged();
- void sizetableChanged();
- void opacitytableChanged();
-
- void colorChanged();
- void colorVariationChanged();
-
- void alphaVariationChanged(qreal arg);
-
- void alphaChanged(qreal arg);
-
- void redVariationChanged(qreal arg);
-
- void greenVariationChanged(qreal arg);
-
- void blueVariationChanged(qreal arg);
-
- void rotationChanged(qreal arg);
-
- void rotationVariationChanged(qreal arg);
-
- void rotationSpeedChanged(qreal arg);
-
- void rotationSpeedVariationChanged(qreal arg);
-
- void autoRotationChanged(bool arg);
-
- void xVectorChanged(QQuickDirection* arg);
-
- void yVectorChanged(QQuickDirection* arg);
-
- void spritesInterpolateChanged(bool arg);
-
- void bloatChanged(bool arg);
-
- void entryEffectChanged(EntryEffect arg);
-
-public slots:
- void reloadColor(const Color4ub &c, QQuickParticleData* d);
- void setAlphaVariation(qreal arg);
-
- void setAlpha(qreal arg);
-
- void setRedVariation(qreal arg);
-
- void setGreenVariation(qreal arg);
-
- void setBlueVariation(qreal arg);
-
- void setRotation(qreal arg);
-
- void setRotationVariation(qreal arg);
-
- void setRotationSpeed(qreal arg);
-
- void setRotationSpeedVariation(qreal arg);
-
- void setAutoRotation(bool arg);
-
- void setXVector(QQuickDirection* arg);
-
- void setYVector(QQuickDirection* arg);
-
- void setSpritesInterpolate(bool arg);
-
- void setBloat(bool arg);
-
- void setEntryEffect(EntryEffect arg);
-
-protected:
- void reset();
- virtual void initialize(int gIdx, int pIdx);
- virtual void commit(int gIdx, int pIdx);
-
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void prepareNextFrame();
- QSGGeometryNode* buildParticleNodes();
-
-private slots:
- void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
-
- void spriteAdvance(int spriteIndex);
-private:
- QUrl m_image_name;
- QUrl m_colortable_name;
- QUrl m_sizetable_name;
- QUrl m_opacitytable_name;
-
-
- QColor m_color;
- qreal m_color_variation;
-
- QSGGeometryNode *m_rootNode;
- QHash<int, QSGGeometryNode *> m_nodes;
- QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
- QList<QPair<int, int> > m_startsIdx;//Same data, optimized for alternate retrieval
-
- int m_lastIdxStart;
- QSGMaterial *m_material;
-
- // derived values...
-
- qreal m_alphaVariation;
- qreal m_alpha;
- qreal m_redVariation;
- qreal m_greenVariation;
- qreal m_blueVariation;
- qreal m_rotation;
- qreal m_rotationVariation;
- qreal m_rotationSpeed;
- qreal m_rotationSpeedVariation;
- bool m_autoRotation;
- QQuickDirection* m_xVector;
- QQuickDirection* m_yVector;
-
- QList<QQuickSprite*> m_sprites;
- QQuickSpriteEngine* m_spriteEngine;
- bool m_spritesInterpolate;
-
- bool m_explicitColor;
- bool m_explicitRotation;
- bool m_explicitDeformation;
- bool m_explicitAnimation;
- QHash<int, QVector<QQuickParticleData*> > m_shadowData;
- void clearShadows();
- QQuickParticleData* getShadowDatum(QQuickParticleData* datum);
-
- bool m_bloat;
- PerformanceLevel perfLevel;
-
- PerformanceLevel m_lastLevel;
- bool m_debugMode;
-
- template<class Vertex>
- void initTexCoords(Vertex* v, int count){
- Vertex* end = v + count;
- while (v < end){
- v[0].tx = 0;
- v[0].ty = 0;
-
- v[1].tx = 1;
- v[1].ty = 0;
-
- v[2].tx = 0;
- v[2].ty = 1;
-
- v[3].tx = 1;
- v[3].ty = 1;
-
- v += 4;
- }
- }
-
- template<class MaterialData>
- MaterialData* getState(QSGMaterial* m){
- return static_cast<QSGSimpleMaterial<MaterialData> *>(m)->state();
- }
- EntryEffect m_entryEffect;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // ULTRAPARTICLE_H
diff --git a/src/declarative/particles/qquickitemparticle.cpp b/src/declarative/particles/qquickitemparticle.cpp
deleted file mode 100644
index 8b39ac3abd..0000000000
--- a/src/declarative/particles/qquickitemparticle.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 "qquickitemparticle_p.h"
-#include <private/qquickvisualitemmodel_p.h>
-#include <qsgnode.h>
-#include <QTimer>
-#include <QDeclarativeComponent>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass ItemParticle QQuickItemParticle
- \inqmlmodule QtQuick.Particles 2
- \inherits ParticlePainter
- \brief The ItemParticle element allows you to specify your own delegate to paint particles.
-
-*/
-
-
-/*!
- \qmlmethod void QtQuick.Particles2::ItemParticle::freeze(Item item)
-
- Suspends the flow of time for the logical particle which item represents, allowing you to control its movement.
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ItemParticle::unfreeze(Item item)
-
- Restarts the flow of time for the logical particle which item represents, allowing it to be moved by the particle system again.
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ItemParticle::take(Item item, bool prioritize)
-
- Asks the ItemParticle to take over control of item. It will be emitted when there is a logical particle available.
-
- By default items form a queue when waiting for a logical particle, but if prioritize is true then it will go immediately to the
- head of the queue.
-*/
-/*!
- \qmlmethod void QtQuick.Particles2::ItemParticle::give(Item item)
-
- Orders the ItemParticle to give you control of the item. It will cease controlling it and the item will lose its association to the logical particle.
-*/
-
-/*!
- \qmlproperty bool QtQuick.Particles2::ItemParticle::fade
-
- If true, the item will automatically be faded in and out
- at the ends of its lifetime. If false, you will have to
- implement any entry effect yourself.
-
- Default is true.
-*/
-/*!
- \qmlproperty Component QtQuick.Particles2::ItemParticle::delegate
-
- An instance of the delegate will be created for every logical
- particle, and moved along with it.
-*/
-
-QQuickItemParticle::QQuickItemParticle(QQuickItem *parent) :
- QQuickParticlePainter(parent), m_fade(true), m_delegate(0)
-{
- setFlag(QQuickItem::ItemHasContents);
- QTimer* manageDelegates = new QTimer(this);//TODO: don't leak
- connect(manageDelegates, SIGNAL(timeout()),
- this, SLOT(tick()));
- manageDelegates->setInterval(16);
- manageDelegates->setSingleShot(false);
- manageDelegates->start();
-}
-
-
-void QQuickItemParticle::freeze(QQuickItem* item)
-{
- m_stasis << item;
-}
-
-
-void QQuickItemParticle::unfreeze(QQuickItem* item)
-{
- m_stasis.remove(item);
-}
-
-void QQuickItemParticle::take(QQuickItem *item, bool prioritize)
-{
- if (prioritize)
- m_pendingItems.push_front(item);
- else
- m_pendingItems.push_back(item);
-}
-
-void QQuickItemParticle::give(QQuickItem *item)
-{
- //TODO: This
- Q_UNUSED(item);
-}
-
-void QQuickItemParticle::initialize(int gIdx, int pIdx)
-{
- m_loadables << m_system->groupData[gIdx]->data[pIdx];//defer to other thread
-}
-
-void QQuickItemParticle::commit(int, int)
-{
-}
-
-void QQuickItemParticle::tick()
-{
- foreach (QQuickItem* item, m_deletables){
- if (m_fade)
- item->setOpacity(0.);
- item->setVisible(false);
- QQuickItemParticleAttached* mpa;
- if ((mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(item))))
- mpa->detach();//reparent as well?
- //TODO: Delete iff we created it
- m_activeCount--;
- }
- m_deletables.clear();
-
- foreach (QQuickParticleData* d, m_loadables){
- if (m_stasis.contains(d->delegate))
- qWarning() << "Current model particles prefers overwrite:false";
- //remove old item from the particle that is dying to make room for this one
- if (d->delegate)
- m_deletables << d->delegate;
- d->delegate = 0;
- if (!m_pendingItems.isEmpty()){
- d->delegate = m_pendingItems.front();
- m_pendingItems.pop_front();
- }else if (m_delegate){
- d->delegate = qobject_cast<QQuickItem*>(m_delegate->create(qmlContext(this)));
- }
- if (d->delegate && d){//###Data can be zero if creating an item leads to a reset - this screws things up.
- d->delegate->setX(d->curX() - d->delegate->width()/2);//TODO: adjust for system?
- d->delegate->setY(d->curY() - d->delegate->height()/2);
- QQuickItemParticleAttached* mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(d->delegate));
- if (mpa){
- mpa->m_mp = this;
- mpa->attach();
- }
- d->delegate->setParentItem(this);
- if (m_fade)
- d->delegate->setOpacity(0.);
- d->delegate->setVisible(false);//Will be set to true when we prepare the next frame
- m_activeCount++;
- }
- }
- m_loadables.clear();
-}
-
-void QQuickItemParticle::reset()
-{
- QQuickParticlePainter::reset();
- //TODO: Cleanup items?
- m_loadables.clear();
- //deletables?
-}
-
-
-QSGNode* QQuickItemParticle::updatePaintNode(QSGNode* n, UpdatePaintNodeData* d)
-{
- //Dummy update just to get painting tick
- if (m_pleaseReset){
- m_pleaseReset = false;
- reset();
- }
- prepareNextFrame();
-
- update();//Get called again
- if (n)
- n->markDirty(QSGNode::DirtyMaterial);
- return QQuickItem::updatePaintNode(n,d);
-}
-
-void QQuickItemParticle::prepareNextFrame()
-{
- if (!m_system)
- return;
- qint64 timeStamp = m_system->systemSync(this);
- qreal curT = timeStamp/1000.0;
- qreal dt = curT - m_lastT;
- m_lastT = curT;
- if (!m_activeCount)
- return;
-
- //TODO: Size, better fade?
- foreach (const QString &str, m_groups){
- int gIdx = m_system->groupIds[str];
- int count = m_system->groupData[gIdx]->size();
-
- for (int i=0; i<count; i++){
- QQuickParticleData* data = m_system->groupData[gIdx]->data[i];
- QQuickItem* item = data->delegate;
- if (!item)
- continue;
- qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
- if (m_stasis.contains(item)) {
- data->t += dt;//Stasis effect
- continue;
- }
- if (t >= 1.0){//Usually happens from load
- m_deletables << item;
- data->delegate = 0;
- }else{//Fade
- data->delegate->setVisible(true);
- if (m_fade){
- qreal o = 1.;
- if (t<0.2)
- o = t*5;
- if (t>0.8)
- o = (1-t)*5;
- item->setOpacity(o);
- }
- }
- item->setX(data->curX() - item->width()/2 - m_systemOffset.x());
- item->setY(data->curY() - item->height()/2 - m_systemOffset.y());
- }
- }
-}
-
-QQuickItemParticleAttached *QQuickItemParticle::qmlAttachedProperties(QObject *object)
-{
- return new QQuickItemParticleAttached(object);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qquickitemparticle_p.h b/src/declarative/particles/qquickitemparticle_p.h
deleted file mode 100644
index 2e92b9c9ae..0000000000
--- a/src/declarative/particles/qquickitemparticle_p.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 ITEMPARTICLE_H
-#define ITEMPARTICLE_H
-#include "qquickparticlepainter_p.h"
-#include <QPointer>
-#include <QSet>
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class QQuickVisualDataModel;
-class QQuickItemParticleAttached;
-
-class QQuickItemParticle : public QQuickParticlePainter
-{
- Q_OBJECT
- Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged)
- Q_PROPERTY(QDeclarativeComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
-public:
- explicit QQuickItemParticle(QQuickItem *parent = 0);
-
- bool fade() const { return m_fade; }
-
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
- static QQuickItemParticleAttached *qmlAttachedProperties(QObject *object);
- QDeclarativeComponent* delegate() const
- {
- return m_delegate;
- }
-
-signals:
- void fadeChanged();
-
- void delegateChanged(QDeclarativeComponent* arg);
-
-public slots:
- //TODO: Add a follow mode, where moving the delegate causes the logical particle to go with it?
- void freeze(QQuickItem* item);
- void unfreeze(QQuickItem* item);
- void take(QQuickItem* item,bool prioritize=false);//take by modelparticle
- void give(QQuickItem* item);//give from modelparticle
-
- void setFade(bool arg){if (arg == m_fade) return; m_fade = arg; emit fadeChanged();}
- void setDelegate(QDeclarativeComponent* arg)
- {
- if (m_delegate != arg) {
- m_delegate = arg;
- emit delegateChanged(arg);
- }
- }
-
-protected:
- virtual void reset();
- virtual void commit(int gIdx, int pIdx);
- virtual void initialize(int gIdx, int pIdx);
- void prepareNextFrame();
-private slots:
- void tick();
-private:
- QList<QQuickItem* > m_deletables;
- QList< QQuickParticleData* > m_loadables;
- bool m_fade;
-
- QList<QQuickItem*> m_pendingItems;
- QList<int> m_available;
- QSet<QQuickItem*> m_stasis;
- qreal m_lastT;
- int m_activeCount;
- QDeclarativeComponent* m_delegate;
-};
-
-class QQuickItemParticleAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQuickItemParticle* particle READ particle CONSTANT);
-public:
- QQuickItemParticleAttached(QObject* parent)
- : QObject(parent), m_mp(0)
- {;}
- QQuickItemParticle* particle() {return m_mp;}
- void detach(){emit detached();}
- void attach(){emit attached();}
-private:
- QQuickItemParticle* m_mp;
- friend class QQuickItemParticle;
-Q_SIGNALS:
- void detached();
- void attached();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPEINFO(QQuickItemParticle, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-#endif // ITEMPARTICLE_H
diff --git a/src/declarative/particles/qquickmaskextruder_p.h b/src/declarative/particles/qquickmaskextruder_p.h
deleted file mode 100644
index 9430321e50..0000000000
--- a/src/declarative/particles/qquickmaskextruder_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 MASKEXTRUDER_H
-#define MASKEXTRUDER_H
-#include "qquickparticleextruder_p.h"
-#include <QUrl>
-#include <QImage>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickMaskExtruder : public QQuickParticleExtruder
-{
- Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
-public:
- explicit QQuickMaskExtruder(QObject *parent = 0);
- virtual QPointF extrude(const QRectF &);
- virtual bool contains(const QRectF &bounds, const QPointF &point);
-
- QUrl source() const
- {
- return m_source;
- }
-
-signals:
-
- void sourceChanged(QUrl arg);
-
-public slots:
-
- void setSource(QUrl arg)
- {
- if (m_source != arg) {
- m_source = arg;
- m_lastHeight = -1;//Trigger reset
- m_lastWidth = -1;
- emit sourceChanged(arg);
- }
- }
-private:
- QUrl m_source;
-
- void ensureInitialized(const QRectF &r);
- int m_lastWidth;
- int m_lastHeight;
- QImage m_img;
- QList<QPointF> m_mask;//TODO: More memory efficient datastructures
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // MASKEXTRUDER_H
diff --git a/src/declarative/particles/qquickparticleaffector_p.h b/src/declarative/particles/qquickparticleaffector_p.h
deleted file mode 100644
index d254759ff6..0000000000
--- a/src/declarative/particles/qquickparticleaffector_p.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 PARTICLEAFFECTOR_H
-#define PARTICLEAFFECTOR_H
-
-#include <QObject>
-#include "qquickparticlesystem_p.h"
-#include "qquickparticleextruder_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticleAffector : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
- Q_PROPERTY(QStringList whenCollidingWith READ whenCollidingWith WRITE setWhenCollidingWith NOTIFY whenCollidingWithChanged)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
- Q_PROPERTY(QQuickParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
-
-public:
- explicit QQuickParticleAffector(QQuickItem *parent = 0);
- virtual void affectSystem(qreal dt);
- virtual void reset(QQuickParticleData*);//As some store their own data per particle?
- QQuickParticleSystem* system() const
- {
- return m_system;
- }
-
- QStringList groups() const
- {
- return m_groups;
- }
-
- bool enabled() const
- {
- return m_enabled;
- }
-
- bool onceOff() const
- {
- return m_onceOff;
- }
-
- QQuickParticleExtruder* shape() const
- {
- return m_shape;
- }
-
- QStringList whenCollidingWith() const
- {
- return m_whenCollidingWith;
- }
-
-signals:
-
- void systemChanged(QQuickParticleSystem* arg);
-
- void groupsChanged(QStringList arg);
-
- void enabledChanged(bool arg);
-
- void onceChanged(bool arg);
-
- void shapeChanged(QQuickParticleExtruder* arg);
-
- void affected(qreal x, qreal y);
-
- void whenCollidingWithChanged(QStringList arg);
-
-public slots:
-void setSystem(QQuickParticleSystem* arg)
-{
- if (m_system != arg) {
- m_system = arg;
- m_system->registerParticleAffector(this);
- emit systemChanged(arg);
- }
-}
-
-void setGroups(QStringList arg)
-{
- if (m_groups != arg) {
- m_groups = arg;
- m_updateIntSet = true;
- emit groupsChanged(arg);
- }
-}
-
-void setEnabled(bool arg)
-{
- if (m_enabled != arg) {
- m_enabled = arg;
- emit enabledChanged(arg);
- }
-}
-
-void setOnceOff(bool arg)
-{
- if (m_onceOff != arg) {
- m_onceOff = arg;
- m_needsReset = true;
- emit onceChanged(arg);
- }
-}
-
-void setShape(QQuickParticleExtruder* arg)
-{
- if (m_shape != arg) {
- m_shape = arg;
- emit shapeChanged(arg);
- }
-}
-
-void setWhenCollidingWith(QStringList arg)
-{
- if (m_whenCollidingWith != arg) {
- m_whenCollidingWith = arg;
- emit whenCollidingWithChanged(arg);
- }
-}
-public slots:
- void updateOffsets();
-
-protected:
- friend class QQuickParticleSystem;
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
- bool m_needsReset:1;//### What is this really saving?
- bool m_ignoresTime:1;
- bool m_onceOff:1;
- bool m_enabled:1;
-
- QQuickParticleSystem* m_system;
- QStringList m_groups;
- bool activeGroup(int g);
- bool shouldAffect(QQuickParticleData* datum);//Call to do the logic on whether it is affecting that datum
- void postAffect(QQuickParticleData* datum);//Call to do the post-affect logic on particles which WERE affected(once off, needs reset, affected signal)
- virtual void componentComplete();
- QPointF m_offset;
- bool isAffectedConnected();
- static const qreal simulationDelta;
- static const qreal simulationCutoff;
-private:
- QSet<int> m_groupIds;
- QSet<QPair<int, int> > m_onceOffed;
- bool m_updateIntSet;
-
- QQuickParticleExtruder* m_shape;
-
- QStringList m_whenCollidingWith;
-
- bool isColliding(QQuickParticleData* d);
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // PARTICLEAFFECTOR_H
diff --git a/src/declarative/particles/qquickparticleemitter_p.h b/src/declarative/particles/qquickparticleemitter_p.h
deleted file mode 100644
index 2d725e5c9e..0000000000
--- a/src/declarative/particles/qquickparticleemitter_p.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 PARTICLEEMITTER_H
-#define PARTICLEEMITTER_H
-
-#include <QQuickItem>
-#include <QDebug>
-#include "qquickparticlesystem_p.h"
-#include "qquickparticleextruder_p.h"
-#include "qquickdirection_p.h"
-
-#include <QList>
-#include <QPair>
-#include <QPointF>
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticleEmitter : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
- Q_PROPERTY(QString group READ group WRITE setGroup NOTIFY groupChanged)
- Q_PROPERTY(QQuickParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
-
- Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
- Q_PROPERTY(int lifeSpan READ particleDuration WRITE setParticleDuration NOTIFY particleDurationChanged)
- Q_PROPERTY(int lifeSpanVariation READ particleDurationVariation WRITE setParticleDurationVariation NOTIFY particleDurationVariationChanged)
- Q_PROPERTY(int maximumEmitted READ maxParticleCount WRITE setMaxParticleCount NOTIFY maximumEmittedChanged)
-
- Q_PROPERTY(qreal size READ particleSize WRITE setParticleSize NOTIFY particleSizeChanged)
- Q_PROPERTY(qreal endSize READ particleEndSize WRITE setParticleEndSize NOTIFY particleEndSizeChanged)
- Q_PROPERTY(qreal sizeVariation READ particleSizeVariation WRITE setParticleSizeVariation NOTIFY particleSizeVariationChanged)
-
- Q_PROPERTY(QQuickDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
- Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
- Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
-
- Q_ENUMS(Lifetime)
-public:
- explicit QQuickParticleEmitter(QQuickItem *parent = 0);
- virtual ~QQuickParticleEmitter();
- virtual void emitWindow(int timeStamp);
-
- enum Lifetime {
- InfiniteLife = QQuickParticleSystem::maxLife
- };
-
- bool enabled() const
- {
- return m_enabled;
- }
-
- qreal particlesPerSecond() const
- {
- return m_particlesPerSecond;
- }
-
- int particleDuration() const
- {
- return m_particleDuration;
- }
-
- QQuickParticleSystem* system() const
- {
- return m_system;
- }
-
- QString group() const
- {
- return m_group;
- }
-
- int particleDurationVariation() const
- {
- return m_particleDurationVariation;
- }
-
- qreal speedFromMovement() const { return m_speed_from_movement; }
- void setSpeedFromMovement(qreal s);
- virtual void componentComplete();
-signals:
- void emitParticles(QDeclarativeV8Handle particles);
- void particlesPerSecondChanged(qreal);
- void particleDurationChanged(int);
- void enabledChanged(bool);
-
- void systemChanged(QQuickParticleSystem* arg);
-
- void groupChanged(QString arg);
-
- void particleDurationVariationChanged(int arg);
-
- void extruderChanged(QQuickParticleExtruder* arg);
-
- void particleSizeChanged(qreal arg);
-
- void particleEndSizeChanged(qreal arg);
-
- void particleSizeVariationChanged(qreal arg);
-
- void speedChanged(QQuickDirection * arg);
-
- void accelerationChanged(QQuickDirection * arg);
-
- void maximumEmittedChanged(int arg);
- void particleCountChanged();
-
- void speedFromMovementChanged();
-
- void startTimeChanged(int arg);
-
-public slots:
- void pulse(int milliseconds);
- void burst(int num);
- void burst(int num, qreal x, qreal y);
-
- void setEnabled(bool arg);
-
- void setParticlesPerSecond(qreal arg)
- {
- if (m_particlesPerSecond != arg) {
- m_particlesPerSecond = arg;
- emit particlesPerSecondChanged(arg);
- }
- }
-
- void setParticleDuration(int arg)
- {
- if (m_particleDuration != arg) {
- m_particleDuration = arg;
- emit particleDurationChanged(arg);
- }
- }
-
- void setSystem(QQuickParticleSystem* arg)
- {
- if (m_system != arg) {
- m_system = arg;
- m_system->registerParticleEmitter(this);
- emit systemChanged(arg);
- }
- }
-
- void setGroup(QString arg)
- {
- if (m_group != arg) {
- m_group = arg;
- emit groupChanged(arg);
- }
- }
-
- void setParticleDurationVariation(int arg)
- {
- if (m_particleDurationVariation != arg) {
- m_particleDurationVariation = arg;
- emit particleDurationVariationChanged(arg);
- }
- }
- void setExtruder(QQuickParticleExtruder* arg)
- {
- if (m_extruder != arg) {
- m_extruder = arg;
- emit extruderChanged(arg);
- }
- }
-
- void setParticleSize(qreal arg)
- {
- if (m_particleSize != arg) {
- m_particleSize = arg;
- emit particleSizeChanged(arg);
- }
- }
-
- void setParticleEndSize(qreal arg)
- {
- if (m_particleEndSize != arg) {
- m_particleEndSize = arg;
- emit particleEndSizeChanged(arg);
- }
- }
-
- void setParticleSizeVariation(qreal arg)
- {
- if (m_particleSizeVariation != arg) {
- m_particleSizeVariation = arg;
- emit particleSizeVariationChanged(arg);
- }
- }
-
- void setSpeed(QQuickDirection * arg)
- {
- if (m_speed != arg) {
- m_speed = arg;
- emit speedChanged(arg);
- }
- }
-
- void setAcceleration(QQuickDirection * arg)
- {
- if (m_acceleration != arg) {
- m_acceleration = arg;
- emit accelerationChanged(arg);
- }
- }
-
- void setMaxParticleCount(int arg);
-
- void setStartTime(int arg)
- {
- if (m_startTime != arg) {
- m_startTime = arg;
- emit startTimeChanged(arg);
- }
- }
-
- virtual void reset();
-public:
- int particleCount() const;
-
- QQuickParticleExtruder* extruder() const
- {
- return m_extruder;
- }
-
- qreal particleSize() const
- {
- return m_particleSize;
- }
-
- qreal particleEndSize() const
- {
- return m_particleEndSize;
- }
-
- qreal particleSizeVariation() const
- {
- return m_particleSizeVariation;
- }
-
- QQuickDirection * speed() const
- {
- return m_speed;
- }
-
- QQuickDirection * acceleration() const
- {
- return m_acceleration;
- }
-
- int maxParticleCount() const
- {
- return m_maxParticleCount;
- }
-
- int startTime() const
- {
- return m_startTime;
- }
-
-protected:
- qreal m_particlesPerSecond;
- int m_particleDuration;
- int m_particleDurationVariation;
- bool m_enabled;
- QQuickParticleSystem* m_system;
- QString m_group;
- QQuickParticleExtruder* m_extruder;
- QQuickParticleExtruder* m_defaultExtruder;
- QQuickParticleExtruder* effectiveExtruder();
- QQuickDirection * m_speed;
- QQuickDirection * m_acceleration;
- qreal m_particleSize;
- qreal m_particleEndSize;
- qreal m_particleSizeVariation;
-
- qreal m_speedFromMovement;
- int m_startTime;
- bool m_overwrite;
-
- int m_pulseLeft;
- QList<QPair<int, QPointF > > m_burstQueue;
- int m_maxParticleCount;
-
- //Used in default implementation, but might be useful
- qreal m_speed_from_movement;
-
- int m_emitCap;
- bool m_reset_last;
- qreal m_last_timestamp;
- qreal m_last_emission;
-
- QPointF m_last_emitter;
- QPointF m_last_last_emitter;
- QPointF m_last_last_last_emitter;
-
- bool isEmitConnected();
-private:
- QQuickDirection m_nullVector;
-
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // PARTICLEEMITTER_H
diff --git a/src/declarative/particles/qquickparticleextruder_p.h b/src/declarative/particles/qquickparticleextruder_p.h
deleted file mode 100644
index 7969abad7c..0000000000
--- a/src/declarative/particles/qquickparticleextruder_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 PARTICLEEXTRUDER_H
-#define PARTICLEEXTRUDER_H
-
-#include <QObject>
-#include <QRectF>
-#include <QPointF>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticleExtruder : public QObject
-{
- Q_OBJECT
-
-public:
- explicit QQuickParticleExtruder(QObject *parent = 0);
- virtual QPointF extrude(const QRectF &);
- virtual bool contains(const QRectF &bounds, const QPointF &point);
-
-signals:
-public slots:
-protected:
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // PARTICLEEXTRUDER_H
diff --git a/src/declarative/particles/qquickparticlepainter_p.h b/src/declarative/particles/qquickparticlepainter_p.h
deleted file mode 100644
index e80d68fa09..0000000000
--- a/src/declarative/particles/qquickparticlepainter_p.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 PARTICLE_H
-#define PARTICLE_H
-
-#include <QObject>
-#include <QDebug>
-#include <QPair>
-#include "qquickparticlesystem_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickParticlePainter : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
-
-public:
- explicit QQuickParticlePainter(QQuickItem *parent = 0);
- //Data Interface to system
- void load(QQuickParticleData*);
- void reload(QQuickParticleData*);
- void setCount(int c);
- int count();
- void performPendingCommits();//Called from updatePaintNode
- QQuickParticleSystem* system() const
- {
- return m_system;
- }
-
-
- QStringList groups() const
- {
- return m_groups;
- }
-
-signals:
- void countChanged();
- void systemChanged(QQuickParticleSystem* arg);
-
- void groupsChanged(QStringList arg);
-
-public slots:
- void setSystem(QQuickParticleSystem* arg);
-
- void setGroups(QStringList arg)
- {
- if (m_groups != arg) {
- m_groups = arg;
- emit groupsChanged(arg);
- }
- }
-
- void calcSystemOffset(bool resetPending = false);
-
-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.
- ###Hunt down all cases where we do a complete reset for convenience and be more targeted
- */
- virtual void reset();
-
- virtual void componentComplete();
- virtual void initialize(int gIdx, int pIdx){//Called from main thread
- Q_UNUSED(gIdx);
- Q_UNUSED(pIdx);
- }
- virtual void commit(int gIdx, int pIdx){//Called in Render Thread
- //###If you need to do something on size changed, check m_data size in this? Or we reset you every time?
- Q_UNUSED(gIdx);
- Q_UNUSED(pIdx);
- }
-
- QQuickParticleSystem* m_system;
- friend class QQuickParticleSystem;
- int m_count;
- bool m_pleaseReset;//Used by subclasses, but it's a nice optimization to know when stuff isn't going to matter.
- QStringList m_groups;
- QPointF m_systemOffset;
-
-private:
- QSet<QPair<int,int> > m_pendingCommits;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // PARTICLE_H
diff --git a/src/declarative/particles/qquickparticlesmodule_p.h b/src/declarative/particles/qquickparticlesmodule_p.h
deleted file mode 100644
index afea56293b..0000000000
--- a/src/declarative/particles/qquickparticlesmodule_p.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQuickPARTICLESMODULE_H
-#define QQuickPARTICLESMODULE_H
-
-#include <qdeclarative.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticlesModule
-{
-public:
- static void defineModule();
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QQuickPARTICLESMODULE_H
diff --git a/src/declarative/particles/qquickparticlesystem.cpp b/src/declarative/particles/qquickparticlesystem.cpp
deleted file mode 100644
index 9e6bafab20..0000000000
--- a/src/declarative/particles/qquickparticlesystem.cpp
+++ /dev/null
@@ -1,1106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 "qquickparticlesystem_p.h"
-#include <qsgnode.h>
-#include "qquickparticleemitter_p.h"
-#include "qquickparticleaffector_p.h"
-#include "qquickparticlepainter_p.h"
-#include <private/qquickspriteengine_p.h>
-#include <private/qquicksprite_p.h>
-#include "qquickv8particledata_p.h"
-#include "qquickparticlegroup_p.h"
-
-#include "qquicktrailemitter_p.h"//###For auto-follow on states, perhaps should be in emitter?
-#include <private/qdeclarativeengine_p.h>
-#include <cmath>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
-DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
-/*!
- \qmlclass ParticleSystem QQuickParticleSystem
- \inqmlmodule QtQuick.Particles 2
- \brief The ParticleSystem brings together ParticlePainter, Emitter and Affector elements.
-
-*/
-
-/*!
- \qmlproperty bool QtQuick.Particles2::ParticleSystem::running
-
- If running is set to false, the particle system will stop the simulation. All particles
- will be destroyed when the system is set to running again.
-
- It can also be controlled with the start() and stop() methods.
-*/
-
-
-/*!
- \qmlproperty bool QtQuick.Particles2::ParticleSystem::paused
-
- If paused is set to true, the particle system will not advance the simulation. When
- paused is set to false again, the simulation will resume from the same point it was
- paused.
-
- The simulation will automatically pause if it detects that there are no live particles
- left, and unpause when new live particles are added.
-
- It can also be controlled with the pause() and resume() methods.
-*/
-
-/*!
- \qmlproperty bool QtQuick.Particles2::ParticleSystem::empty
-
- empty is set to true when there are no live particles left in the system.
-
- You can use this to pause the system, keeping it from spending any time updating,
- but you will need to resume it in order for additional particles to be generated
- by the system.
-
- To kill all the particles in the system, use a Kill affector.
-*/
-
-/*!
- \qmlproperty list<Sprite> QtQuick.Particles2::ParticleSystem::particleStates
-
- You can define a sub-set of particle groups in this property in order to provide them
- with stochastic state transitions.
-
- Each QtQuick2::Sprite in this list is interpreted as corresponding to the particle group
- with ths same name. Any transitions defined in these sprites will take effect on the particle
- groups as well. Additionally TrailEmitters, Affectors and ParticlePainters definined
- inside one of these sprites are automatically associated with the corresponding particle group.
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::pause
-
- Pauses the simulation if it is running.
-
- \sa resume, paused
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::resume
-
- Resumes the simulation if it is paused.
-
- \sa pause, paused
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::start
-
- Starts the simulation if it has not already running.
-
- \sa stop, restart, running
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::stop
-
- Stops the simulation if it is running.
-
- \sa start, restart, running
-*/
-
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::restart
-
- Stops the simulation if it is running, and then starts it.
-
- \sa stop, restart, running
-*/
-/*!
- \qmlmethod void QtQuick.Particles2::ParticleSystem::reset
-
- Discards all currently existing particles.
-
-*/
-const qreal EPSILON = 0.001;
-//Utility functions for when within 1ms is close enough
-bool timeEqualOrGreater(qreal a, qreal b)
-{
- return (a+EPSILON >= b);
-}
-
-bool timeLess(qreal a, qreal b)
-{
- return (a-EPSILON < b);
-}
-
-bool timeEqual(qreal a, qreal b)
-{
- return (a+EPSILON > b) && (a-EPSILON < b);
-}
-
-int roundedTime(qreal a)
-{// in ms
- return (int)qRound(a*1000.0);
-}
-
-QQuickParticleDataHeap::QQuickParticleDataHeap()
- : m_data(0)
-{
- m_data.reserve(1000);
- clear();
-}
-
-void QQuickParticleDataHeap::grow() //###Consider automatic growth vs resize() calls from GroupData
-{
- m_data.resize(1 << ++m_size);
-}
-
-void QQuickParticleDataHeap::insert(QQuickParticleData* data)
-{
- insertTimed(data, roundedTime(data->t + data->lifeSpan));
-}
-
-void QQuickParticleDataHeap::insertTimed(QQuickParticleData* data, int time)
-{
- //TODO: Optimize 0 lifespan (or already dead) case
- if (m_lookups.contains(time)) {
- m_data[m_lookups[time]].data << data;
- return;
- }
- if (m_end == (1 << m_size))
- grow();
- m_data[m_end].time = time;
- m_data[m_end].data.clear();
- m_data[m_end].data.insert(data);
- m_lookups.insert(time, m_end);
- bubbleUp(m_end++);
-}
-
-int QQuickParticleDataHeap::top()
-{
- if (m_end == 0)
- return 1 << 30;
- return m_data[0].time;
-}
-
-QSet<QQuickParticleData*> QQuickParticleDataHeap::pop()
-{
- if (!m_end)
- return QSet<QQuickParticleData*> ();
- QSet<QQuickParticleData*> ret = m_data[0].data;
- m_lookups.remove(m_data[0].time);
- if (m_end == 1) {
- --m_end;
- } else {
- m_data[0] = m_data[--m_end];
- bubbleDown(0);
- }
- return ret;
-}
-
-void QQuickParticleDataHeap::clear()
-{
- m_size = 0;
- m_end = 0;
- //m_size is in powers of two. So to start at 0 we have one allocated
- m_data.resize(1);
- m_lookups.clear();
-}
-
-bool QQuickParticleDataHeap::contains(QQuickParticleData* d)
-{
- for (int i=0; i<m_end; i++)
- if (m_data[i].data.contains(d))
- return true;
- return false;
-}
-
-void QQuickParticleDataHeap::swap(int a, int b)
-{
- m_tmp = m_data[a];
- m_data[a] = m_data[b];
- m_data[b] = m_tmp;
- m_lookups[m_data[a].time] = a;
- m_lookups[m_data[b].time] = b;
-}
-
-void QQuickParticleDataHeap::bubbleUp(int idx)//tends to be called once
-{
- if (!idx)
- return;
- int parent = (idx-1)/2;
- if (m_data[idx].time < m_data[parent].time) {
- swap(idx, parent);
- bubbleUp(parent);
- }
-}
-
-void QQuickParticleDataHeap::bubbleDown(int idx)//tends to be called log n times
-{
- int left = idx*2 + 1;
- if (left >= m_end)
- return;
- int lesser = left;
- int right = idx*2 + 2;
- if (right < m_end) {
- if (m_data[left].time > m_data[right].time)
- lesser = right;
- }
- if (m_data[idx].time > m_data[lesser].time) {
- swap(idx, lesser);
- bubbleDown(lesser);
- }
-}
-
-QQuickParticleGroupData::QQuickParticleGroupData(int id, QQuickParticleSystem* sys):index(id),m_size(0),m_system(sys)
-{
- initList();
-}
-
-QQuickParticleGroupData::~QQuickParticleGroupData()
-{
- foreach (QQuickParticleData* d, data)
- delete d;
-}
-
-int QQuickParticleGroupData::size()
-{
- return m_size;
-}
-
-QString QQuickParticleGroupData::name()//### Worth caching as well?
-{
- return m_system->groupIds.key(index);
-}
-
-void QQuickParticleGroupData::setSize(int newSize)
-{
- if (newSize == m_size)
- return;
- Q_ASSERT(newSize > m_size);//XXX allow shrinking
- data.resize(newSize);
- for (int i=m_size; i<newSize; i++) {
- data[i] = new QQuickParticleData(m_system);
- data[i]->group = index;
- data[i]->index = i;
- reusableIndexes << i;
- }
- int delta = newSize - m_size;
- m_size = newSize;
- foreach (QQuickParticlePainter* p, painters)
- p->setCount(p->count() + delta);
-}
-
-void QQuickParticleGroupData::initList()
-{
- dataHeap.clear();
-}
-
-void QQuickParticleGroupData::kill(QQuickParticleData* d)
-{
- Q_ASSERT(d->group == index);
- d->lifeSpan = 0;//Kill off
- foreach (QQuickParticlePainter* p, painters)
- p->reload(d);
- reusableIndexes << d->index;
-}
-
-QQuickParticleData* QQuickParticleGroupData::newDatum(bool respectsLimits)
-{
- //recycle();//Extra recycler round to be sure?
-
- while (!reusableIndexes.empty()) {
- int idx = *(reusableIndexes.begin());
- reusableIndexes.remove(idx);
- if (data[idx]->stillAlive()) {// ### This means resurrection of 'dead' particles. Is that allowed?
- prepareRecycler(data[idx]);
- continue;
- }
- return data[idx];
- }
- if (respectsLimits)
- return 0;
-
- int oldSize = m_size;
- setSize(oldSize + 10);//###+1,10%,+10? Choose something non-arbitrarily
- reusableIndexes.remove(oldSize);
- return data[oldSize];
-}
-
-bool QQuickParticleGroupData::recycle()
-{
- while (dataHeap.top() <= m_system->timeInt) {
- foreach (QQuickParticleData* datum, dataHeap.pop()) {
- if (!datum->stillAlive()) {
- reusableIndexes << datum->index;
- } else {
- prepareRecycler(datum); //ttl has been altered mid-way, put it back
- }
- }
- }
-
- //TODO: If the data is clear, gc (consider shrinking stack size)?
- return reusableIndexes.count() == m_size;
-}
-
-void QQuickParticleGroupData::prepareRecycler(QQuickParticleData* d)
-{
- if (d->lifeSpan*1000 < m_system->maxLife) {
- dataHeap.insert(d);
- } else {
- while ((roundedTime(d->t) + 2*m_system->maxLife/3) <= m_system->timeInt)
- d->extendLife(m_system->maxLife/3000.0);
- dataHeap.insertTimed(d, roundedTime(d->t) + 2*m_system->maxLife/3);
- }
-}
-
-QQuickParticleData::QQuickParticleData(QQuickParticleSystem* sys)
- : group(0)
- , e(0)
- , system(sys)
- , index(0)
- , systemIndex(-1)
- , colorOwner(0)
- , rotationOwner(0)
- , deformationOwner(0)
- , animationOwner(0)
- , v8Datum(0)
-{
- x = 0;
- y = 0;
- t = -1;
- lifeSpan = 0;
- size = 0;
- endSize = 0;
- vx = 0;
- vy = 0;
- ax = 0;
- ay = 0;
- xx = 1;
- xy = 0;
- yx = 0;
- yy = 1;
- rotation = 0;
- rotationSpeed = 0;
- autoRotate = 0;
- animIdx = 0;
- frameDuration = 1;
- frameCount = 1;
- animT = -1;
- animX = 0;
- animY = 0;
- animWidth = 1;
- animHeight = 1;
- color.r = 255;
- color.g = 255;
- color.b = 255;
- color.a = 255;
- r = 0;
- delegate = 0;
- modelIndex = -1;
-}
-
-QQuickParticleData::~QQuickParticleData()
-{
- delete v8Datum;
-}
-
-void QQuickParticleData::clone(const QQuickParticleData& other)
-{
- x = other.x;
- y = other.y;
- t = other.t;
- lifeSpan = other.lifeSpan;
- size = other.size;
- endSize = other.endSize;
- vx = other.vx;
- vy = other.vy;
- ax = other.ax;
- ay = other.ay;
- xx = other.xx;
- xy = other.xy;
- yx = other.yx;
- yy = other.yy;
- rotation = other.rotation;
- rotationSpeed = other.rotationSpeed;
- autoRotate = other.autoRotate;
- animIdx = other.animIdx;
- frameDuration = other.frameDuration;
- frameCount = other.frameCount;
- animT = other.animT;
- animX = other.animX;
- animY = other.animY;
- animWidth = other.animWidth;
- animHeight = other.animHeight;
- color.r = other.color.r;
- color.g = other.color.g;
- color.b = other.color.b;
- color.a = other.color.a;
- r = other.r;
- delegate = other.delegate;
- modelIndex = other.modelIndex;
-
- colorOwner = other.colorOwner;
- rotationOwner = other.rotationOwner;
- deformationOwner = other.deformationOwner;
- animationOwner = other.animationOwner;
-}
-
-QDeclarativeV8Handle QQuickParticleData::v8Value()
-{
- if (!v8Datum)
- v8Datum = new QQuickV8ParticleData(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(system)), this);
- return v8Datum->v8Value();
-}
-//sets the x accleration without affecting the instantaneous x velocity or position
-void QQuickParticleData::setInstantaneousAX(qreal ax)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- qreal vx = (this->vx + t*this->ax) - t*ax;
- qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t;
- qreal x = ex - t*vx - 0.5 * t*t*ax;
-
- this->ax = ax;
- this->vx = vx;
- this->x = x;
-}
-
-//sets the x velocity without affecting the instantaneous x postion
-void QQuickParticleData::setInstantaneousVX(qreal vx)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- qreal evx = vx - t*this->ax;
- qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t;
- qreal x = ex - t*evx - 0.5 * t*t*this->ax;
-
- this->vx = evx;
- this->x = x;
-}
-
-//sets the instantaneous x postion
-void QQuickParticleData::setInstantaneousX(qreal x)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- this->x = x - t*this->vx - 0.5 * t*t*this->ax;
-}
-
-//sets the y accleration without affecting the instantaneous y velocity or position
-void QQuickParticleData::setInstantaneousAY(qreal ay)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- qreal vy = (this->vy + t*this->ay) - t*ay;
- qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t;
- qreal y = ey - t*vy - 0.5 * t*t*ay;
-
- this->ay = ay;
- this->vy = vy;
- this->y = y;
-}
-
-//sets the y velocity without affecting the instantaneous y position
-void QQuickParticleData::setInstantaneousVY(qreal vy)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- qreal evy = vy - t*this->ay;
- qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t;
- qreal y = ey - t*evy - 0.5 * t*t*this->ay;
-
- this->vy = evy;
- this->y = y;
-}
-
-//sets the instantaneous Y position
-void QQuickParticleData::setInstantaneousY(qreal y)
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- this->y = y - t*this->vy - 0.5 * t*t*this->ay;
-}
-
-qreal QQuickParticleData::curX() const
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- return this->x + this->vx * t + 0.5 * this->ax * t * t;
-}
-
-qreal QQuickParticleData::curVX() const
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- return this->vx + t*this->ax;
-}
-
-qreal QQuickParticleData::curY() const
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- return y + vy * t + 0.5 * ay * t * t;
-}
-
-qreal QQuickParticleData::curVY() const
-{
- qreal t = (system->timeInt / 1000.0) - this->t;
- return vy + t*ay;
-}
-
-void QQuickParticleData::debugDump()
-{
- qDebug() << "Particle" << systemIndex << group << "/" << index << stillAlive()
- << "Pos: " << x << "," << y
- << "Vel: " << vx << "," << vy
- << "Acc: " << ax << "," << ay
- << "Size: " << size << "," << endSize
- << "Time: " << t << "," <<lifeSpan << ";" << (system->timeInt / 1000.0) ;
-}
-
-bool QQuickParticleData::stillAlive()
-{
- if (!system)
- return false;
- return (t + lifeSpan - EPSILON) > ((qreal)system->timeInt/1000.0);
-}
-
-bool QQuickParticleData::alive()
-{
- if (!system)
- return false;
- qreal st = ((qreal)system->timeInt/1000.0);
- return (t + EPSILON) < st && (t + lifeSpan - EPSILON) > st;
-}
-
-float QQuickParticleData::curSize()
-{
- if (!system || !lifeSpan)
- return 0.0f;
- return size + (endSize - size) * (1 - (lifeLeft() / lifeSpan));
-}
-
-float QQuickParticleData::lifeLeft()
-{
- if (!system)
- return 0.0f;
- return (t + lifeSpan) - (system->timeInt/1000.0);
-}
-
-void QQuickParticleData::extendLife(float time)
-{
- qreal newX = curX();
- qreal newY = curY();
- qreal newVX = curVX();
- qreal newVY = curVY();
-
- t += time;
- animT += time;
-
- qreal elapsed = (system->timeInt / 1000.0) - t;
- qreal evy = newVY - elapsed*ay;
- qreal ey = newY - elapsed*evy - 0.5 * elapsed*elapsed*ay;
- qreal evx = newVX - elapsed*ax;
- qreal ex = newX - elapsed*evx - 0.5 * elapsed*elapsed*ax;
-
- x = ex;
- vx = evx;
- y = ey;
- vy = evy;
-}
-
-QQuickParticleSystem::QQuickParticleSystem(QQuickItem *parent) :
- QQuickItem(parent),
- stateEngine(0),
- m_running(true),
- particleCount(0),
- m_nextIndex(0),
- m_componentComplete(false),
- m_paused(false)
-{
- connect(&m_painterMapper, SIGNAL(mapped(QObject*)),
- this, SLOT(loadPainter(QObject*)));
-
- m_debugMode = qmlParticlesDebug();
-}
-
-QQuickParticleSystem::~QQuickParticleSystem()
-{
- foreach (QQuickParticleGroupData* gd, groupData)
- delete gd;
-}
-
-void QQuickParticleSystem::initGroups()
-{
- m_reusableIndexes.clear();
- m_nextIndex = 0;
-
- qDeleteAll(groupData);
- groupData.clear();
- groupIds.clear();
-
- QQuickParticleGroupData* gd = new QQuickParticleGroupData(0, this);//Default group
- groupData.insert(0,gd);
- groupIds.insert(QString(), 0);
- m_nextGroupId = 1;
-}
-
-void QQuickParticleSystem::registerParticlePainter(QQuickParticlePainter* p)
-{
- //TODO: a way to Unregister emitters, painters and affectors
- m_painters << QPointer<QQuickParticlePainter>(p);//###Set or uniqueness checking?
- connect(p, SIGNAL(groupsChanged(QStringList)),
- &m_painterMapper, SLOT(map()));
- loadPainter(p);
-}
-
-void QQuickParticleSystem::registerParticleEmitter(QQuickParticleEmitter* e)
-{
- m_emitters << QPointer<QQuickParticleEmitter>(e);//###How to get them out?
- connect(e, SIGNAL(particleCountChanged()),
- this, SLOT(emittersChanged()));
- connect(e, SIGNAL(groupChanged(QString)),
- this, SLOT(emittersChanged()));
- emittersChanged();
- e->reset();//Start, so that starttime factors appropriately
-}
-
-void QQuickParticleSystem::registerParticleAffector(QQuickParticleAffector* a)
-{
- m_affectors << QPointer<QQuickParticleAffector>(a);
-}
-
-void QQuickParticleSystem::registerParticleGroup(QQuickParticleGroup* g)
-{
- m_groups << QPointer<QQuickParticleGroup>(g);
- createEngine();
-}
-
-void QQuickParticleSystem::setRunning(bool arg)
-{
- if (m_running != arg) {
- m_running = arg;
- emit runningChanged(arg);
- setPaused(false);
- if (m_animation)//Not created until componentCompleted
- m_running ? m_animation->start() : m_animation->stop();
- reset();
- }
-}
-
-void QQuickParticleSystem::setPaused(bool arg) {
- if (m_paused != arg) {
- m_paused = arg;
- if (m_animation && m_animation->state() != QAbstractAnimation::Stopped)
- m_paused ? m_animation->pause() : m_animation->resume();
- if (!m_paused) {
- foreach (QQuickParticlePainter *p, m_painters)
- p->update();
- }
- emit pausedChanged(arg);
- }
-}
-
-void QQuickParticleSystem::statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
-{
- //Hooks up automatic state-associated stuff
- QQuickParticleSystem* sys = qobject_cast<QQuickParticleSystem*>(prop->object->parent());
- QQuickParticleGroup* group = qobject_cast<QQuickParticleGroup*>(prop->object);
- if (!group || !sys || !value)
- return;
- stateRedirect(group, sys, value);
-}
-
-void QQuickParticleSystem::stateRedirect(QQuickParticleGroup* group, QQuickParticleSystem* sys, QObject *value)
-{
- QStringList list;
- list << group->name();
- QQuickParticleAffector* a = qobject_cast<QQuickParticleAffector*>(value);
- if (a) {
- a->setParentItem(sys);
- a->setGroups(list);
- a->setSystem(sys);
- return;
- }
- QQuickTrailEmitter* fe = qobject_cast<QQuickTrailEmitter*>(value);
- if (fe) {
- fe->setParentItem(sys);
- fe->setFollow(group->name());
- fe->setSystem(sys);
- return;
- }
- QQuickParticleEmitter* e = qobject_cast<QQuickParticleEmitter*>(value);
- if (e) {
- e->setParentItem(sys);
- e->setGroup(group->name());
- e->setSystem(sys);
- return;
- }
- QQuickParticlePainter* p = qobject_cast<QQuickParticlePainter*>(value);
- if (p) {
- p->setParentItem(sys);
- p->setGroups(list);
- p->setSystem(sys);
- return;
- }
- qWarning() << value << " was placed inside a particle system state but cannot be taken into the particle system. It will be lost.";
-}
-
-void QQuickParticleSystem::componentComplete()
-
-{
- QQuickItem::componentComplete();
- m_componentComplete = true;
- m_animation = new QQuickParticleSystemAnimation(this);
- reset();//restarts animation as well
-}
-
-void QQuickParticleSystem::reset()
-{
- if (!m_componentComplete)
- return;
-
- timeInt = 0;
- //Clear guarded pointers which have been deleted
- int cleared = 0;
- cleared += m_emitters.removeAll(0);
- cleared += m_painters.removeAll(0);
- cleared += m_affectors.removeAll(0);
-
- bySysIdx.resize(0);
- initGroups();//Also clears all logical particles
-
- if (!m_running)
- return;
-
- foreach (QQuickParticleEmitter* e, m_emitters)
- e->reset();
-
- emittersChanged();
-
- foreach (QQuickParticlePainter *p, m_painters) {
- loadPainter(p);
- p->reset();
- }
-
- //### Do affectors need reset too?
- if (m_animation) {//Animation is explicitly disabled in benchmarks
- //reset restarts animation (if running)
- if ((m_animation->state() == QAbstractAnimation::Running))
- m_animation->stop();
- m_animation->start();
- if (m_paused)
- m_animation->pause();
- }
-
- initialized = true;
-}
-
-
-void QQuickParticleSystem::loadPainter(QObject *p)
-{
- if (!m_componentComplete)
- return;
-
- QQuickParticlePainter* painter = qobject_cast<QQuickParticlePainter*>(p);
- Q_ASSERT(painter);//XXX
- foreach (QQuickParticleGroupData* sg, groupData)
- sg->painters.remove(painter);
- int particleCount = 0;
- if (painter->groups().isEmpty()) {//Uses default particle
- QStringList def;
- def << QString();
- painter->setGroups(def);
- particleCount += groupData[0]->size();
- groupData[0]->painters << painter;
- } else {
- foreach (const QString &group, painter->groups()) {
- if (group != QLatin1String("") && !groupIds[group]) {//new group
- int id = m_nextGroupId++;
- QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
- groupIds.insert(group, id);
- groupData.insert(id, gd);
- }
- particleCount += groupData[groupIds[group]]->size();
- groupData[groupIds[group]]->painters << painter;
- }
- }
- painter->setCount(particleCount);
- painter->update();//Initial update here
- return;
-}
-
-void QQuickParticleSystem::emittersChanged()
-{
- if (!m_componentComplete)
- return;
-
- m_emitters.removeAll(0);
-
-
- QList<int> previousSizes;
- QList<int> newSizes;
- for (int i=0; i<m_nextGroupId; i++) {
- previousSizes << groupData[i]->size();
- newSizes << 0;
- }
-
- foreach (QQuickParticleEmitter* e, m_emitters) {//Populate groups and set sizes.
- if (!groupIds.contains(e->group())
- || (!e->group().isEmpty() && !groupIds[e->group()])) {//or it was accidentally inserted by a failed lookup earlier
- int id = m_nextGroupId++;
- QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
- groupIds.insert(e->group(), id);
- groupData.insert(id, gd);
- previousSizes << 0;
- newSizes << 0;
- }
- newSizes[groupIds[e->group()]] += e->particleCount();
- //###: Cull emptied groups?
- }
-
- //TODO: Garbage collection?
- particleCount = 0;
- for (int i=0; i<m_nextGroupId; i++) {
- groupData[i]->setSize(qMax(newSizes[i], previousSizes[i]));
- particleCount += groupData[i]->size();
- }
-
- if (m_debugMode)
- qDebug() << "Particle system emitters changed. New particle count: " << particleCount;
-
- if (particleCount > bySysIdx.size())//New datum requests haven't updated it
- bySysIdx.resize(particleCount);
-
- foreach (QQuickParticlePainter *p, m_painters)
- loadPainter(p);
-
- if (!m_groups.isEmpty())
- createEngine();
-
-}
-
-void QQuickParticleSystem::createEngine()
-{
- if (!m_componentComplete)
- return;
- if (stateEngine && m_debugMode)
- qDebug() << "Resetting Existing Sprite Engine...";
- //### Solve the losses if size/states go down
- foreach (QQuickParticleGroup* group, m_groups) {
- bool exists = false;
- foreach (const QString &name, groupIds.keys())
- if (group->name() == name)
- exists = true;
- if (!exists) {
- int id = m_nextGroupId++;
- QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
- groupIds.insert(group->name(), id);
- groupData.insert(id, gd);
- }
- }
-
- if (m_groups.count()) {
- //Reorder groups List so as to have the same order as groupData
- QList<QQuickParticleGroup*> newList;
- for (int i=0; i<m_nextGroupId; i++) {
- bool exists = false;
- QString name = groupData[i]->name();
- foreach (QQuickParticleGroup* existing, m_groups) {
- if (existing->name() == name) {
- newList << existing;
- exists = true;
- }
- }
- if (!exists) {
- newList << new QQuickParticleGroup(this);
- newList.back()->setName(name);
- }
- }
- m_groups = newList;
- QList<QQuickStochasticState*> states;
- foreach (QQuickParticleGroup* g, m_groups)
- states << (QQuickStochasticState*)g;
-
- if (!stateEngine)
- stateEngine = new QQuickStochasticEngine(this);
- stateEngine->setCount(particleCount);
- stateEngine->m_states = states;
-
- connect(stateEngine, SIGNAL(stateChanged(int)),
- this, SLOT(particleStateChange(int)));
-
- } else {
- if (stateEngine)
- delete stateEngine;
- stateEngine = 0;
- }
-
-}
-
-void QQuickParticleSystem::particleStateChange(int idx)
-{
- moveGroups(bySysIdx[idx], stateEngine->curState(idx));
-}
-
-void QQuickParticleSystem::moveGroups(QQuickParticleData *d, int newGIdx)
-{
- if (!d || newGIdx == d->group)
- return;
-
- QQuickParticleData* pd = newDatum(newGIdx, false, d->systemIndex);
- if (!pd)
- return;
-
- pd->clone(*d);
- finishNewDatum(pd);
-
- d->systemIndex = -1;
- groupData[d->group]->kill(d);
-}
-
-int QQuickParticleSystem::nextSystemIndex()
-{
- if (!m_reusableIndexes.isEmpty()) {
- int ret = *(m_reusableIndexes.begin());
- m_reusableIndexes.remove(ret);
- return ret;
- }
- if (m_nextIndex >= bySysIdx.size()) {
- bySysIdx.resize(bySysIdx.size() < 10 ? 10 : bySysIdx.size()*1.1);//###+1,10%,+10? Choose something non-arbitrarily
- if (stateEngine)
- stateEngine->setCount(bySysIdx.size());
-
- }
- return m_nextIndex++;
-}
-
-QQuickParticleData* QQuickParticleSystem::newDatum(int groupId, bool respectLimits, int sysIndex)
-{
- Q_ASSERT(groupId < groupData.count());//XXX shouldn't really be an assert
-
- QQuickParticleData* ret = groupData[groupId]->newDatum(respectLimits);
- if (!ret) {
- return 0;
- }
- if (sysIndex == -1) {
- if (ret->systemIndex == -1)
- ret->systemIndex = nextSystemIndex();
- } else {
- if (ret->systemIndex != -1) {
- if (stateEngine)
- stateEngine->stop(ret->systemIndex);
- m_reusableIndexes << ret->systemIndex;
- bySysIdx[ret->systemIndex] = 0;
- }
- ret->systemIndex = sysIndex;
- }
- bySysIdx[ret->systemIndex] = ret;
-
- if (stateEngine)
- stateEngine->start(ret->systemIndex, ret->group);
-
- m_empty = false;
- return ret;
-}
-
-void QQuickParticleSystem::emitParticle(QQuickParticleData* pd)
-{// called from prepareNextFrame()->emitWindow - enforce?
- //Account for relative emitter position
- QPointF offset = this->mapFromItem(pd->e, QPointF(0, 0));
- if (!offset.isNull()) {
- pd->x += offset.x();
- pd->y += offset.y();
- }
-
- finishNewDatum(pd);
-}
-
-void QQuickParticleSystem::finishNewDatum(QQuickParticleData *pd)
-{
- Q_ASSERT(pd);
- groupData[pd->group]->prepareRecycler(pd);
-
- foreach (QQuickParticleAffector *a, m_affectors)
- if (a && a->m_needsReset)
- a->reset(pd);
- foreach (QQuickParticlePainter* p, groupData[pd->group]->painters)
- if (p)
- p->load(pd);
-}
-
-void QQuickParticleSystem::updateCurrentTime( int currentTime )
-{
- if (!initialized)
- return;//error in initialization
-
- //### Elapsed time never shrinks - may cause problems if left emitting for weeks at a time.
- qreal dt = timeInt / 1000.;
- timeInt = currentTime;
- qreal time = timeInt / 1000.;
- dt = time - dt;
- needsReset.clear();
-
- m_emitters.removeAll(0);
- m_painters.removeAll(0);
- m_affectors.removeAll(0);
-
- bool oldClear = m_empty;
- m_empty = true;
- foreach (QQuickParticleGroupData* gd, groupData)//Recycle all groups and see if they're out of live particles
- m_empty = gd->recycle() && m_empty;
-
- if (stateEngine)
- stateEngine->updateSprites(timeInt);
-
- foreach (QQuickParticleEmitter* emitter, m_emitters)
- emitter->emitWindow(timeInt);
- foreach (QQuickParticleAffector* a, m_affectors)
- a->affectSystem(dt);
- foreach (QQuickParticleData* d, needsReset)
- foreach (QQuickParticlePainter* p, groupData[d->group]->painters)
- p->reload(d);
-
- if (oldClear != m_empty)
- emptyChanged(m_empty);
-}
-
-int QQuickParticleSystem::systemSync(QQuickParticlePainter* p)
-{
- if (!m_running)
- return 0;
- if (!initialized)
- return 0;//error in initialization
- p->performPendingCommits();
- return timeInt;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qquickparticlesystem_p.h b/src/declarative/particles/qquickparticlesystem_p.h
deleted file mode 100644
index 791770af11..0000000000
--- a/src/declarative/particles/qquickparticlesystem_p.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 PARTICLESYSTEM_H
-#define PARTICLESYSTEM_H
-
-#include <QQuickItem>
-#include <QElapsedTimer>
-#include <QVector>
-#include <QHash>
-#include <QPointer>
-#include <QSignalMapper>
-#include <private/qquicksprite_p.h>
-#include <QAbstractAnimation>
-#include <QtDeclarative/qdeclarative.h>
-#include <private/qv8engine_p.h> //For QDeclarativeV8Handle
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticleSystem;
-class QQuickParticleAffector;
-class QQuickParticleEmitter;
-class QQuickParticlePainter;
-class QQuickParticleData;
-class QQuickParticleSystemAnimation;
-class QQuickStochasticEngine;
-class QQuickSprite;
-class QQuickV8ParticleData;
-class QQuickParticleGroup;
-class QQuickImageParticle;
-
-struct QQuickParticleDataHeapNode{
- int time;//in ms
- QSet<QQuickParticleData*> data;//Set ptrs instead?
-};
-
-class QQuickParticleDataHeap {
- //Idea is to do a binary heap, but which also stores a set of int,Node* so that if the int already exists, you can
- //add it to the data* list. Pops return the whole list at once.
-public:
- QQuickParticleDataHeap();
- void insert(QQuickParticleData* data);
- void insertTimed(QQuickParticleData* data, int time);
-
- int top();
-
- QSet<QQuickParticleData*> pop();
-
- void clear();
-
- bool contains(QQuickParticleData*);//O(n), for debugging purposes only
-private:
- void grow();
- void swap(int, int);
- void bubbleUp(int);
- void bubbleDown(int);
- int m_size;
- int m_end;
- QQuickParticleDataHeapNode m_tmp;
- QVector<QQuickParticleDataHeapNode> m_data;
- QHash<int,int> m_lookups;
-};
-
-class Q_AUTOTEST_EXPORT QQuickParticleGroupData {
-public:
- QQuickParticleGroupData(int id, QQuickParticleSystem* sys);
- ~QQuickParticleGroupData();
-
- int size();
- QString name();
-
- void setSize(int newSize);
-
- int index;
- QSet<QQuickParticlePainter*> painters;//TODO: What if they are dynamically removed?
-
- //TODO: Refactor particle data list out into a separate class
- QVector<QQuickParticleData*> data;
- QQuickParticleDataHeap dataHeap;
- QSet<int> reusableIndexes;
- bool recycle(); //Force recycling round, returns true if all indexes are now reusable
-
- void initList();
- void kill(QQuickParticleData* d);
-
- //After calling this, initialize, then call prepareRecycler(d)
- QQuickParticleData* newDatum(bool respectsLimits);
-
- //TODO: Find and clean up those that don't get added to the recycler (currently they get lost)
- void prepareRecycler(QQuickParticleData* d);
-
-private:
- int m_size;
- QQuickParticleSystem* m_system;
-};
-
-struct Color4ub {
- uchar r;
- uchar g;
- uchar b;
- uchar a;
-};
-
-class Q_AUTOTEST_EXPORT QQuickParticleData {
-public:
- //TODO: QObject like memory management (without the cost, just attached to system)
- QQuickParticleData(QQuickParticleSystem* sys);
- ~QQuickParticleData();
-
- //Convenience functions for working backwards, because parameters are from the start of particle life
- //If setting multiple parameters at once, doing the conversion yourself will be faster.
-
- //sets the x accleration without affecting the instantaneous x velocity or position
- void setInstantaneousAX(qreal ax);
- //sets the x velocity without affecting the instantaneous x postion
- void setInstantaneousVX(qreal vx);
- //sets the instantaneous x postion
- void setInstantaneousX(qreal x);
- //sets the y accleration without affecting the instantaneous y velocity or position
- void setInstantaneousAY(qreal ay);
- //sets the y velocity without affecting the instantaneous y postion
- void setInstantaneousVY(qreal vy);
- //sets the instantaneous Y postion
- void setInstantaneousY(qreal y);
-
- //TODO: Slight caching?
- qreal curX() const;
- qreal curVX() const;
- qreal curAX() const { return ax; }
- qreal curY() const;
- qreal curVY() const;
- qreal curAY() const { return ay; }
-
- int group;
- QQuickParticleEmitter* e;//### Needed?
- QQuickParticleSystem* system;
- int index;
- int systemIndex;
-
- //General Position Stuff
- float x;
- float y;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float vx;
- float vy;
- float ax;
- float ay;
-
- //Other stuff, now universally shared
- Color4ub color;
- float xx;
- float xy;
- float yx;
- float yy;
- float rotation;
- float rotationSpeed;
- float autoRotate;//Assume that GPUs prefer floats to bools
- float animIdx;
- float frameDuration;
- float frameCount;
- float animT;
- float animX;
- float animY;
- float animWidth;
- float animHeight;
- float r;
- QQuickItem* delegate;
- int modelIndex;
- float update;//Used by custom affectors
-
- //Used by image particle
- QQuickImageParticle* colorOwner;
- QQuickImageParticle* rotationOwner;
- QQuickImageParticle* deformationOwner;
- QQuickImageParticle* animationOwner;
-
- void debugDump();
- bool stillAlive();//Only checks end, because usually that's all you need and it's a little faster.
- bool alive();
- float lifeLeft();
- float curSize();
- void clone(const QQuickParticleData& other);//Not =, leaves meta-data like index
- QDeclarativeV8Handle v8Value();
- void extendLife(float time);
-private:
- QQuickV8ParticleData* v8Datum;
-};
-
-class Q_AUTOTEST_EXPORT QQuickParticleSystem : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
- Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
-
-public:
- explicit QQuickParticleSystem(QQuickItem *parent = 0);
- ~QQuickParticleSystem();
-
- bool isRunning() const
- {
- return m_running;
- }
-
- int count(){ return particleCount; }
-
- static const int maxLife = 600000;
-
-signals:
-
- void systemInitialized();
- void runningChanged(bool arg);
- void pausedChanged(bool arg);
- void emptyChanged(bool arg);
-
-public slots:
- void start(){setRunning(true);}
- void stop(){setRunning(false);}
- void restart(){setRunning(false);setRunning(true);}
- void pause(){setPaused(true);}
- void resume(){setPaused(false);}
-
- void reset();
- void setRunning(bool arg);
- void setPaused(bool arg);
-
- virtual int duration() const { return -1; }
-
-
-protected:
- //This one only once per frame (effectively)
- void componentComplete();
-
-private slots:
- void emittersChanged();
- void loadPainter(QObject* p);
- void createEngine(); //Not invoked by sprite engine, unlike Sprite uses
- void particleStateChange(int idx);
-
-public:
- //These can be called multiple times per frame, performance critical
- void emitParticle(QQuickParticleData* p);
- QQuickParticleData* newDatum(int groupId, bool respectLimits = true, int sysIdx = -1);
- void finishNewDatum(QQuickParticleData*);
- void moveGroups(QQuickParticleData *d, int newGIdx);
- int nextSystemIndex();
-
- //This one only once per painter per frame
- int systemSync(QQuickParticlePainter* p);
-
- //Data members here for ease of related class and auto-test usage. Not "public" API. TODO: d_ptrize
- QSet<QQuickParticleData*> needsReset;
- QVector<QQuickParticleData*> bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
- QHash<QString, int> groupIds;
- QHash<int, QQuickParticleGroupData*> groupData;
- QQuickStochasticEngine* stateEngine;
-
- //Also only here for auto-test usage
- void updateCurrentTime( int currentTime );
- QQuickParticleSystemAnimation* m_animation;
- bool m_running;
-
- int timeInt;
- bool initialized;
- int particleCount;
-
- void registerParticlePainter(QQuickParticlePainter* p);
- void registerParticleEmitter(QQuickParticleEmitter* e);
- void registerParticleAffector(QQuickParticleAffector* a);
- void registerParticleGroup(QQuickParticleGroup* g);
-
- static void statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);
- static void stateRedirect(QQuickParticleGroup* group, QQuickParticleSystem* sys, QObject *value);
- bool isPaused() const
- {
- return m_paused;
- }
-
- bool isEmpty() const
- {
- return m_empty;
- }
-
-private:
- void initializeSystem();
- void initGroups();
- QList<QPointer<QQuickParticleEmitter> > m_emitters;
- QList<QPointer<QQuickParticleAffector> > m_affectors;
- QList<QPointer<QQuickParticlePainter> > m_painters;
- QList<QPointer<QQuickParticlePainter> > m_syncList;
- QList<QQuickParticleGroup*> m_groups;
- int m_nextGroupId;
- int m_nextIndex;
- QSet<int> m_reusableIndexes;
- bool m_componentComplete;
-
- QSignalMapper m_painterMapper;
- QSignalMapper m_emitterMapper;
- bool m_paused;
- bool m_debugMode;
- bool m_allDead;
- bool m_empty;
-};
-
-// Internally, this animation drives all the timing. Painters sync up in their updatePaintNode
-class QQuickParticleSystemAnimation : public QAbstractAnimation
-{
- Q_OBJECT
-public:
- QQuickParticleSystemAnimation(QQuickParticleSystem* system)
- : QAbstractAnimation(static_cast<QObject*>(system)), m_system(system)
- { }
-protected:
- virtual void updateCurrentTime( int t )
- {
- m_system->updateCurrentTime(t);
- }
-
- virtual int duration() const
- {
- return -1;
- }
-
-private:
- QQuickParticleSystem* m_system;
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // PARTICLESYSTEM_H
-
-
diff --git a/src/declarative/particles/qquickpointattractor_p.h b/src/declarative/particles/qquickpointattractor_p.h
deleted file mode 100644
index b488e132e3..0000000000
--- a/src/declarative/particles/qquickpointattractor_p.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 ATTRACTORAFFECTOR_H
-#define ATTRACTORAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickAttractorAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
- Q_PROPERTY(qreal pointX READ pointX WRITE setPointX NOTIFY pointXChanged)
- Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged)
- Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
- Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
- Q_ENUMS(AffectableParameters)
- Q_ENUMS(Proportion)
-
-public:
- enum Proportion{
- Constant,
- Linear,
- Quadratic,
- InverseLinear,
- InverseQuadratic
- };
-
- enum AffectableParameters {
- Position,
- Velocity,
- Acceleration
- };
-
- explicit QQuickAttractorAffector(QQuickItem *parent = 0);
-
- qreal strength() const
- {
- return m_strength;
- }
-
- qreal pointX() const
- {
- return m_x;
- }
-
- qreal pointY() const
- {
- return m_y;
- }
-
- AffectableParameters affectedParameter() const
- {
- return m_physics;
- }
-
- Proportion proportionalToDistance() const
- {
- return m_proportionalToDistance;
- }
-
-signals:
-
- void strengthChanged(qreal arg);
-
- void pointXChanged(qreal arg);
-
- void pointYChanged(qreal arg);
-
- void affectedParameterChanged(AffectableParameters arg);
-
- void proportionalToDistanceChanged(Proportion arg);
-
-public slots:
-void setStrength(qreal arg)
-{
- if (m_strength != arg) {
- m_strength = arg;
- emit strengthChanged(arg);
- }
-}
-
-void setPointX(qreal arg)
-{
- if (m_x != arg) {
- m_x = arg;
- emit pointXChanged(arg);
- }
-}
-
-void setPointY(qreal arg)
-{
- if (m_y != arg) {
- m_y = arg;
- emit pointYChanged(arg);
- }
-}
-void setAffectedParameter(AffectableParameters arg)
-{
- if (m_physics != arg) {
- m_physics = arg;
- emit affectedParameterChanged(arg);
- }
-}
-
-void setProportionalToDistance(Proportion arg)
-{
- if (m_proportionalToDistance != arg) {
- m_proportionalToDistance = arg;
- emit proportionalToDistanceChanged(arg);
- }
-}
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-private:
-qreal m_strength;
-qreal m_x;
-qreal m_y;
-AffectableParameters m_physics;
-Proportion m_proportionalToDistance;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // ATTRACTORAFFECTOR_H
diff --git a/src/declarative/particles/qquickpointdirection_p.h b/src/declarative/particles/qquickpointdirection_p.h
deleted file mode 100644
index 29ee7cb613..0000000000
--- a/src/declarative/particles/qquickpointdirection_p.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 POINTVECTOR_H
-#define POINTVECTOR_H
-#include "qquickdirection_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickPointDirection : public QQuickDirection
-{
- Q_OBJECT
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
- Q_PROPERTY(qreal xVariation READ xVariation WRITE setXVariation NOTIFY xVariationChanged)
- Q_PROPERTY(qreal yVariation READ yVariation WRITE setYVariation NOTIFY yVariationChanged)
-public:
- explicit QQuickPointDirection(QObject *parent = 0);
- virtual const QPointF sample(const QPointF &from);
- qreal x() const
- {
- return m_x;
- }
-
- qreal y() const
- {
- return m_y;
- }
-
- qreal xVariation() const
- {
- return m_xVariation;
- }
-
- qreal yVariation() const
- {
- return m_yVariation;
- }
-
-signals:
-
- void xChanged(qreal arg);
-
- void yChanged(qreal arg);
-
- void xVariationChanged(qreal arg);
-
- void yVariationChanged(qreal arg);
-
-public slots:
- void setX(qreal arg)
- {
- if (m_x != arg) {
- m_x = arg;
- emit xChanged(arg);
- }
- }
-
- void setY(qreal arg)
- {
- if (m_y != arg) {
- m_y = arg;
- emit yChanged(arg);
- }
- }
-
- void setXVariation(qreal arg)
- {
- if (m_xVariation != arg) {
- m_xVariation = arg;
- emit xVariationChanged(arg);
- }
- }
-
- void setYVariation(qreal arg)
- {
- if (m_yVariation != arg) {
- m_yVariation = arg;
- emit yVariationChanged(arg);
- }
- }
-
-private:
-
- qreal m_x;
- qreal m_y;
- qreal m_xVariation;
- qreal m_yVariation;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // POINTVECTOR_H
diff --git a/src/declarative/particles/qquickrectangleextruder_p.h b/src/declarative/particles/qquickrectangleextruder_p.h
deleted file mode 100644
index ec8caaeec1..0000000000
--- a/src/declarative/particles/qquickrectangleextruder_p.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 RECTANGLEEXTRUDER_H
-#define RECTANGLEEXTRUDER_H
-
-#include "qquickparticleextruder_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickRectangleExtruder : public QQuickParticleExtruder
-{
- Q_OBJECT
- Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)
-
-public:
- explicit QQuickRectangleExtruder(QObject *parent = 0);
- virtual QPointF extrude(const QRectF &);
- virtual bool contains(const QRectF &bounds, const QPointF &point);
- bool fill() const
- {
- return m_fill;
- }
-
-signals:
-
- void fillChanged(bool arg);
-
-public slots:
-
- void setFill(bool arg)
- {
- if (m_fill != arg) {
- m_fill = arg;
- emit fillChanged(arg);
- }
- }
-protected:
- bool m_fill;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // RectangleEXTRUDER_H
diff --git a/src/declarative/particles/qquickspritegoal_p.h b/src/declarative/particles/qquickspritegoal_p.h
deleted file mode 100644
index b979772a78..0000000000
--- a/src/declarative/particles/qquickspritegoal_p.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 SPRITEGOALAFFECTOR_H
-#define SPRITEGOALAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-#include <QtDeclarative/qdeclarativeinfo.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickStochasticEngine;
-
-class QQuickSpriteGoalAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
- Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
- Q_PROPERTY(bool systemStates READ systemStates WRITE setSystemStates NOTIFY systemStatesChanged)
-public:
- explicit QQuickSpriteGoalAffector(QQuickItem *parent = 0);
-
- QString goalState() const
- {
- return m_goalState;
- }
-
- bool jump() const
- {
- return m_jump;
- }
- bool systemStates() const
- {
- return m_systemStates;
- }
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-signals:
-
- void goalStateChanged(QString arg);
-
- void jumpChanged(bool arg);
-
- void systemStatesChanged(bool arg);
-
-public slots:
-
-void setGoalState(QString arg);
-
-void setJump(bool arg)
-{
- if (m_jump != arg) {
- m_jump = arg;
- emit jumpChanged(arg);
- }
-}
-
-void setSystemStates(bool arg)
-{
- if (m_systemStates != arg) {
- //TODO: GroupGoal was added (and this deprecated) Oct 4 - remove it in a few weeks.
- qmlInfo(this) << "systemStates is deprecated and will be removed soon. Use GroupGoal instead.";
- m_systemStates = arg;
- emit systemStatesChanged(arg);
- }
-}
-
-private:
- void updateStateIndex(QQuickStochasticEngine* e);
- QString m_goalState;
- int m_goalIdx;
- QQuickStochasticEngine* m_lastEngine;
- bool m_jump;
- bool m_systemStates;
-
- bool m_notUsingEngine;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // SPRITEGOALAFFECTOR_H
diff --git a/src/declarative/particles/qquicktargetdirection_p.h b/src/declarative/particles/qquicktargetdirection_p.h
deleted file mode 100644
index 2fc62b3ad8..0000000000
--- a/src/declarative/particles/qquicktargetdirection_p.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 DIRECTEDVECTOR_H
-#define DIRECTEDVECTOR_H
-#include "qquickdirection_p.h"
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickItem;
-class QQuickTargetDirection : public QQuickDirection
-{
- Q_OBJECT
- Q_PROPERTY(qreal targetX READ targetX WRITE setTargetX NOTIFY targetXChanged)
- Q_PROPERTY(qreal targetY READ targetY WRITE setTargetY NOTIFY targetYChanged)
- //If targetItem is set, X/Y are ignored. Aims at middle of item, use variation for variation
- Q_PROPERTY(QQuickItem* targetItem READ targetItem WRITE setTargetItem NOTIFY targetItemChanged)
-
- Q_PROPERTY(qreal targetVariation READ targetVariation WRITE setTargetVariation NOTIFY targetVariationChanged)
-
- //TODO: An enum would be better
- Q_PROPERTY(bool proportionalMagnitude READ proportionalMagnitude WRITE setProportionalMagnitude NOTIFY proprotionalMagnitudeChanged)
- Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
- Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
-
-public:
- explicit QQuickTargetDirection(QObject *parent = 0);
- virtual const QPointF sample(const QPointF &from);
-
- qreal targetX() const
- {
- return m_targetX;
- }
-
- qreal targetY() const
- {
- return m_targetY;
- }
-
- qreal targetVariation() const
- {
- return m_targetVariation;
- }
-
- qreal magnitude() const
- {
- return m_magnitude;
- }
-
- bool proportionalMagnitude() const
- {
- return m_proportionalMagnitude;
- }
-
- qreal magnitudeVariation() const
- {
- return m_magnitudeVariation;
- }
-
- QQuickItem* targetItem() const
- {
- return m_targetItem;
- }
-
-signals:
-
- void targetXChanged(qreal arg);
-
- void targetYChanged(qreal arg);
-
- void targetVariationChanged(qreal arg);
-
- void magnitudeChanged(qreal arg);
-
- void proprotionalMagnitudeChanged(bool arg);
-
- void magnitudeVariationChanged(qreal arg);
-
- void targetItemChanged(QQuickItem* arg);
-
-public slots:
- void setTargetX(qreal arg)
- {
- if (m_targetX != arg) {
- m_targetX = arg;
- emit targetXChanged(arg);
- }
- }
-
- void setTargetY(qreal arg)
- {
- if (m_targetY != arg) {
- m_targetY = arg;
- emit targetYChanged(arg);
- }
- }
-
- void setTargetVariation(qreal arg)
- {
- if (m_targetVariation != arg) {
- m_targetVariation = arg;
- emit targetVariationChanged(arg);
- }
- }
-
- void setMagnitude(qreal arg)
- {
- if (m_magnitude != arg) {
- m_magnitude = arg;
- emit magnitudeChanged(arg);
- }
- }
-
- void setProportionalMagnitude(bool arg)
- {
- if (m_proportionalMagnitude != arg) {
- m_proportionalMagnitude = arg;
- emit proprotionalMagnitudeChanged(arg);
- }
- }
-
- void setMagnitudeVariation(qreal arg)
- {
- if (m_magnitudeVariation != arg) {
- m_magnitudeVariation = arg;
- emit magnitudeVariationChanged(arg);
- }
- }
-
- void setTargetItem(QQuickItem* arg)
- {
- if (m_targetItem != arg) {
- m_targetItem = arg;
- emit targetItemChanged(arg);
- }
- }
-
-private:
- qreal m_targetX;
- qreal m_targetY;
- qreal m_targetVariation;
- bool m_proportionalMagnitude;
- qreal m_magnitude;
- qreal m_magnitudeVariation;
- QQuickItem *m_targetItem;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // DIRECTEDVECTOR_H
diff --git a/src/declarative/particles/qquicktrailemitter_p.h b/src/declarative/particles/qquicktrailemitter_p.h
deleted file mode 100644
index ad94d7107d..0000000000
--- a/src/declarative/particles/qquicktrailemitter_p.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 FOLLOWEMITTER_H
-#define FOLLOWEMITTER_H
-#include "qquickparticleemitter_p.h"
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickTrailEmitter : public QQuickParticleEmitter
-{
- Q_OBJECT
- Q_PROPERTY(QString follow READ follow WRITE setFollow NOTIFY followChanged)
- Q_PROPERTY(int emitRatePerParticle READ particlesPerParticlePerSecond WRITE setParticlesPerParticlePerSecond NOTIFY particlesPerParticlePerSecondChanged)
-
- Q_PROPERTY(QQuickParticleExtruder* emitShape READ emissonShape WRITE setEmissionShape NOTIFY emissionShapeChanged)
- Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
- Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
-
- Q_ENUMS(EmitSize)
-public:
- enum EmitSize {
- ParticleSize = -2//Anything less than 0 will do
- };
- explicit QQuickTrailEmitter(QQuickItem *parent = 0);
- virtual void emitWindow(int timeStamp);
- virtual void reset();
-
- int particlesPerParticlePerSecond() const
- {
- return m_particlesPerParticlePerSecond;
- }
-
- qreal emitterXVariation() const
- {
- return m_emitterXVariation;
- }
-
- qreal emitterYVariation() const
- {
- return m_emitterYVariation;
- }
-
- QString follow() const
- {
- return m_follow;
- }
-
- QQuickParticleExtruder* emissonShape() const
- {
- return m_emissionExtruder;
- }
-
-signals:
- void emitFollowParticles(QDeclarativeV8Handle particles, QDeclarativeV8Handle followed);
-
- void particlesPerParticlePerSecondChanged(int arg);
-
- void emitterXVariationChanged(qreal arg);
-
- void emitterYVariationChanged(qreal arg);
-
- void followChanged(QString arg);
-
- void emissionShapeChanged(QQuickParticleExtruder* arg);
-
-public slots:
-
- void setParticlesPerParticlePerSecond(int arg)
- {
- if (m_particlesPerParticlePerSecond != arg) {
- m_particlesPerParticlePerSecond = arg;
- emit particlesPerParticlePerSecondChanged(arg);
- }
- }
- void setEmitterXVariation(qreal arg)
- {
- if (m_emitterXVariation != arg) {
- m_emitterXVariation = arg;
- emit emitterXVariationChanged(arg);
- }
- }
-
- void setEmitterYVariation(qreal arg)
- {
- if (m_emitterYVariation != arg) {
- m_emitterYVariation = arg;
- emit emitterYVariationChanged(arg);
- }
- }
-
- void setFollow(QString arg)
- {
- if (m_follow != arg) {
- m_follow = arg;
- emit followChanged(arg);
- }
- }
-
- void setEmissionShape(QQuickParticleExtruder* arg)
- {
- if (m_emissionExtruder != arg) {
- m_emissionExtruder = arg;
- emit emissionShapeChanged(arg);
- }
- }
-
-private slots:
- void recalcParticlesPerSecond();
-
-private:
- QSet<QQuickParticleData*> m_pending;
- QVector<qreal> m_lastEmission;
- int m_particlesPerParticlePerSecond;
- qreal m_lastTimeStamp;
- qreal m_emitterXVariation;
- qreal m_emitterYVariation;
- QString m_follow;
- int m_followCount;
- QQuickParticleExtruder* m_emissionExtruder;
- QQuickParticleExtruder* m_defaultEmissionExtruder;
- bool isEmitFollowConnected();
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // FOLLOWEMITTER_H
diff --git a/src/declarative/particles/qquickturbulence_p.h b/src/declarative/particles/qquickturbulence_p.h
deleted file mode 100644
index dc72f40eff..0000000000
--- a/src/declarative/particles/qquickturbulence_p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 TURBULENCEAFFECTOR_H
-#define TURBULENCEAFFECTOR_H
-#include "qquickparticleaffector_p.h"
-#include <QDeclarativeListProperty>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QQuickParticlePainter;
-
-class QQuickTurbulenceAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
- Q_PROPERTY(QUrl noiseSource READ noiseSource WRITE setNoiseSource NOTIFY noiseSourceChanged)
- public:
- explicit QQuickTurbulenceAffector(QQuickItem *parent = 0);
- ~QQuickTurbulenceAffector();
- virtual void affectSystem(qreal dt);
-
- qreal strength() const
- {
- return m_strength;
- }
-
- QUrl noiseSource() const
- {
- return m_noiseSource;
- }
-signals:
-
- void strengthChanged(qreal arg);
-
- void noiseSourceChanged(QUrl arg);
-
-public slots:
-
- void setStrength(qreal arg)
- {
- if (m_strength != arg) {
- m_strength = arg;
- emit strengthChanged(arg);
- }
- }
-
- void setNoiseSource(QUrl arg)
- {
- if (m_noiseSource != arg) {
- m_noiseSource = arg;
- emit noiseSourceChanged(arg);
- initializeGrid();
- }
- }
-
-protected:
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
-private:
- void ensureInit();
- void mapUpdate();
- void initializeGrid();
- qreal boundsRespectingField(int x, int y);
- qreal m_strength;
- qreal m_lastT;
- int m_gridSize;
- qreal** m_field;
- QPointF** m_vectorField;
- bool m_inited;
- QUrl m_noiseSource;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // TURBULENCEAFFECTOR_H
diff --git a/src/declarative/particles/qquickv8particledata_p.h b/src/declarative/particles/qquickv8particledata_p.h
deleted file mode 100644
index 811974c132..0000000000
--- a/src/declarative/particles/qquickv8particledata_p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 QQuickV8PARTICLEDATA_H
-#define QQuickV8PARTICLEDATA_H
-
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QQuickParticleData;
-class QQuickV8ParticleData {
-public:
- QQuickV8ParticleData(QV8Engine*,QQuickParticleData*);
- ~QQuickV8ParticleData();
- QDeclarativeV8Handle v8Value();
-private:
- v8::Persistent<v8::Object> m_v8Value;
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-
-#endif
diff --git a/src/declarative/particles/qquickwander_p.h b/src/declarative/particles/qquickwander_p.h
deleted file mode 100644
index 99515fe629..0000000000
--- a/src/declarative/particles/qquickwander_p.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 WANDERAFFECTOR_H
-#define WANDERAFFECTOR_H
-#include <QHash>
-#include "qquickparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-struct WanderData{
- qreal x_vel;
- qreal y_vel;
- qreal x_peak;
- qreal x_var;
- qreal y_peak;
- qreal y_var;
-};
-
-class QQuickWanderAffector : public QQuickParticleAffector
-{
- Q_OBJECT
- Q_PROPERTY(qreal pace READ pace WRITE setPace NOTIFY paceChanged)
- Q_PROPERTY(qreal xVariance READ xVariance WRITE setXVariance NOTIFY xVarianceChanged)
- Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged)
- Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
- Q_ENUMS(AffectableParameters)
-
-public:
- enum AffectableParameters {
- Position,
- Velocity,
- Acceleration
- };
-
- explicit QQuickWanderAffector(QQuickItem *parent = 0);
- ~QQuickWanderAffector();
- virtual void reset(int systemIdx);
-
- qreal xVariance() const
- {
- return m_xVariance;
- }
-
- qreal yVariance() const
- {
- return m_yVariance;
- }
-
- qreal pace() const
- {
- return m_pace;
- }
-
- AffectableParameters affectedParameter() const
- {
- return m_affectedParameter;
- }
-
-protected:
- virtual bool affectParticle(QQuickParticleData *d, qreal dt);
-signals:
-
- void xVarianceChanged(qreal arg);
-
- void yVarianceChanged(qreal arg);
-
- void paceChanged(qreal arg);
-
-
- void affectedParameterChanged(AffectableParameters arg);
-
-public slots:
-void setXVariance(qreal arg)
-{
- if (m_xVariance != arg) {
- m_xVariance = arg;
- emit xVarianceChanged(arg);
- }
-}
-
-void setYVariance(qreal arg)
-{
- if (m_yVariance != arg) {
- m_yVariance = arg;
- emit yVarianceChanged(arg);
- }
-}
-
-void setPace(qreal arg)
-{
- if (m_pace != arg) {
- m_pace = arg;
- emit paceChanged(arg);
- }
-}
-
-
-void setAffectedParameter(AffectableParameters arg)
-{
- if (m_affectedParameter != arg) {
- m_affectedParameter = arg;
- emit affectedParameterChanged(arg);
- }
-}
-
-private:
- WanderData* getData(int idx);
- QHash<int, WanderData*> m_wanderData;
- qreal m_xVariance;
- qreal m_yVariance;
- qreal m_pace;
- AffectableParameters m_affectedParameter;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // WANDERAFFECTOR_H
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index ea68291942..49b3d037ad 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -78,7 +78,7 @@ class QDeclarativeEngine;
class QDeclarativeCompiledData;
class QDeclarativeComponentAttached;
-class Q_AUTOTEST_EXPORT QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback
{
Q_DECLARE_PUBLIC(QDeclarativeComponent)
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index d0d095567e..ee42f0b7c3 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -83,7 +83,6 @@
#include <private/qobject_p.h>
-#include <private/qtquick2_p.h>
#include <private/qdeclarativelocale_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
@@ -159,7 +158,6 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
\endcode
*/
-static bool qt_QmlQtModule_registered = false;
bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
@@ -343,10 +341,6 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
{
- if (!qt_QmlQtModule_registered) {
- qt_QmlQtModule_registered = true;
- QDeclarativeQtQuick2Module::defineModule();
- }
}
QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 7a2bda218f..7b53bab093 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -168,7 +168,7 @@ private:
class QDeclarativeExpression;
class QString;
-class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeJavaScriptExpression
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeJavaScriptExpression
{
Q_DECLARE_PUBLIC(QDeclarativeExpression)
public:
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index 46395e15e8..c175d725b8 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -1899,7 +1899,6 @@ int QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()
static int id = 0;
if (!id) {
id = QMetaType::type("QQuickAnchorLine");
- Q_ASSERT(id != 0);
}
return id;
}
diff --git a/src/declarative/qtquick2.cpp b/src/declarative/qtquick2.cpp
deleted file mode 100644
index ff49641865..0000000000
--- a/src/declarative/qtquick2.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qtquick2_p.h"
-#include <private/qdeclarativeengine_p.h>
-#include <private/qdeclarativeutilmodule_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include <private/qquickitemsmodule_p.h>
-#include <private/qquickparticlesmodule_p.h>
-#include <private/qquickwindowmodule_p.h>
-
-#include <private/qdeclarativeenginedebugservice_p.h>
-#include <private/qdeclarativedebugstatesdelegate_p.h>
-#include <private/qdeclarativebinding_p.h>
-#include <private/qdeclarativecontext_p.h>
-#include <private/qdeclarativepropertychanges_p.h>
-#include <private/qdeclarativestate_p.h>
-#include <qdeclarativeproperty.h>
-#include <QtCore/QWeakPointer>
-
-QT_BEGIN_NAMESPACE
-
-class QDeclarativeQtQuick2DebugStatesDelegate : public QDeclarativeDebugStatesDelegate
-{
-public:
- QDeclarativeQtQuick2DebugStatesDelegate();
- virtual ~QDeclarativeQtQuick2DebugStatesDelegate();
- virtual void buildStatesList(QDeclarativeContext *ctxt, bool cleanList);
- virtual void updateBinding(QDeclarativeContext *context,
- const QDeclarativeProperty &property,
- const QVariant &expression, bool isLiteralValue,
- const QString &fileName, int line,
- bool *isBaseState);
- virtual bool setBindingForInvalidProperty(QObject *object,
- const QString &propertyName,
- const QVariant &expression,
- bool isLiteralValue);
- virtual void resetBindingForInvalidProperty(QObject *object,
- const QString &propertyName);
-
-private:
- void buildStatesList(QObject *obj);
-
- QList<QWeakPointer<QDeclarativeState> > m_allStates;
-};
-
-QDeclarativeQtQuick2DebugStatesDelegate::QDeclarativeQtQuick2DebugStatesDelegate()
-{
-}
-
-QDeclarativeQtQuick2DebugStatesDelegate::~QDeclarativeQtQuick2DebugStatesDelegate()
-{
-}
-
-void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QDeclarativeContext *ctxt, bool cleanList)
-{
- if (cleanList)
- m_allStates.clear();
-
- QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
- for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
- buildStatesList(ctxtPriv->instances.at(ii));
- }
-
- QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts;
- while (child) {
- buildStatesList(child->asQDeclarativeContext());
- child = child->nextChild;
- }
-}
-
-void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QObject *obj)
-{
- if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
- m_allStates.append(state);
- }
-
- QObjectList children = obj->children();
- for (int ii = 0; ii < children.count(); ++ii) {
- buildStatesList(children.at(ii));
- }
-}
-
-void QDeclarativeQtQuick2DebugStatesDelegate::updateBinding(QDeclarativeContext *context,
- const QDeclarativeProperty &property,
- const QVariant &expression, bool isLiteralValue,
- const QString &fileName, int line,
- bool *inBaseState)
-{
- QObject *object = property.object();
- QString propertyName = property.name();
- foreach (QWeakPointer<QDeclarativeState> statePointer, m_allStates) {
- if (QDeclarativeState *state = statePointer.data()) {
- // here we assume that the revert list on itself defines the base state
- if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
- *inBaseState = false;
-
- QDeclarativeBinding *newBinding = 0;
- if (!isLiteralValue) {
- newBinding = new QDeclarativeBinding(expression.toString(), object, context);
- newBinding->setTarget(property);
- newBinding->setNotifyOnValueChanged(true);
- newBinding->setSourceLocation(fileName, line);
- }
-
- state->changeBindingInRevertList(object, propertyName, newBinding);
-
- if (isLiteralValue)
- state->changeValueInRevertList(object, propertyName, expression);
- }
- }
- }
-}
-
-bool QDeclarativeQtQuick2DebugStatesDelegate::setBindingForInvalidProperty(QObject *object,
- const QString &propertyName,
- const QVariant &expression,
- bool isLiteralValue)
-{
- if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
- if (isLiteralValue)
- propertyChanges->changeValue(propertyName, expression);
- else
- propertyChanges->changeExpression(propertyName, expression.toString());
- return true;
- } else {
- return false;
- }
-}
-
-void QDeclarativeQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *object, const QString &propertyName)
-{
- if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
- propertyChanges->removeProperty(propertyName);
- }
-}
-
-
-void QDeclarativeQtQuick2Module::defineModule()
-{
- QDeclarativeUtilModule::defineModule();
- QDeclarativeEnginePrivate::defineModule();
- QQuickItemsModule::defineModule();
- QQuickParticlesModule::defineModule();
- QQuickWindowModule::defineModule();
- QDeclarativeValueTypeFactory::registerValueTypes();
-
- if (QDeclarativeEngineDebugService::isDebuggingEnabled()) {
- QDeclarativeEngineDebugService::instance()->setStatesDelegate(
- new QDeclarativeQtQuick2DebugStatesDelegate);
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qtquick2_p.h b/src/declarative/qtquick2_p.h
deleted file mode 100644
index 7e2b334124..0000000000
--- a/src/declarative/qtquick2_p.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QTQUICK2_P_H
-#define QTQUICK2_P_H
-
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeQtQuick2Module
-{
-public:
- static void defineModule();
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QTQUICK2_P_H
diff --git a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h
deleted file mode 100644
index 45cebdd7b9..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QMLRENDERER_H
-#define QMLRENDERER_H
-
-#include "qsgrenderer_p.h"
-
-#include <QtGui/private/qdatabuffer_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-
-class QSGDefaultRenderer : public QSGRenderer
-{
- Q_OBJECT
-public:
- class IndexGeometryNodePair : public QPair<int, QSGGeometryNode *>
- {
- public:
- IndexGeometryNodePair(int i, QSGGeometryNode *n);
- bool operator < (const IndexGeometryNodePair &other) const;
- };
-
-
- // Minimum heap.
- class IndexGeometryNodePairHeap
- {
- public:
- IndexGeometryNodePairHeap();
- void insert(const IndexGeometryNodePair &x);
- const IndexGeometryNodePair &top() const { return v.first(); }
- IndexGeometryNodePair pop();
- bool isEmpty() const { return v.isEmpty(); }
- private:
- static int parent(int i) { return (i - 1) >> 1; }
- static int left(int i) { return (i << 1) | 1; }
- static int right(int i) { return (i + 1) << 1; }
- QDataBuffer<IndexGeometryNodePair> v;
- };
-
- QSGDefaultRenderer(QSGContext *context);
-
- void render();
-
- void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
-
- void setSortFrontToBackEnabled(bool sort);
- bool isSortFrontToBackEnabled() const;
-
-private:
- void buildLists(QSGNode *node);
- void renderNodes(const QDataBuffer<QSGGeometryNode *> &list);
-
- const QSGClipNode *m_currentClip;
- QSGMaterial *m_currentMaterial;
- QSGMaterialShader *m_currentProgram;
- const QMatrix4x4 *m_currentMatrix;
- QMatrix4x4 m_renderOrderMatrix;
- QDataBuffer<QSGGeometryNode *> m_opaqueNodes;
- QDataBuffer<QSGGeometryNode *> m_transparentNodes;
- QDataBuffer<QSGGeometryNode *> m_tempNodes;
- IndexGeometryNodePairHeap m_heap;
-
- bool m_rebuild_lists;
- bool m_needs_sorting;
- bool m_sort_front_to_back;
- int m_currentRenderOrder;
-
-#ifdef QML_RUNTIME_TESTING
- bool m_render_opaque_nodes;
- bool m_render_alpha_nodes;
-#endif
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QMLRENDERER_H
diff --git a/src/declarative/scenegraph/coreapi/qsggeometry.h b/src/declarative/scenegraph/coreapi/qsggeometry.h
deleted file mode 100644
index d7b343c108..0000000000
--- a/src/declarative/scenegraph/coreapi/qsggeometry.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt scene graph research project.
-**
-** $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 QSGGEOMETRY_H
-#define QSGGEOMETRY_H
-
-#include <QtGui/qopengl.h>
-#include <QRectF>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGGeometryData;
-
-class Q_DECLARATIVE_EXPORT QSGGeometry
-{
-public:
-
- struct Attribute
- {
- int position;
- int tupleSize;
- int type;
-
- uint isVertexCoordinate : 1;
- uint migrateYourCodeToUseTheCreateFunction: 31; // ### Remove before release
-
- static Attribute create(int pos, int tupleSize, int primitiveType, bool isPosition = false);
- };
-
- struct AttributeSet {
- int count;
- int stride;
- const Attribute *attributes;
- };
-
- struct Point2D {
- float x, y;
- void set(float nx, float ny) {
- x = nx; y = ny;
- }
- };
- struct TexturedPoint2D {
- float x, y;
- float tx, ty;
- void set(float nx, float ny, float ntx, float nty) {
- x = nx; y = ny; tx = ntx; ty = nty;
- }
- };
- struct ColoredPoint2D {
- float x, y;
- unsigned char r, g, b, a;
- void set(float nx, float ny, uchar nr, uchar ng, uchar nb, uchar na) {
- x = nx; y = ny;
- r = nr; g = ng, b = nb; a = na;
- }
- };
-
- static const AttributeSet &defaultAttributes_Point2D();
- static const AttributeSet &defaultAttributes_TexturedPoint2D();
- static const AttributeSet &defaultAttributes_ColoredPoint2D();
-
- enum DataPattern {
- AlwaysUploadPattern = 0,
- StreamPattern = 1,
- DynamicPattern = 2,
- StaticPattern = 3
- };
-
- QSGGeometry(const QSGGeometry::AttributeSet &attribs,
- int vertexCount,
- int indexCount = 0,
- int indexType = GL_UNSIGNED_SHORT);
- virtual ~QSGGeometry();
-
- void setDrawingMode(GLenum mode);
- inline GLenum drawingMode() const { return m_drawing_mode; }
-
- void allocate(int vertexCount, int indexCount = 0);
-
- int vertexCount() const { return m_vertex_count; }
-
- void *vertexData() { return m_data; }
- inline Point2D *vertexDataAsPoint2D();
- inline TexturedPoint2D *vertexDataAsTexturedPoint2D();
- inline ColoredPoint2D *vertexDataAsColoredPoint2D();
-
- inline const void *vertexData() const { return m_data; }
- inline const Point2D *vertexDataAsPoint2D() const;
- inline const TexturedPoint2D *vertexDataAsTexturedPoint2D() const;
- inline const ColoredPoint2D *vertexDataAsColoredPoint2D() const;
-
- inline int indexType() const { return m_index_type; }
-
- int indexCount() const { return m_index_count; }
-
- void *indexData();
- inline uint *indexDataAsUInt();
- inline quint16 *indexDataAsUShort();
-
- inline int sizeOfIndex() const;
-
- const void *indexData() const;
- inline const uint *indexDataAsUInt() const;
- inline const quint16 *indexDataAsUShort() const;
-
- inline int attributeCount() const { return m_attributes.count; }
- inline const Attribute *attributes() const { return m_attributes.attributes; }
- inline int sizeOfVertex() const { return m_attributes.stride; }
-
- static void updateRectGeometry(QSGGeometry *g, const QRectF &rect);
- static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect);
-
- void setIndexDataPattern(DataPattern p);
- DataPattern indexDataPattern() const { return (DataPattern) m_index_usage_pattern; }
-
- void setVertexDataPattern(DataPattern p);
- DataPattern vertexDataPattern() const { return (DataPattern) m_vertex_usage_pattern; }
-
- void markIndexDataDirty();
- void markVertexDataDirty();
-
-private:
- friend class QSGGeometryData;
-
- int m_drawing_mode;
- int m_vertex_count;
- int m_index_count;
- int m_index_type;
- const AttributeSet &m_attributes;
- void *m_data;
- int m_index_data_offset;
-
- QSGGeometryData *m_server_data;
-
- uint m_owns_data : 1;
- uint m_index_usage_pattern : 2;
- uint m_vertex_usage_pattern : 2;
- uint m_dirty_index_data : 1;
- uint m_dirty_vertex_data : 1;
- uint m_reserved_bits : 27;
-
- float m_prealloc[16];
-};
-
-inline uint *QSGGeometry::indexDataAsUInt()
-{
- Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
- return (uint *) indexData();
-}
-
-inline quint16 *QSGGeometry::indexDataAsUShort()
-{
- Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
- return (quint16 *) indexData();
-}
-
-inline const uint *QSGGeometry::indexDataAsUInt() const
-{
- Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
- return (uint *) indexData();
-}
-
-inline const quint16 *QSGGeometry::indexDataAsUShort() const
-{
- Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
- return (quint16 *) indexData();
-}
-
-inline QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D()
-{
- Q_ASSERT(m_attributes.count == 1);
- Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- return (Point2D *) m_data;
-}
-
-inline QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D()
-{
- Q_ASSERT(m_attributes.count == 2);
- Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[1].position == 1);
- Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
- return (TexturedPoint2D *) m_data;
-}
-
-inline QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D()
-{
- Q_ASSERT(m_attributes.count == 2);
- Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[1].position == 1);
- Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
- Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
- return (ColoredPoint2D *) m_data;
-}
-
-inline const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const
-{
- Q_ASSERT(m_attributes.count == 1);
- Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- return (const Point2D *) m_data;
-}
-
-inline const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() const
-{
- Q_ASSERT(m_attributes.count == 2);
- Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[1].position == 1);
- Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
- return (const TexturedPoint2D *) m_data;
-}
-
-inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() const
-{
- Q_ASSERT(m_attributes.count == 2);
- Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
- Q_ASSERT(m_attributes.attributes[0].position == 0);
- Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
- Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
- Q_ASSERT(m_attributes.attributes[1].position == 1);
- Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
- Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
- return (const ColoredPoint2D *) m_data;
-}
-
-int QSGGeometry::sizeOfIndex() const
-{
- if (m_index_type == GL_UNSIGNED_SHORT) return 2;
- else if (m_index_type == GL_UNSIGNED_BYTE) return 1;
- else if (m_index_type == GL_UNSIGNED_INT) return 4;
- return 0;
-}
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGGEOMETRY_H
diff --git a/src/declarative/scenegraph/coreapi/qsgmaterial.h b/src/declarative/scenegraph/coreapi/qsgmaterial.h
deleted file mode 100644
index 084219bfba..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgmaterial.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 MATERIAL_H
-#define MATERIAL_H
-
-#include <qopenglshaderprogram.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGMaterial;
-
-class Q_DECLARATIVE_EXPORT QSGMaterialShader
-{
-public:
- class Q_DECLARATIVE_EXPORT RenderState {
- public:
- enum DirtyState
- {
- DirtyMatrix = 0x0001,
- DirtyOpacity = 0x0002
- };
- Q_DECLARE_FLAGS(DirtyStates, DirtyState)
-
- inline DirtyStates dirtyStates() const { return m_dirty; }
-
- inline bool isMatrixDirty() const { return m_dirty & DirtyMatrix; }
- inline bool isOpacityDirty() const { return m_dirty & DirtyOpacity; }
-
- float opacity() const;
- QMatrix4x4 combinedMatrix() const;
- QMatrix4x4 modelViewMatrix() const;
- QRect viewportRect() const;
- QRect deviceRect() const;
-
- QOpenGLContext *context() const;
-
- private:
- friend class QSGRenderer;
- DirtyStates m_dirty;
- const void *m_data;
- };
-
- QSGMaterialShader();
-
- virtual void activate();
- virtual void deactivate();
- // First time a material is used, oldMaterial is null.
- virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
- virtual char const *const *attributeNames() const = 0; // Array must end with null.
-
- inline QOpenGLShaderProgram *program() { return &m_program; }
-
-protected:
-
- friend class QSGContext;
-
- virtual void compile();
- virtual void initialize() { }
-
- virtual const char *vertexShader() const = 0;
- virtual const char *fragmentShader() const = 0;
-
-private:
- QOpenGLShaderProgram m_program;
- void *m_reserved;
-};
-
-struct QSGMaterialType { };
-
-class Q_DECLARATIVE_EXPORT QSGMaterial
-{
-public:
- enum Flag {
- Blending = 0x0001
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QSGMaterial();
- virtual ~QSGMaterial();
-
- virtual QSGMaterialType *type() const = 0;
- virtual QSGMaterialShader *createShader() const = 0;
- virtual int compare(const QSGMaterial *other) const;
-
- QSGMaterial::Flags flags() const { return m_flags; }
- void setFlag(Flags flags, bool on = true);
-
-private:
- Flags m_flags;
- void *m_reserved;
- Q_DISABLE_COPY(QSGMaterial)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGMaterial::Flags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGMaterialShader::RenderState::DirtyStates)
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/coreapi/qsgnode.cpp b/src/declarative/scenegraph/coreapi/qsgnode.cpp
deleted file mode 100644
index 764071c190..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgnode.cpp
+++ /dev/null
@@ -1,1264 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgnode.h"
-#include "qsgrenderer_p.h"
-#include "qsgnodeupdater_p.h"
-#include "qsgmaterial.h"
-
-#include "limits.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_DEBUG
-static int qt_node_count = 0;
-
-static void qt_print_node_count()
-{
- qDebug("Number of leaked nodes: %i", qt_node_count);
- qt_node_count = -1;
-}
-#endif
-
-/*!
- \class QSGNode
- \brief The QSGNode class is the base class for all nodes in the scene graph.
-
- \inmodule QtDeclarative
-
- The QSGNode class can be used as a child container. Children are added with
- the appendChildNode(), prependChildNode(), insertChildNodeBefore() and
- insertChildNodeAfter(). Ordering of nodes is important as geometry nodes
- will be rendered in the order they are added to the scene graph.
- Actually, the scene may reorder nodes freely, but the resulting visual
- order is still guaranteed.
-
- If nodes change every frame, the preprocess() function can be used to
- apply changes to a node for every frame its rendered. The use of preprocess()
- must be explicitly enabled by setting the QSGNode::UsePreprocess flag
- on the node.
-
- The virtual isSubtreeBlocked() function can be used to disable a subtree all
- together. Nodes in a blocked subtree will not be preprocessed() and not
- rendered.
-
- Anything related to QSGNode should happen on the scene graph rendering thread.
- */
-
-QSGNode::QSGNode()
- : m_parent(0)
- , m_type(BasicNodeType)
- , m_firstChild(0)
- , m_lastChild(0)
- , m_nextSibling(0)
- , m_previousSibling(0)
- , m_subtreeGeometryCount(0)
- , m_nodeFlags(OwnedByParent)
- , m_flags(0)
-{
- init();
-}
-
-QSGNode::QSGNode(NodeType type)
- : m_parent(0)
- , m_type(type)
- , m_firstChild(0)
- , m_lastChild(0)
- , m_nextSibling(0)
- , m_previousSibling(0)
- , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
- , m_nodeFlags(OwnedByParent)
- , m_flags(0)
-{
- init();
-}
-
-void QSGNode::init()
-{
-#ifndef QT_NO_DEBUG
- ++qt_node_count;
- static bool atexit_registered = false;
- if (!atexit_registered) {
- atexit(qt_print_node_count);
- atexit_registered = true;
- }
-#endif
-}
-
-QSGNode::~QSGNode()
-{
-#ifndef QT_NO_DEBUG
- --qt_node_count;
- if (qt_node_count < 0)
- qDebug("Node destroyed after qt_print_node_count() was called.");
-#endif
- destroy();
-}
-
-
-/*!
- \fn void QSGNode::preprocess()
-
- Override this function to do processing on the node before it is rendered.
-
- Preprocessing needs to be explicitly enabled by setting the flag
- QSGNode::UsePreprocess. The flag needs to be set before the node is added
- to the scene graph and will cause the preprocess() function to be called
- for every frame the node is rendered.
-
- The preprocess function is called before the update pass that propegates
- opacity and transformations through the scene graph. That means that
- functions like QSGOpacityNode::combinedOpacity() and
- QSGTransformNode::combinedMatrix() will not contain up-to-date values.
- If such values are changed during the preprocess, these changes will be
- propegated through the scene graph before it is rendered.
-
- \warning Beware of deleting nodes while they are being preprocessed. It is
- possible, with a small performance hit, to delete a single node during its
- own preprocess call. Deleting a subtree which has nodes that also use
- preprocessing may result in a segmentation fault. This is done for
- performance reasons.
- */
-
-
-
-
-/*!
- Returns whether this node and its subtree is available for use.
-
- Blocked subtrees will not get their dirty states updated and they
- will not be rendered.
-
- The QSGOpacityNode will return a blocked subtree when accumulated opacity
- is 0, for instance.
- */
-
-bool QSGNode::isSubtreeBlocked() const
-{
- return m_subtreeGeometryCount == 0;
-}
-
-/*!
- \internal
- Detaches the node from the scene graph and deletes any children it owns.
-
- This function is called from QSGNode's and QSGRootNode's destructor. It
- should not be called explicitly in user code. QSGRootNode needs to call
- destroy() because destroy() calls removeChildNode() which in turn calls
- markDirty() which type-casts the node to QSGRootNode. This type-cast is not
- valid at the time QSGNode's destructor is called because the node will
- already be partially destroyed at that point.
-*/
-
-void QSGNode::destroy()
-{
- if (m_parent) {
- m_parent->removeChildNode(this);
- Q_ASSERT(m_parent == 0);
- }
- while (m_firstChild) {
- QSGNode *child = m_firstChild;
- removeChildNode(child);
- Q_ASSERT(child->m_parent == 0);
- if (child->flags() & OwnedByParent)
- delete child;
- }
-
- Q_ASSERT(m_firstChild == 0 && m_lastChild == 0);
-}
-
-
-/*!
- Prepends \a node to this node's the list of children.
-
- Ordering of nodes is important as geometry nodes will be rendered in the
- order they are added to the scene graph.
- */
-
-void QSGNode::prependChildNode(QSGNode *node)
-{
- //Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
- Q_ASSERT_X(!node->m_parent, "QSGNode::prependChildNode", "QSGNode already has a parent");
-
-#ifndef QT_NO_DEBUG
- if (node->type() == QSGNode::GeometryNodeType) {
- QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
- Q_ASSERT_X(g->material(), "QSGNode::prependChildNode", "QSGGeometryNode is missing material");
- Q_ASSERT_X(g->geometry(), "QSGNode::prependChildNode", "QSGGeometryNode is missing geometry");
- }
-#endif
-
- if (m_firstChild)
- m_firstChild->m_previousSibling = node;
- else
- m_lastChild = node;
- node->m_nextSibling = m_firstChild;
- m_firstChild = node;
- node->m_parent = this;
-
- node->markDirty(DirtyNodeAdded);
-}
-
-/*!
- Appends \a node to this node's list of children.
-
- Ordering of nodes is important as geometry nodes will be rendered in the
- order they are added to the scene graph.
- */
-
-void QSGNode::appendChildNode(QSGNode *node)
-{
- //Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
- Q_ASSERT_X(!node->m_parent, "QSGNode::appendChildNode", "QSGNode already has a parent");
-
-#ifndef QT_NO_DEBUG
- if (node->type() == QSGNode::GeometryNodeType) {
- QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
- Q_ASSERT_X(g->material(), "QSGNode::appendChildNode", "QSGGeometryNode is missing material");
- Q_ASSERT_X(g->geometry(), "QSGNode::appendChildNode", "QSGGeometryNode is missing geometry");
- }
-#endif
-
- if (m_lastChild)
- m_lastChild->m_nextSibling = node;
- else
- m_firstChild = node;
- node->m_previousSibling = m_lastChild;
- m_lastChild = node;
- node->m_parent = this;
-
- node->markDirty(DirtyNodeAdded);
-}
-
-
-
-/*!
- Inserts \a node to this node's list of children before the node specified with \a before.
-
- Ordering of nodes is important as geometry nodes will be rendered in the
- order they are added to the scene graph.
- */
-
-void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
-{
- //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
- Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeBefore", "QSGNode already has a parent");
- Q_ASSERT_X(before && before->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
-
-#ifndef QT_NO_DEBUG
- if (node->type() == QSGNode::GeometryNodeType) {
- QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
- Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing material");
- Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing geometry");
- }
-#endif
-
- QSGNode *previous = before->m_previousSibling;
- if (previous)
- previous->m_nextSibling = node;
- else
- m_firstChild = node;
- node->m_previousSibling = previous;
- node->m_nextSibling = before;
- before->m_previousSibling = node;
- node->m_parent = this;
-
- node->markDirty(DirtyNodeAdded);
-}
-
-
-
-/*!
- Inserts \a node to this node's list of children after the node specified with \a after.
-
- Ordering of nodes is important as geometry nodes will be rendered in the
- order they are added to the scene graph.
- */
-
-void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
-{
- //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
- Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent");
- Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
-
-#ifndef QT_NO_DEBUG
- if (node->type() == QSGNode::GeometryNodeType) {
- QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
- Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing material");
- Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing geometry");
- }
-#endif
-
- QSGNode *next = after->m_nextSibling;
- if (next)
- next->m_previousSibling = node;
- else
- m_lastChild = node;
- node->m_nextSibling = next;
- node->m_previousSibling = after;
- after->m_nextSibling = node;
- node->m_parent = this;
-
- node->markDirty(DirtyNodeAdded);
-}
-
-
-
-/*!
- Removes \a node from this node's list of children.
- */
-
-void QSGNode::removeChildNode(QSGNode *node)
-{
- //Q_ASSERT(m_children.contains(node));
- Q_ASSERT(node->parent() == this);
-
- QSGNode *previous = node->m_previousSibling;
- QSGNode *next = node->m_nextSibling;
- if (previous)
- previous->m_nextSibling = next;
- else
- m_firstChild = next;
- if (next)
- next->m_previousSibling = previous;
- else
- m_lastChild = previous;
- node->m_previousSibling = 0;
- node->m_nextSibling = 0;
-
- node->markDirty(DirtyNodeRemoved);
- node->m_parent = 0;
-}
-
-
-/*!
- Removes all child nodes from this node's list of children.
- */
-
-void QSGNode::removeAllChildNodes()
-{
- while (m_firstChild) {
- QSGNode *node = m_firstChild;
- m_firstChild = node->m_nextSibling;
- node->m_nextSibling = 0;
- if (m_firstChild)
- m_firstChild->m_previousSibling = 0;
- else
- m_lastChild = 0;
- node->markDirty(DirtyNodeRemoved);
- node->m_parent = 0;
- }
-}
-
-
-int QSGNode::childCount() const
-{
- int count = 0;
- QSGNode *n = m_firstChild;
- while (n) {
- ++count;
- n = n->m_nextSibling;
- }
- return count;
-}
-
-
-QSGNode *QSGNode::childAtIndex(int i) const
-{
- QSGNode *n = m_firstChild;
- while (i && n) {
- --i;
- n = n->m_nextSibling;
- }
- return n;
-}
-
-
-/*!
- Sets the flag \a f on this node if \a enabled is true;
- otherwise clears the flag.
-
- \sa flags()
-*/
-
-void QSGNode::setFlag(Flag f, bool enabled)
-{
- if (enabled)
- m_nodeFlags |= f;
- else
- m_nodeFlags &= ~f;
-}
-
-
-/*!
- Sets the flags \a f on this node if \a enabled is true;
- otherwise clears the flags.
-
- \sa flags()
-*/
-
-void QSGNode::setFlags(Flags f, bool enabled)
-{
- if (enabled)
- m_nodeFlags |= f;
- else
- m_nodeFlags &= ~f;
-}
-
-
-
-/*!
- Marks this node with the states in \a flags as dirty.
-
- When a node is marked dirty, it recursively mark the parent chain
- as dirty and notify all connected renderers that the has dirty states.
- */
-
-void QSGNode::markDirty(DirtyFlags flags)
-{
- m_flags |= (flags & DirtyPropagationMask);
-
- DirtyFlags subtreeFlags = DirtyFlags((flags & DirtyPropagationMask) << 16);
-
- int geometryCountDiff = 0;
- if (flags & DirtyNodeAdded)
- geometryCountDiff += m_subtreeGeometryCount;
- if (flags & DirtyNodeRemoved)
- geometryCountDiff -= m_subtreeGeometryCount;
-
- QSGNode *p = m_parent;
- while (p) {
- p->m_flags |= subtreeFlags;
- p->m_subtreeGeometryCount += geometryCountDiff;
- if (p->type() == RootNodeType)
- static_cast<QSGRootNode *>(p)->notifyNodeChange(this, flags);
- p = p->m_parent;
- }
-}
-
-
-
-/*!
- \class QSGBasicGeometryNode
- \brief The QSGBasicGeometryNode class serves as a baseclass for geometry based nodes
-
- \inmodule QtDeclarative
-
- The QSGBasicGeometryNode class should not be used by itself. It is only encapsulates
- shared functionality between the QSGGeometryNode and QSGClipNode classes.
- */
-
-
-/*!
- Creates a new basic geometry node.
- */
-QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
- : QSGNode(type)
- , m_geometry(0)
- , m_matrix(0)
- , m_clip_list(0)
-{
-}
-
-
-/*!
- Deletes this QSGBasicGeometryNode.
-
- If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
- geometry object it is pointing to. This flag is not set by default.
- */
-
-QSGBasicGeometryNode::~QSGBasicGeometryNode()
-{
- if (flags() & OwnsGeometry)
- delete m_geometry;
-}
-
-
-/*!
- \fn QSGGeometry *QSGBasicGeometryNode::geometry() const
-
- Returns this node's geometry.
-
- The geometry is null by default.
- */
-
-
-/*!
- Sets the geometry of this node to \a geometry.
-
- If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
- geometry object it is pointing to. This flag is not set by default.
- */
-
-void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
-{
- if (flags() & OwnsGeometry)
- delete m_geometry;
- m_geometry = geometry;
- markDirty(DirtyGeometry);
-}
-
-
-
-/*!
- \class QSGGeometryNode
- \brief The QSGGeometryNode class is used for all rendered content in the scene graph.
-
- \inmodule QtDeclarative
-
- The QSGGeometryNode consists of geometry and material. The geometry defines the mesh,
- the vertices and their structure, to be drawn. The Material defines how the shape is
- filled.
-
- A geometry node must have both geometry and a normal material before it is added to
- the scene graph.
-
- The geometry node supports two types of materials, the opaqueMaterial and the normal
- material. The opaqueMaterial is used when the accumulated scene graph opacity at the
- time of rendering is 1. The primary usecase is to special case opaque rendering
- to avoid an extra operation in the fragment shader can have significant performance
- impact on embedded graphics chips. The opaque material is optional.
-
- */
-
-
-/*!
- Creates a new geometry node without geometry and material.
- */
-
-QSGGeometryNode::QSGGeometryNode()
- : QSGBasicGeometryNode(GeometryNodeType)
- , m_render_order(0)
- , m_material(0)
- , m_opaque_material(0)
- , m_opacity(1)
-{
-}
-
-
-/*!
- Deletes this geometry node.
-
- The flags QSGNode::OwnsMaterial, QSGNode::OwnsOpaqueMaterial and
- QSGNode::OwnsGeometry decides weither the geometry node should also
- delete the materials and geometry. By default, these flags are disabled.
- */
-
-QSGGeometryNode::~QSGGeometryNode()
-{
- if (flags() & OwnsMaterial)
- delete m_material;
- if (flags() & OwnsOpaqueMaterial)
- delete m_opaque_material;
-}
-
-
-
-/*!
- \fn int QSGGeometryNode::renderOrder() const
-
- Returns the render order of this geometry node.
-
- \internal
- */
-
-
-/*!
- Sets the render order of this node to be \a order.
-
- GeometryNodes are rendered in an order that visually looks like
- low order nodes are rendered prior to high order nodes. For opaque
- geometry there is little difference as z-testing will handle
- the discard, but for translucent objects, the rendering should
- normally be specified in the order of back-to-front.
-
- The default render order is 0.
-
- \internal
- */
-void QSGGeometryNode::setRenderOrder(int order)
-{
- m_render_order = order;
-}
-
-
-
-/*!
- Sets the material of this geometry node to \a material.
-
- Geometry nodes must have a material before they can be added to the
- scene graph.
- */
-void QSGGeometryNode::setMaterial(QSGMaterial *material)
-{
- if (flags() & OwnsMaterial)
- delete m_material;
- m_material = material;
-#ifndef QT_NO_DEBUG
- if (m_material != 0 && m_opaque_material == m_material)
- qWarning("QSGGeometryNode: using same material for both opaque and translucent");
-#endif
- markDirty(DirtyMaterial);
-}
-
-
-
-/*!
- Sets the opaque material of this geometry to \a material.
-
- The opaque material will be preferred by the renderer over the
- default material, as returned by the material() function, if
- it is not null and the geometry item has an inherited opacity of
- 1.
-
- The opaqueness refers to scene graph opacity, the material is still
- allowed to set QSGMaterial::Blending to true and draw transparent
- pixels.
- */
-void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
-{
- if (flags() & OwnsOpaqueMaterial)
- delete m_opaque_material;
- m_opaque_material = material;
-#ifndef QT_NO_DEBUG
- if (m_opaque_material != 0 && m_opaque_material == m_material)
- qWarning("QSGGeometryNode: using same material for both opaque and translucent");
-#endif
-
- markDirty(DirtyMaterial);
-}
-
-
-
-/*!
- Returns the material which should currently be used for geometry node.
-
- If the inherited opacity of the node is 1 and there is an opaque material
- set on this node, it will be returned; otherwise, the default material
- will be returned.
-
- \warning This function requires the scene graph above this item to be
- completely free of dirty states, so it can only be called during rendering
-
- \internal
-
- \sa setMaterial, setOpaqueMaterial
- */
-QSGMaterial *QSGGeometryNode::activeMaterial() const
-{
- Q_ASSERT_X(dirtyFlags() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up");
- if (m_opaque_material && m_opacity > 0.999)
- return m_opaque_material;
- return m_material;
-}
-
-
-/*!
- Sets the inherited opacity of this geometry to \a opacity.
-
- This function is meant to be called by the node preprocessing
- prior to rendering the tree, so it will not mark the tree as
- dirty.
-
- \internal
- */
-void QSGGeometryNode::setInheritedOpacity(qreal opacity)
-{
- Q_ASSERT(opacity >= 0 && opacity <= 1);
- m_opacity = opacity;
-}
-
-
-/*!
- \class QSGClipNode
- \brief The QSGClipNode class implements the clipping functionality in the scene graph.
-
- \inmodule QtDeclarative
-
- Clipping applies to the node's subtree and can be nested. Multiple clip nodes will be
- accumulated by intersecting all their geometries. The accumulation happens
- as part of the rendering.
-
- Clip nodes must have a geometry before they can be added to the scene graph.
-
- Clipping is usually implemented by using the stencil buffer.
- */
-
-
-
-/*!
- Creates a new QSGClipNode without a geometry.
-
- The clip node must have a geometry before it can be added to the
- scene graph.
- */
-
-QSGClipNode::QSGClipNode()
- : QSGBasicGeometryNode(ClipNodeType)
-{
-}
-
-
-
-/*!
- Deletes this QSGClipNode.
-
- If the flag QSGNode::OwnsGeometry is set, the geometry will also be
- deleted.
- */
-
-QSGClipNode::~QSGClipNode()
-{
-}
-
-
-
-/*!
- \fn bool QSGClipNode::isRectangular() const
-
- Returns if this clip node has a rectangular clip.
- */
-
-
-
-/*!
- Sets whether this clip node has a rectangular clip to \a rectHint.
-
- This is an optimization hint which means that the renderer can
- use scissoring instead of stencil, which is significnatly faster.
-
- When this hint is and it is applicable, the clip region will be
- generated from clipRect() rather than geometry().
- */
-
-void QSGClipNode::setIsRectangular(bool rectHint)
-{
- m_is_rectangular = rectHint;
-}
-
-
-
-/*!
- \fn void QSGClipNode::clipRect() const
-
- Returns the clip rect of this node.
- */
-
-
-/*!
- Sets the clip rect of this clip node to \a rect.
-
- When a rectangular clip is set in combination with setIsRectangular
- the renderer may in some cases use a more optimal clip method.
- */
-void QSGClipNode::setClipRect(const QRectF &rect)
-{
- m_clip_rect = rect;
-}
-
-
-/*!
- \class QSGTransformNode
- \brief The QSGTransformNode class implements transformations in the scene graph
-
- \inmodule QtDeclarative
-
- Transformations apply the node's subtree and can be nested. Multiple transform nodes
- will be accumulated by intersecting all their matrices. The accumulation happens
- as part of the rendering.
-
- The transform nodes implement a 4x4 matrix which in theory supports full 3D
- transformations. However, because the renderer optimizes for 2D use-cases rather
- than 3D use-cases, rendering a scene with full 3D transformations needs to
- be done with some care.
- */
-
-QSGTransformNode::QSGTransformNode()
- : QSGNode(TransformNodeType)
-{
-}
-
-
-
-/*!
- Deletes this transform node.
- */
-
-QSGTransformNode::~QSGTransformNode()
-{
-}
-
-
-
-/*!
- \fn QMatrix4x4 QSGTransformNode::matrix() const
-
- Returns this transform node's matrix.
- */
-
-
-
-/*!
- Sets this transform node's matrix to \a matrix.
- */
-
-void QSGTransformNode::setMatrix(const QMatrix4x4 &matrix)
-{
- m_matrix = matrix;
- markDirty(DirtyMatrix);
-}
-
-
-/*!
- Sets the combined matrix of this matrix to \a transform.
-
- This function is meant to be called by the node preprocessing
- prior to rendering the tree, so it will not mark the tree as
- dirty.
-
- \internal
- */
-void QSGTransformNode::setCombinedMatrix(const QMatrix4x4 &matrix)
-{
- m_combined_matrix = matrix;
-}
-
-
-
-/*!
- \class QSGRootNode
- \brief The QSGRootNode is the toplevel root of any scene graph.
-
- The root node is used to attach a scene graph to a renderer.
-
- \internal
- */
-
-
-
-/*!
- \fn QSGRootNode::QSGRootNode()
-
- Creates a new root node.
- */
-
-QSGRootNode::QSGRootNode()
- : QSGNode(RootNodeType)
-{
-}
-
-
-/*!
- Deletes the root node.
-
- When a root node is deleted it removes itself from all of renderers
- that are referencing it.
- */
-
-QSGRootNode::~QSGRootNode()
-{
- while (!m_renderers.isEmpty())
- m_renderers.last()->setRootNode(0);
- destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode.
-}
-
-
-
-/*!
- Called to notify all renderers that \a node has been marked as dirty
- with \a flags.
- */
-
-void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyFlags flags)
-{
- for (int i=0; i<m_renderers.size(); ++i) {
- m_renderers.at(i)->nodeChanged(node, flags);
- }
-}
-
-
-
-/*!
- \class QSGOpacityNode
- \brief The QSGOpacityNode class is used to change opacity of nodes.
-
- \inmodule QtDeclarative
-
- Opacity applies to its subtree and can be nested. Multiple opacity nodes
- will be accumulated by multiplying their opacity. The accumulation happens
- as part of the rendering.
-
- When nested opacity gets below a certain threshold, the subtree might
- be marked as blocked, causing isSubtreeBlocked() to return true. This
- is done for performance reasons.
-
- */
-
-
-
-/*!
- Constructs an opacity node with a default opacity of 1.
-
- Opacity accumulates downwards in the scene graph so a node with two
- QSGOpacityNode instances above it, both with opacity of 0.5, will have
- effective opacity of 0.25.
-
- The default opacity of nodes is 1.
- */
-QSGOpacityNode::QSGOpacityNode()
- : QSGNode(OpacityNodeType)
- , m_opacity(1)
- , m_combined_opacity(1)
-{
-}
-
-
-
-/*!
- Deletes the opacity node.
- */
-
-QSGOpacityNode::~QSGOpacityNode()
-{
-}
-
-
-
-/*!
- \fn qreal QSGOpacityNode::opacity() const
-
- Returns this opacity node's opacity.
- */
-
-
-
-/*!
- Sets the opacity of this node to \a opacity.
-
- Before rendering the graph, the renderer will do an update pass
- over the subtree to propegate the opacity to its children.
-
- The value will be bounded to the range 0 to 1.
- */
-
-void QSGOpacityNode::setOpacity(qreal opacity)
-{
- opacity = qBound<qreal>(0, opacity, 1);
- if (m_opacity == opacity)
- return;
- m_opacity = opacity;
- markDirty(DirtyOpacity);
-}
-
-
-
-/*!
- \fn qreal QSGOpacityNode::combinedOpacity() const
-
- Returns this node's accumulated opacity.
-
- This vaule is calculated during rendering and only stored
- in the opacity node temporarily.
-
- \internal
- */
-
-
-
-/*!
- Sets the combined opacity of this node to \a opacity.
-
- This function is meant to be called by the node preprocessing
- prior to rendering the tree, so it will not mark the tree as
- dirty.
-
- \internal
- */
-
-void QSGOpacityNode::setCombinedOpacity(qreal opacity)
-{
- m_combined_opacity = opacity;
-}
-
-
-
-/*!
- For performance reasons, we block the subtree when the opacity
- is below a certain threshold.
-
- \internal
- */
-
-bool QSGOpacityNode::isSubtreeBlocked() const
-{
- return QSGNode::isSubtreeBlocked() || m_opacity < 0.001;
-}
-
-
-/*!
- \class QSGNodeVisitor
- \brief The QSGNodeVisitor class is a helper class for traversing the scene graph.
-
- \internal
- */
-
-QSGNodeVisitor::~QSGNodeVisitor()
-{
-
-}
-
-
-void QSGNodeVisitor::visitNode(QSGNode *n)
-{
- switch (n->type()) {
- case QSGNode::TransformNodeType: {
- QSGTransformNode *t = static_cast<QSGTransformNode *>(n);
- enterTransformNode(t);
- visitChildren(t);
- leaveTransformNode(t);
- break; }
- case QSGNode::GeometryNodeType: {
- QSGGeometryNode *g = static_cast<QSGGeometryNode *>(n);
- enterGeometryNode(g);
- visitChildren(g);
- leaveGeometryNode(g);
- break; }
- case QSGNode::ClipNodeType: {
- QSGClipNode *c = static_cast<QSGClipNode *>(n);
- enterClipNode(c);
- visitChildren(c);
- leaveClipNode(c);
- break; }
- case QSGNode::OpacityNodeType: {
- QSGOpacityNode *o = static_cast<QSGOpacityNode *>(n);
- enterOpacityNode(o);
- visitChildren(o);
- leaveOpacityNode(o);
- break; }
- default:
- visitChildren(n);
- break;
- }
-}
-
-void QSGNodeVisitor::visitChildren(QSGNode *n)
-{
- for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
- visitNode(c);
-}
-
-
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QSGGeometryNode *n)
-{
- if (!n) {
- d << "QSGGeometryNode(null)";
- return d;
- }
- d << "QSGGeometryNode(" << hex << (void *) n << dec;
-
- const QSGGeometry *g = n->geometry();
-
- if (!g) {
- d << "no geometry";
- } else {
-
- switch (g->drawingMode()) {
- case GL_TRIANGLE_STRIP: d << "strip"; break;
- case GL_TRIANGLE_FAN: d << "fan"; break;
- case GL_TRIANGLES: d << "triangles"; break;
- default: break;
- }
-
- d << g->vertexCount();
-
- if (g->attributeCount() > 0 && g->attributes()->type == GL_FLOAT) {
- float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
- int stride = g->sizeOfVertex();
- for (int i = 0; i < g->vertexCount(); ++i) {
- float x = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
- float y = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
-
- x1 = qMin(x1, x);
- x2 = qMax(x2, x);
- y1 = qMin(y1, y);
- y2 = qMax(y2, y);
- }
-
- d << "x1=" << x1 << "y1=" << y1 << "x2=" << x2 << "y2=" << y2;
- }
- }
-
- d << "order=" << n->renderOrder();
- if (n->material())
- d << "effect=" << n->material() << "type=" << n->material()->type();
-
-
- d << ")";
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
- return d;
-}
-
-QDebug operator<<(QDebug d, const QSGClipNode *n)
-{
- if (!n) {
- d << "QSGClipNode(null)";
- return d;
- }
- d << "QSGClipNode(" << hex << (void *) n << dec;
-
- if (n->childCount())
- d << "children=" << n->childCount();
-
- d << "is rect?" << (n->isRectangular() ? "yes" : "no");
-
- d << ")";
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
- return d;
-}
-
-QDebug operator<<(QDebug d, const QSGTransformNode *n)
-{
- if (!n) {
- d << "QSGTransformNode(null)";
- return d;
- }
- const QMatrix4x4 m = n->matrix();
- d << "QSGTransformNode(";
- d << hex << (void *) n << dec;
- if (m.isIdentity())
- d << "identity";
- else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
- d << "translate" << m(0, 3) << m(1, 3) << m(2, 3);
- else
- d << "det=" << n->matrix().determinant();
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
- d << ")";
- return d;
-}
-
-QDebug operator<<(QDebug d, const QSGOpacityNode *n)
-{
- if (!n) {
- d << "QSGOpacityNode(null)";
- return d;
- }
- d << "QSGOpacityNode(";
- d << hex << (void *) n << dec;
- d << "opacity=" << n->opacity()
- << "combined=" << n->combinedOpacity()
- << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
- d << ")";
- return d;
-}
-
-
-QDebug operator<<(QDebug d, const QSGRootNode *n)
-{
- if (!n) {
- d << "QSGRootNode(null)";
- return d;
- }
- d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyFlags() << dec
- << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << ")";
- return d;
-}
-
-
-
-QDebug operator<<(QDebug d, const QSGNode *n)
-{
- if (!n) {
- d << "QSGNode(null)";
- return d;
- }
- switch (n->type()) {
- case QSGNode::GeometryNodeType:
- d << static_cast<const QSGGeometryNode *>(n);
- break;
- case QSGNode::TransformNodeType:
- d << static_cast<const QSGTransformNode *>(n);
- break;
- case QSGNode::ClipNodeType:
- d << static_cast<const QSGClipNode *>(n);
- break;
- case QSGNode::RootNodeType:
- d << static_cast<const QSGRootNode *>(n);
- break;
- case QSGNode::OpacityNodeType:
- d << static_cast<const QSGOpacityNode *>(n);
- break;
- default:
- d << "QSGNode(" << hex << (void *) n << dec
- << "dirty=" << hex << (int) n->dirtyFlags()
- << "flags=" << (int) n->flags() << dec
- << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
-#ifdef QML_RUNTIME_TESTING
- d << n->description;
-#endif
- d << ")";
- break;
- }
- return d;
-}
-
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/coreapi/qsgnode.h b/src/declarative/scenegraph/coreapi/qsgnode.h
deleted file mode 100644
index 58afff4bc7..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgnode.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 NODE_H
-#define NODE_H
-
-#include "qsggeometry.h"
-#include <QtGui/QMatrix4x4>
-
-#include <float.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-#define QML_RUNTIME_TESTING
-
-class QSGRenderer;
-
-class QSGNode;
-class QSGRootNode;
-class QSGGeometryNode;
-class QSGTransformNode;
-class QSGClipNode;
-
-class Q_DECLARATIVE_EXPORT QSGNode
-{
-public:
- enum NodeType {
- BasicNodeType,
- RootNodeType,
- GeometryNodeType,
- TransformNodeType,
- ClipNodeType,
- OpacityNodeType,
- UserNodeType = 1024
- };
-
- enum DirtyFlag {
- DirtyMatrix = 0x0001,
- DirtyClipList = 0x0002,
- DirtyNodeAdded = 0x0004,
- DirtyNodeRemoved = 0x0008,
- DirtyGeometry = 0x0010,
- DirtyMaterial = 0x0040,
- DirtyOpacity = 0x0080,
- DirtyForceUpdate = 0x0100,
-
- DirtyPropagationMask = DirtyMatrix
- | DirtyClipList
- | DirtyNodeAdded
- | DirtyOpacity
- | DirtyForceUpdate
-
- };
- Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
-
- enum Flag {
- // Lower 16 bites reserved for general node
- OwnedByParent = 0x0001,
- UsePreprocess = 0x0002,
- ChildrenDoNotOverlap = 0x0004,
-
- // Upper 16 bits reserved for node subclasses
-
- // QSGBasicGeometryNode
- OwnsGeometry = 0x00010000,
- OwnsMaterial = 0x00020000,
- OwnsOpaqueMaterial = 0x00040000
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QSGNode();
- virtual ~QSGNode();
-
- QSGNode *parent() const { return m_parent; }
-
- void removeChildNode(QSGNode *node);
- void removeAllChildNodes();
- void prependChildNode(QSGNode *node);
- void appendChildNode(QSGNode *node);
- void insertChildNodeBefore(QSGNode *node, QSGNode *before);
- void insertChildNodeAfter(QSGNode *node, QSGNode *after);
-
- int childCount() const;
- QSGNode *childAtIndex(int i) const;
- QSGNode *firstChild() const { return m_firstChild; }
- QSGNode *lastChild() const { return m_lastChild; }
- QSGNode *nextSibling() const { return m_nextSibling; }
- QSGNode* previousSibling() const { return m_previousSibling; }
-
- inline NodeType type() const { return m_type; }
-
- void clearDirty() { m_flags = 0; }
- void markDirty(DirtyFlags flags);
- DirtyFlags dirtyFlags() const { return m_flags; }
-
- virtual bool isSubtreeBlocked() const;
-
- Flags flags() const { return m_nodeFlags; }
- void setFlag(Flag, bool = true);
- void setFlags(Flags, bool = true);
-
- virtual void preprocess() { }
-
-#ifdef QML_RUNTIME_TESTING
- QString description;
-#endif
-
-protected:
- QSGNode(NodeType type);
-
-private:
- friend class QSGRootNode;
-
- void init();
- void destroy();
-
- QSGNode *m_parent;
- NodeType m_type;
- QSGNode *m_firstChild;
- QSGNode *m_lastChild;
- QSGNode *m_nextSibling;
- QSGNode *m_previousSibling;
- int m_subtreeGeometryCount;
-
- Flags m_nodeFlags;
- DirtyFlags m_flags;
-
- void *m_reserved;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::Flags)
-
-class Q_DECLARATIVE_EXPORT QSGBasicGeometryNode : public QSGNode
-{
-public:
-// enum UsagePattern {
-// Static,
-// Dynamic,
-// Stream
-// };
-// void setUsagePattern(UsagePattern pattern);
-// UsagePattern usagePattern() const { return m_pattern; }
-
- ~QSGBasicGeometryNode();
-
- void setGeometry(QSGGeometry *geometry);
- const QSGGeometry *geometry() const { return m_geometry; }
- QSGGeometry *geometry() { return m_geometry; }
-
- const QMatrix4x4 *matrix() const { return m_matrix; }
- const QSGClipNode *clipList() const { return m_clip_list; }
-
-protected:
- QSGBasicGeometryNode(NodeType type);
-
-private:
- friend class QSGNodeUpdater;
- QSGGeometry *m_geometry;
-
- int m_reserved_start_index;
- int m_reserved_end_index;
-
- const QMatrix4x4 *m_matrix;
- const QSGClipNode *m_clip_list;
-
-// UsagePattern m_pattern;
-};
-
-class QSGMaterial;
-
-class Q_DECLARATIVE_EXPORT QSGGeometryNode : public QSGBasicGeometryNode
-{
-public:
- QSGGeometryNode();
- ~QSGGeometryNode();
-
- void setMaterial(QSGMaterial *material);
- QSGMaterial *material() const { return m_material; }
-
- void setOpaqueMaterial(QSGMaterial *material);
- QSGMaterial *opaqueMaterial() const { return m_opaque_material; }
-
- QSGMaterial *activeMaterial() const;
-
- void setRenderOrder(int order);
- int renderOrder() const { return m_render_order; }
-
- void setInheritedOpacity(qreal opacity);
- qreal inheritedOpacity() const { return m_opacity; }
-
-private:
- friend class QSGNodeUpdater;
-
- int m_render_order;
- QSGMaterial *m_material;
- QSGMaterial *m_opaque_material;
-
- qreal m_opacity;
-};
-
-class Q_DECLARATIVE_EXPORT QSGClipNode : public QSGBasicGeometryNode
-{
-public:
- QSGClipNode();
- ~QSGClipNode();
-
- void setIsRectangular(bool rectHint);
- bool isRectangular() const { return m_is_rectangular; }
-
- void setClipRect(const QRectF &);
- QRectF clipRect() const { return m_clip_rect; }
-
-private:
- uint m_is_rectangular : 1;
- uint m_reserved : 31;
-
- QRectF m_clip_rect;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGTransformNode : public QSGNode
-{
-public:
- QSGTransformNode();
- ~QSGTransformNode();
-
- void setMatrix(const QMatrix4x4 &matrix);
- const QMatrix4x4 &matrix() const { return m_matrix; }
-
- void setCombinedMatrix(const QMatrix4x4 &matrix);
- const QMatrix4x4 &combinedMatrix() const { return m_combined_matrix; }
-
-private:
- QMatrix4x4 m_matrix;
- QMatrix4x4 m_combined_matrix;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGRootNode : public QSGNode
-{
-public:
- QSGRootNode();
- ~QSGRootNode();
-
-private:
- void notifyNodeChange(QSGNode *node, DirtyFlags flags);
-
- friend class QSGRenderer;
- friend class QSGNode;
- friend class QSGGeometryNode;
-
- QList<QSGRenderer *> m_renderers;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGOpacityNode : public QSGNode
-{
-public:
- QSGOpacityNode();
- ~QSGOpacityNode();
-
- void setOpacity(qreal opacity);
- qreal opacity() const { return m_opacity; }
-
- void setCombinedOpacity(qreal opacity);
- qreal combinedOpacity() const { return m_combined_opacity; }
-
- bool isSubtreeBlocked() const;
-
-private:
- qreal m_opacity;
- qreal m_combined_opacity;
-};
-
-class Q_DECLARATIVE_EXPORT QSGNodeVisitor {
-public:
- virtual ~QSGNodeVisitor();
-
-protected:
- virtual void enterTransformNode(QSGTransformNode *) {}
- virtual void leaveTransformNode(QSGTransformNode *) {}
- virtual void enterClipNode(QSGClipNode *) {}
- virtual void leaveClipNode(QSGClipNode *) {}
- virtual void enterGeometryNode(QSGGeometryNode *) {}
- virtual void leaveGeometryNode(QSGGeometryNode *) {}
- virtual void enterOpacityNode(QSGOpacityNode *) {}
- virtual void leaveOpacityNode(QSGOpacityNode *) {}
- virtual void visitNode(QSGNode *n);
- virtual void visitChildren(QSGNode *n);
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGNode *n);
-Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGGeometryNode *n);
-Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGTransformNode *n);
-Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGOpacityNode *n);
-Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGRootNode *n);
-
-#endif
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // NODE_H
diff --git a/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h b/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h
deleted file mode 100644
index 25d7c11fa1..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 NODEUPDATER_P_H
-#define NODEUPDATER_P_H
-
-#include "qsgnode.h"
-#include <QtGui/private/qdatabuffer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_DECLARATIVE_EXPORT QSGNodeUpdater
-{
-public:
- QSGNodeUpdater();
-
- virtual void updateStates(QSGNode *n);
- virtual bool isNodeBlocked(QSGNode *n, QSGNode *root) const;
-
- void setToplevelOpacity(qreal alpha) { m_opacity_stack.last() = alpha; }
- qreal toplevelOpacity() const { return m_opacity_stack.last(); }
-
-protected:
- virtual void enterTransformNode(QSGTransformNode *);
- virtual void leaveTransformNode(QSGTransformNode *);
- void enterClipNode(QSGClipNode *c);
- void leaveClipNode(QSGClipNode *c);
- void enterOpacityNode(QSGOpacityNode *o);
- void leaveOpacityNode(QSGOpacityNode *o);
- void enterGeometryNode(QSGGeometryNode *);
- void leaveGeometryNode(QSGGeometryNode *);
-
- void visitNode(QSGNode *n);
- void visitChildren(QSGNode *n);
-
-
- QDataBuffer<const QMatrix4x4 *> m_combined_matrix_stack;
- QDataBuffer<qreal> m_opacity_stack;
- const QSGClipNode *m_current_clip;
-
- int m_force_update;
-
- qreal m_toplevel_alpha;
-};
-
-QT_END_NAMESPACE
-
-#endif // NODEUPDATER_P_H
diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h b/src/declarative/scenegraph/coreapi/qsgrenderer_p.h
deleted file mode 100644
index 05fb9b42fd..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 RENDERER_H
-#define RENDERER_H
-
-#include <qset.h>
-#include <qhash.h>
-
-#include <qcolor.h>
-#include <qopenglfunctions.h>
-#include <qopenglshaderprogram.h>
-
-#include "qsgnode.h"
-#include "qsgmaterial.h"
-#include "qsgtexture.h"
-
-#include <private/qsgcontext_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGMaterialShader;
-struct QSGMaterialType;
-class QOpenGLFramebufferObject;
-class TextureReference;
-class QSGBindable;
-class QSGNodeUpdater;
-
-class Q_DECLARATIVE_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions
-{
- Q_OBJECT
-public:
- enum ClipType
- {
- NoClip,
- ScissorClip,
- StencilClip
- };
-
- enum ClearModeBit
- {
- ClearColorBuffer = 0x0001,
- ClearDepthBuffer = 0x0002,
- ClearStencilBuffer = 0x0004
- };
- Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
-
- QSGRenderer(QSGContext *context);
- virtual ~QSGRenderer();
-
- void setRootNode(QSGRootNode *node);
- QSGRootNode *rootNode() const { return m_root_node; }
-
- void setDeviceRect(const QRect &rect) { m_device_rect = rect; }
- inline void setDeviceRect(const QSize &size) { setDeviceRect(QRect(QPoint(), size)); }
- QRect deviceRect() const { return m_device_rect; }
-
- void setViewportRect(const QRect &rect) { m_viewport_rect = rect; }
- inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
- QRect viewportRect() const { return m_viewport_rect; }
-
- // Accessed by QSGMaterialShader::RenderState.
- QMatrix4x4 currentProjectionMatrix() const { return m_current_projection_matrix; }
- QMatrix4x4 currentModelViewMatrix() const { return m_current_model_view_matrix; }
- QMatrix4x4 currentCombinedMatrix() const { return m_current_projection_matrix * m_current_model_view_matrix; }
- qreal currentOpacity() const { return m_current_opacity; }
-
- void setProjectionMatrixToDeviceRect();
- void setProjectionMatrixToRect(const QRectF &rect);
- void setProjectionMatrix(const QMatrix4x4 &matrix);
- QMatrix4x4 projectionMatrix() const { return m_projection_matrix; }
- bool isMirrored() const { return m_mirrored; }
-
- void setClearColor(const QColor &color);
- QColor clearColor() const { return m_clear_color; }
-
- QOpenGLContext *glContext() const { Q_ASSERT(m_context); return m_context->glContext(); }
-
- QSGContext *context();
-
- void renderScene();
- void renderScene(const QSGBindable &bindable);
- virtual void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
- virtual void materialChanged(QSGGeometryNode *node, QSGMaterial *from, QSGMaterial *to);
-
- QSGNodeUpdater *nodeUpdater() const;
- void setNodeUpdater(QSGNodeUpdater *updater);
-
- inline QSGMaterialShader::RenderState state(QSGMaterialShader::RenderState::DirtyStates dirty) const;
-
- void setClearMode(ClearMode mode) { m_clear_mode = mode; }
- ClearMode clearMode() const { return m_clear_mode; }
-
-signals:
- void sceneGraphChanged(); // Add, remove, ChangeFlags changes...
-
-protected:
- void draw(const QSGMaterialShader *material, const QSGGeometry *g);
-
- virtual void render() = 0;
- QSGRenderer::ClipType updateStencilClip(const QSGClipNode *clip);
-
- const QSGBindable *bindable() const { return m_bindable; }
-
- virtual void preprocess();
-
- void addNodesToPreprocess(QSGNode *node);
- void removeNodesToPreprocess(QSGNode *node);
-
-
- QColor m_clear_color;
- ClearMode m_clear_mode;
- QMatrix4x4 m_current_projection_matrix;
- QMatrix4x4 m_current_model_view_matrix;
- qreal m_current_opacity;
-
- QSGContext *m_context;
-
-private:
- QSGRootNode *m_root_node;
- QSGNodeUpdater *m_node_updater;
-
- QRect m_device_rect;
- QRect m_viewport_rect;
-
- QSet<QSGNode *> m_nodes_to_preprocess;
-
- QMatrix4x4 m_projection_matrix;
- QOpenGLShaderProgram m_clip_program;
- int m_clip_matrix_id;
-
- const QSGBindable *m_bindable;
-
- uint m_changed_emitted : 1;
- uint m_mirrored : 1;
- uint m_is_rendering : 1;
-
- uint m_vertex_buffer_bound : 1;
- uint m_index_buffer_bound : 1;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderer::ClearMode)
-
-class Q_DECLARATIVE_EXPORT QSGBindable
-{
-public:
- virtual ~QSGBindable() { }
- virtual void bind() const = 0;
- virtual void clear(QSGRenderer::ClearMode mode) const;
- virtual void reactivate() const;
-};
-
-class QSGBindableFbo : public QSGBindable
-{
-public:
- QSGBindableFbo(QOpenGLFramebufferObject *fbo);
- virtual void bind() const;
-private:
- QOpenGLFramebufferObject *m_fbo;
-};
-
-
-
-QSGMaterialShader::RenderState QSGRenderer::state(QSGMaterialShader::RenderState::DirtyStates dirty) const
-{
- QSGMaterialShader::RenderState s;
- s.m_dirty = dirty;
- s.m_data = this;
- return s;
-}
-
-
-class Q_DECLARATIVE_EXPORT QSGNodeDumper : public QSGNodeVisitor {
-
-public:
- static void dump(QSGNode *n);
-
- QSGNodeDumper() : m_indent(0) {}
- void visitNode(QSGNode *n);
- void visitChildren(QSGNode *n);
-
-private:
- int m_indent;
-};
-
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // RENDERER_H
diff --git a/src/declarative/scenegraph/qsgadaptationlayer.cpp b/src/declarative/scenegraph/qsgadaptationlayer.cpp
deleted file mode 100644
index 966a24acd3..0000000000
--- a/src/declarative/scenegraph/qsgadaptationlayer.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgadaptationlayer_p.h"
-
-#include <qmath.h>
-#include <private/qsgdistancefieldutil_p.h>
-#include <private/qsgdistancefieldglyphnode_p.h>
-#include <private/qrawfont_p.h>
-#include <QtGui/qguiapplication.h>
-#include <qdir.h>
-
-QT_BEGIN_NAMESPACE
-
-
-QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_caches_data;
-
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
- : ctx(c)
- , m_manager(man)
-{
- Q_ASSERT(font.isValid());
- m_font = font;
-
- m_cacheData = cacheData();
-
- QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- m_glyphCount = fontD->fontEngine->glyphCount();
-
- m_cacheData->doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
-
- m_referenceFont = m_font;
- m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution));
- Q_ASSERT(m_referenceFont.isValid());
-}
-
-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
-{
- 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);
- }
-
- return metric.value();
-}
-
-QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph) const
-{
- return m_cacheData->texCoords.value(glyph);
-}
-
-static QSGDistanceFieldGlyphCache::Texture g_emptyTexture;
-
-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();
-}
-
-void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
-{
- QSet<glyph_t> newGlyphs;
- int count = glyphs.count();
- for (int i = 0; i < count; ++i) {
- glyph_t glyphIndex = glyphs.at(i);
- if ((int) glyphIndex >= glyphCount()) {
- qWarning("Warning: distance-field glyph is not available with index %d", glyphIndex);
- continue;
- }
-
- if (m_cacheData->texCoords.contains(glyphIndex) || 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;
- }
-
- newGlyphs.insert(glyphIndex);
- }
-
- if (newGlyphs.isEmpty())
- return;
-
- QVector<glyph_t> glyphsVec;
- QSet<glyph_t>::const_iterator it = newGlyphs.constBegin();
- while (it != newGlyphs.constEnd()) {
- glyphsVec.append(*it);
- ++it;
- }
- requestGlyphs(glyphsVec);
-}
-
-void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
-{
- releaseGlyphs(glyphs);
-}
-
-void QSGDistanceFieldGlyphCache::update()
-{
- if (m_cacheData->pendingGlyphs.isEmpty())
- return;
-
- QHash<glyph_t, QImage> distanceFields;
-
- // ### Remove before final release
- static bool cacheDistanceFields = QGuiApplication::arguments().contains(QLatin1String("--cache-distance-fields"));
-
- 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());
-
- 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);
-
- if (cacheDistanceFields) {
- QString key = keyBase.arg(glyphIndex);
- QFile file(key);
- if (file.open(QFile::ReadOnly)) {
- int fileSize = file.size();
- int dim = sqrt(float(fileSize));
- QByteArray blob = file.readAll();
- QImage df(dim, dim, QImage::Format_Indexed8);
- memcpy(df.bits(), blob.constData(), fileSize);
- distanceFields.insert(glyphIndex, df);
- continue;
- }
- }
-
- QImage distanceField = qt_renderDistanceFieldGlyph(m_font, glyphIndex, m_cacheData->doubleGlyphResolution);
- distanceFields.insert(glyphIndex, distanceField);
-
- if (cacheDistanceFields) {
- QString key = keyBase.arg(glyphIndex);
- QFile file(key);
- file.open(QFile::WriteOnly);
- file.write((const char *) distanceField.constBits(), distanceField.width() * distanceField.height());
- }
- }
-
- m_cacheData->pendingGlyphs.reset();
-
- storeGlyphs(distanceFields);
-}
-
-void QSGDistanceFieldGlyphCache::addGlyphPositions(const QList<GlyphPosition> &glyphs)
-{
- int count = glyphs.count();
- for (int i = 0; i < count; ++i) {
- GlyphPosition glyph = glyphs.at(i);
-
- 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();
-
- m_cacheData->texCoords.insert(glyph.glyph, c);
- }
-}
-
-void QSGDistanceFieldGlyphCache::addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex)
-{
- int i = m_cacheData->textures.indexOf(tex);
- if (i == -1) {
- m_cacheData->textures.append(tex);
- i = m_cacheData->textures.size() - 1;
- } else {
- m_cacheData->textures[i].size = tex.size;
- }
- Texture *texture = &(m_cacheData->textures[i]);
-
- int count = glyphs.count();
- for (int j = 0; j < count; ++j)
- m_cacheData->glyphTextures.insert(glyphs.at(j), texture);
-
- QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
- while (it != m_cacheData->m_registeredNodes.end()) {
- (*it)->updateGeometry();
- ++it;
- }
-}
-
-void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyphs)
-{
- 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);
-}
-
-void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize)
-{
- int count = m_cacheData->textures.count();
- for (int i = 0; i < count; ++i) {
- Texture &tex = m_cacheData->textures[i];
- if (tex.textureId == oldTex) {
- tex.textureId = newTex;
- tex.size = newTexSize;
- return;
- }
- }
-}
-
-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/declarative/scenegraph/qsgadaptationlayer_p.h b/src/declarative/scenegraph/qsgadaptationlayer_p.h
deleted file mode 100644
index 82e0c7cf42..0000000000
--- a/src/declarative/scenegraph/qsgadaptationlayer_p.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 ADAPTATIONINTERFACES_H
-#define ADAPTATIONINTERFACES_H
-
-#include "qsgnode.h"
-#include "qsgtexture.h"
-#include <QtCore/qobject.h>
-#include <QtCore/qrect.h>
-#include <QtGui/qbrush.h>
-#include <QtGui/qcolor.h>
-#include <QtCore/qsharedpointer.h>
-#include <QtGui/qglyphrun.h>
-#include <QtCore/qurl.h>
-#include <private/qfontengine_p.h>
-#include <QtGui/private/qdatabuffer_p.h>
-#include <private/qopenglcontext_p.h>
-
-// ### remove
-#include <private/qquicktext_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGNode;
-class QImage;
-class TextureReference;
-class QSGDistanceFieldGlyphCacheManager;
-class QSGDistanceFieldGlyphNode;
-
-// TODO: Rename from XInterface to AbstractX.
-class Q_DECLARATIVE_EXPORT QSGRectangleNode : public QSGGeometryNode
-{
-public:
- virtual void setRect(const QRectF &rect) = 0;
- virtual void setColor(const QColor &color) = 0;
- virtual void setPenColor(const QColor &color) = 0;
- virtual void setPenWidth(qreal width) = 0;
- virtual void setGradientStops(const QGradientStops &stops) = 0;
- virtual void setRadius(qreal radius) = 0;
- virtual void setAligned(bool aligned) = 0;
-
- virtual void update() = 0;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGImageNode : public QSGGeometryNode
-{
-public:
- virtual void setTargetRect(const QRectF &rect) = 0;
- virtual void setSourceRect(const QRectF &rect) = 0;
- virtual void setTexture(QSGTexture *texture) = 0;
-
- virtual void setMipmapFiltering(QSGTexture::Filtering filtering) = 0;
- virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
- virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
- virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
-
- virtual void update() = 0;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGGlyphNode : public QSGGeometryNode
-{
-public:
- enum AntialiasingMode
- {
- GrayAntialiasing,
- LowQualitySubPixelAntialiasing,
- HighQualitySubPixelAntialiasing
- };
-
- virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) = 0;
- virtual void setColor(const QColor &color) = 0;
- virtual void setStyle(QQuickText::TextStyle style) = 0;
- virtual void setStyleColor(const QColor &color) = 0;
- virtual QPointF baseLine() const = 0;
-
- virtual QRectF boundingRect() const { return m_bounding_rect; }
- virtual void setBoundingRect(const QRectF &bounds) { m_bounding_rect = bounds; }
-
- virtual void setPreferredAntialiasingMode(AntialiasingMode) = 0;
-
- virtual void update() = 0;
-
-protected:
- QRectF m_bounding_rect;
-};
-
-class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCache
-{
-public:
- QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
- virtual ~QSGDistanceFieldGlyphCache();
-
- struct Metrics {
- qreal width;
- qreal height;
- qreal baselineX;
- qreal baselineY;
-
- bool isNull() const { return width == 0 || height == 0; }
- };
-
- struct TexCoord {
- qreal x;
- qreal y;
- qreal width;
- qreal height;
- qreal xMargin;
- qreal yMargin;
-
- TexCoord() : x(0), y(0), width(-1), height(-1), xMargin(0), yMargin(0) { }
-
- bool isNull() const { return width <= 0 || height <= 0; }
- bool isValid() const { return width >= 0 && height >= 0; }
- };
-
- struct Texture {
- GLuint textureId;
- QSize size;
-
- Texture() : textureId(0), size(QSize()) { }
- bool operator == (const Texture &other) const { return textureId == other.textureId; }
- };
-
- const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
-
- const QRawFont &font() const { return m_font; }
-
- qreal fontScale() const;
- int distanceFieldRadius() const;
- int glyphCount() const { return m_glyphCount; }
- bool doubleGlyphResolution() const { return m_cacheData->doubleGlyphResolution; }
-
- Metrics glyphMetrics(glyph_t glyph);
- TexCoord glyphTexCoord(glyph_t glyph) const;
- const Texture *glyphTexture(glyph_t glyph) const;
-
- void populate(const QVector<glyph_t> &glyphs);
- void release(const QVector<glyph_t> &glyphs);
-
- void update();
-
- void registerGlyphNode(QSGDistanceFieldGlyphNode *node);
- void unregisterGlyphNode(QSGDistanceFieldGlyphNode *node);
-
-protected:
- struct GlyphPosition {
- glyph_t glyph;
- QPointF position;
- };
-
- virtual void requestGlyphs(const QVector<glyph_t> &glyphs) = 0;
- virtual void storeGlyphs(const QHash<glyph_t, QImage> &glyphs) = 0;
- virtual void releaseGlyphs(const QVector<glyph_t> &glyphs) = 0;
-
- void addGlyphPositions(const QList<GlyphPosition> &glyphs);
- void addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex);
- void markGlyphsToRender(const QVector<glyph_t> &glyphs);
- void removeGlyph(glyph_t glyph);
-
- void updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize);
-
- bool containsGlyph(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;
-
- GlyphCacheData(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
- , pendingGlyphs(64)
- , doubleGlyphResolution(false)
- {}
-
- void invalidateResource()
- {
- textures.clear();
- glyphTextures.clear();
- texCoords.clear();
- }
-
- void freeResource(QOpenGLContext *)
- {
- }
- };
-
- 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;
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp
deleted file mode 100644
index 1545303d4a..0000000000
--- a/src/declarative/scenegraph/qsgcontext.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <private/qsgcontext_p.h>
-#include <private/qsgrenderer_p.h>
-#include "qsgnode.h"
-
-#include <private/qdeclarativepixmapcache_p.h>
-
-#include <private/qsgdefaultrenderer_p.h>
-
-#include <private/qsgdistancefieldutil_p.h>
-#include <private/qsgdefaultdistancefieldglyphcache_p.h>
-#include <private/qsgdefaultrectanglenode_p.h>
-#include <private/qsgdefaultimagenode_p.h>
-#include <private/qsgdefaultglyphnode_p.h>
-#include <private/qsgdistancefieldglyphnode_p.h>
-
-#include <private/qsgtexture_p.h>
-#include <QGuiApplication>
-#include <QOpenGLContext>
-
-#include <QDeclarativeImageProvider>
-
-#include <private/qobject_p.h>
-#include <qmutex.h>
-
-DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
-DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-/*
- Comments about this class from Gunnar:
-
- The QSGContext class is right now two things.. The first is the
- adaptation layer and central storage ground for all the things
- in the scene graph, like textures and materials. This part really
- belongs inside the scene graph coreapi.
-
- The other part is the QML adaptation classes, like how to implement
- rectangle nodes. This is not part of the scene graph core API, but
- more part of the QML adaptation of scene graph.
-
- If we ever move the scene graph core API into its own thing, this class
- needs to be split in two. Right now its one because we're lazy when it comes
- to defining plugin interfaces..
-*/
-
-
-QT_BEGIN_NAMESPACE
-
-class QSGContextPrivate : public QObjectPrivate
-{
-public:
- QSGContextPrivate()
- : rootNode(0)
- , renderer(0)
- , gl(0)
- , distanceFieldCacheManager(0)
- , flashMode(qmlFlashMode())
- , distanceFieldDisabled(qmlDisableDistanceField())
- {
- renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
- }
-
- ~QSGContextPrivate()
- {
- }
-
- QSGRootNode *rootNode;
- QSGRenderer *renderer;
-
- QOpenGLContext *gl;
-
- QHash<QSGMaterialType *, QSGMaterialShader *> materials;
- QHash<QDeclarativeTextureFactory *, QSGTexture *> textures;
-
- QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
-
- bool flashMode;
- float renderAlpha;
- bool distanceFieldDisabled;
-};
-
-
-/*!
- \class QSGContext
-
- \brief The QSGContext holds the scene graph entry points for one QML engine.
-
- The context is not ready for use until it has a QOpenGLContext. Once that happens,
- the scene graph population can start.
-
- \internal
- */
-
-QSGContext::QSGContext(QObject *parent) :
- QObject(*(new QSGContextPrivate), parent)
-{
-}
-
-
-QSGContext::~QSGContext()
-{
- Q_D(QSGContext);
- qDeleteAll(d->textures.values());
- d->textures.clear();
- delete d->renderer;
- delete d->rootNode;
- qDeleteAll(d->materials.values());
- delete d->distanceFieldCacheManager;
-}
-
-
-QSGTexture *QSGContext::textureForFactory(QDeclarativeTextureFactory *factory)
-{
- Q_D(QSGContext);
- if (!factory)
- return 0;
-
- QSGTexture *texture = d->textures.value(factory);
- if (!texture) {
- if (QDeclarativeDefaultTextureFactory *dtf = qobject_cast<QDeclarativeDefaultTextureFactory *>(factory))
- texture = createTexture(dtf->image());
- else
- texture = factory->createTexture();
- d->textures.insert(factory, texture);
- connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)));
- }
- return texture;
-}
-
-
-void QSGContext::textureFactoryDestroyed(QObject *o)
-{
- Q_D(QSGContext);
- QDeclarativeTextureFactory *f = static_cast<QDeclarativeTextureFactory *>(o);
-
- // This function will only be called on the scene graph thread, so it is
- // safe to directly delete the texture here.
- delete d->textures.take(f);
-}
-
-
-
-/*!
- Returns the renderer. The renderer instance is created through the adaptation layer.
- */
-QSGRenderer *QSGContext::renderer() const
-{
- Q_D(const QSGContext);
- return d->renderer;
-}
-
-
-/*!
- Returns the root node. The root node instance is only created once the scene graph
- context becomes ready.
- */
-QSGRootNode *QSGContext::rootNode() const
-{
- Q_D(const QSGContext);
- return d->rootNode;
-}
-
-
-QOpenGLContext *QSGContext::glContext() const
-{
- Q_D(const QSGContext);
- return d->gl;
-}
-
-/*!
- Initializes the scene graph context with the GL context \a context. This also
- emits the ready() signal so that the QML graph can start building scene graph nodes.
- */
-void QSGContext::initialize(QOpenGLContext *context)
-{
- Q_D(QSGContext);
-
- Q_ASSERT(!d->gl);
-
- d->gl = context;
-
- d->renderer = createRenderer();
- d->renderer->setClearColor(Qt::white);
-
- d->rootNode = new QSGRootNode();
- d->renderer->setRootNode(d->rootNode);
-
- emit ready();
-}
-
-
-/*!
- Returns if the scene graph context is ready or not, meaning that it has a valid
- GL context.
- */
-bool QSGContext::isReady() const
-{
- Q_D(const QSGContext);
- return d->gl;
-}
-
-
-void QSGContext::renderNextFrame(QOpenGLFramebufferObject *fbo)
-{
- Q_D(QSGContext);
-
- if (fbo) {
- QSGBindableFbo bindable(fbo);
- d->renderer->renderScene(bindable);
- } else {
- d->renderer->renderScene();
- }
-
-}
-
-/*!
- Factory function for scene graph backends of the Rectangle element.
- */
-QSGRectangleNode *QSGContext::createRectangleNode()
-{
- return new QSGDefaultRectangleNode(this);
-}
-
-/*!
- Factory function for scene graph backends of the Image element.
- */
-QSGImageNode *QSGContext::createImageNode()
-{
- return new QSGDefaultImageNode;
-}
-
-/*!
- Factory function for scene graph backends of the distance-field glyph cache.
- */
-QSGDistanceFieldGlyphCache *QSGContext::createDistanceFieldGlyphCache(const QRawFont &font)
-{
- Q_D(QSGContext);
- return new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
-}
-
-/*!
- Factory function for scene graph backends of the Text elements;
- */
-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);
- return node;
- }
-}
-
-/*!
- Factory function for the scene graph renderers.
-
- The renderers are used for the toplevel renderer and once for every
- QQuickShaderEffectSource used in the QML scene.
- */
-QSGRenderer *QSGContext::createRenderer()
-{
- // ### Do something with this before release...
- static bool doFrontToBack = qApp->arguments().contains(QLatin1String("--opaque-front-to-back"));
- QSGDefaultRenderer *renderer = new QSGDefaultRenderer(this);
- if (doFrontToBack) {
- printf("QSGContext: Sorting opaque nodes front to back...\n");
- renderer->setSortFrontToBackEnabled(true);
- }
- return renderer;
-}
-
-
-
-/*!
- Return true if the image provider supports direct decoding of images,
- straight into textures without going through a QImage first.
-
- If the implementation returns true from this function, the decodeImageToTexture() function
- will be called to read data from a QIODevice, rather than QML decoding
- the image using QImageReader and passing the result to setImage().
-
- \warning This function will be called from outside the GUI and rendering threads
- and must not make use of OpenGL.
- */
-
-bool QSGContext::canDecodeImageToTexture() const
-{
- return true;
-}
-
-
-
-/*!
- Decode the data in \a dev directly to a texture provider of \a requestSize size.
- The size of the decoded data should be written to \a impsize.
-
- If the implementation fails to decode the image data, it should return 0. The
- image data will then be decoded normally.
-
- \warning This function will be called from outside the GUI and renderer threads
- and must not make use of GL calls.
- */
-
-QSGTexture *QSGContext::decodeImageToTexture(QIODevice *dev,
- QSize *size,
- const QSize &requestSize)
-{
- Q_UNUSED(dev);
- Q_UNUSED(size);
- Q_UNUSED(requestSize);
- return 0;
-}
-
-
-
-QSurfaceFormat QSGContext::defaultSurfaceFormat() const
-{
- QSurfaceFormat format;
- format.setDepthBufferSize(24);
- format.setStencilBufferSize(8);
- format.setSamples(16);
- return format;
-}
-
-
-/*!
- Factory function for texture objects.
-
- If \a image is a valid image, the QSGTexture::setImage function
- will be called with \a image as argument.
- */
-
-QSGTexture *QSGContext::createTexture(const QImage &image) const
-{
- QSGPlainTexture *t = new QSGPlainTexture();
- if (!image.isNull())
- t->setImage(image);
- return t;
-}
-
-
-
-/*!
- Returns the minimum supported framebuffer object size.
- */
-
-QSize QSGContext::minimumFBOSize() const
-{
-#ifdef Q_OS_MAC
- return QSize(33, 33);
-#else
- return QSize(1, 1);
-#endif
-}
-
-
-
-/*!
- Returns a material shader for the given material.
- */
-
-QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
-{
- Q_D(QSGContext);
- QSGMaterialType *type = material->type();
- QSGMaterialShader *shader = d->materials.value(type);
- if (shader)
- return shader;
-
- shader = material->createShader();
- shader->compile();
- shader->initialize();
- d->materials[type] = shader;
-
- return shader;
-}
-
-
-
-/*!
- Sets whether the scene graph should render with flashing update rectangles or not
- */
-
-void QSGContext::setFlashModeEnabled(bool enabled)
-{
- d_func()->flashMode = enabled;
-}
-
-
-/*!
- Returns true if the scene graph should be rendered with flashing update rectangles
- */
-bool QSGContext::isFlashModeEnabled() const
-{
- return d_func()->flashMode;
-}
-
-
-/*!
- Sets the toplevel opacity for rendering. This value will be multiplied into all
- drawing calls where possible.
-
- The default value is 1. Any other value will cause artifacts and is primarily
- useful for debugging.
- */
-void QSGContext::setRenderAlpha(qreal renderAlpha)
-{
- d_func()->renderAlpha = renderAlpha;
-}
-
-
-/*!
- Returns the toplevel opacity used for rendering.
-
- The default value is 1.
-
- \sa setRenderAlpha()
- */
-qreal QSGContext::renderAlpha() const
-{
- return d_func()->renderAlpha;
-}
-
-
-/*!
- Sets whether or not the scene graph should use the distance field technique to render text
- */
-void QSGContext::setDistanceFieldEnabled(bool enabled)
-{
- d_func()->distanceFieldDisabled = !enabled;
-}
-
-
-/*!
- Returns true if the scene graph uses the distance field technique to render text
- */
-bool QSGContext::isDistanceFieldEnabled() const
-{
- return !d_func()->distanceFieldDisabled;
-}
-
-
-
-/*!
- Creates a new animation driver.
- */
-
-QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
-{
- return new QAnimationDriver(parent);
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgcontext_p.h b/src/declarative/scenegraph/qsgcontext_p.h
deleted file mode 100644
index ed1654b8fc..0000000000
--- a/src/declarative/scenegraph/qsgcontext_p.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGCONTEXT_H
-#define QSGCONTEXT_H
-
-#include <QtCore/QObject>
-#include <QtCore/qabstractanimation.h>
-
-#include <QtGui/QImage>
-#include <QtGui/QSurfaceFormat>
-
-#include <private/qrawfont_p.h>
-
-#include "qsgnode.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGContextPrivate;
-class QSGRectangleNode;
-class QSGImageNode;
-class QSGGlyphNode;
-class QSGRenderer;
-class QSGDistanceFieldGlyphCache;
-
-class QSGTexture;
-class QSGMaterial;
-class QSGMaterialShader;
-class QSGEngine;
-
-class QOpenGLContext;
-class QOpenGLFramebufferObject;
-
-class QDeclarativeTextureFactory;
-
-class Q_DECLARATIVE_EXPORT QSGContext : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QSGContext)
-
-public:
- explicit QSGContext(QObject *parent = 0);
- ~QSGContext();
-
- virtual void initialize(QOpenGLContext *context);
-
- QSGRenderer *renderer() const;
-
- void setRootNode(QSGRootNode *node);
- QSGRootNode *rootNode() const;
-
- QOpenGLContext *glContext() const;
-
- bool isReady() const;
-
- QSGMaterialShader *prepareMaterial(QSGMaterial *material);
-
- virtual void renderNextFrame(QOpenGLFramebufferObject *fbo = 0);
-
- virtual QSGDistanceFieldGlyphCache *createDistanceFieldGlyphCache(const QRawFont &font);
-
- virtual QSGRectangleNode *createRectangleNode();
- virtual QSGImageNode *createImageNode();
- virtual QSGGlyphNode *createGlyphNode();
- virtual QSGRenderer *createRenderer();
-
- virtual bool canDecodeImageToTexture() const;
- virtual QSGTexture *decodeImageToTexture(QIODevice *dev,
- QSize *size,
- const QSize &requestSize);
- virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
- virtual QSize minimumFBOSize() const;
-
- virtual QSurfaceFormat defaultSurfaceFormat() const;
-
- QSGTexture *textureForFactory(QDeclarativeTextureFactory *factory);
-
- static QSGContext *createDefaultContext();
-
- void setFlashModeEnabled(bool enabled);
- bool isFlashModeEnabled() const;
-
- void setRenderAlpha(qreal renderAlpha);
- qreal renderAlpha() const;
-
- void setDistanceFieldEnabled(bool enabled);
- bool isDistanceFieldEnabled() const;
-
- virtual QAnimationDriver *createAnimationDriver(QObject *parent);
-
-signals:
- void ready();
-
-public slots:
- void textureFactoryDestroyed(QObject *o);
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGCONTEXT_H
diff --git a/src/declarative/scenegraph/qsgcontextplugin.cpp b/src/declarative/scenegraph/qsgcontextplugin.cpp
deleted file mode 100644
index 79bcbf9c04..0000000000
--- a/src/declarative/scenegraph/qsgcontextplugin.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgcontextplugin_p.h"
-#include <private/qsgcontext_p.h>
-#include <QtGui/qguiapplication.h>
-#include <QtCore/private/qfactoryloader_p.h>
-#include <QtCore/qlibraryinfo.h>
-
-QT_BEGIN_NAMESPACE
-
-QSGContextPlugin::QSGContextPlugin(QObject *parent)
- : QObject(parent)
-{
-}
-
-QSGContextPlugin::~QSGContextPlugin()
-{
-}
-
-#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QSGContextFactoryInterface_iid, QLatin1String("/scenegraph")))
-#endif
-
-/*!
- \fn QSGContext *QSGContext::createDefaultContext()
-
- Creates a default scene graph context for the current hardware.
- This may load a device-specific plugin.
-*/
-QSGContext *QSGContext::createDefaultContext()
-{
- const QStringList args = QGuiApplication::arguments();
- QString device;
- for (int index = 0; index < args.count(); ++index) {
- if (args.at(index).startsWith(QLatin1String("--device="))) {
- device = args.at(index).mid(9);
- break;
- }
- }
- if (device.isEmpty())
- device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
- if (device.isEmpty())
- return new QSGContext();
-
-#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
- if (QSGContextFactoryInterface *factory
- = qobject_cast<QSGContextFactoryInterface*>
- (loader()->instance(device))) {
- QSGContext *context = factory->create(device);
- if (context)
- return context;
- }
-#ifndef QT_NO_DEBUG
- qWarning("Could not create scene graph context for device '%s'"
- " - check that plugins are installed correctly in %s",
- qPrintable(device),
- qPrintable(QLibraryInfo::location(QLibraryInfo::PluginsPath)));
-#endif
-#endif // QT_NO_LIBRARY || QT_NO_SETTINGS
-
- return new QSGContext();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgcontextplugin_p.h b/src/declarative/scenegraph/qsgcontextplugin_p.h
deleted file mode 100644
index 78c4a25372..0000000000
--- a/src/declarative/scenegraph/qsgcontextplugin_p.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGCONTEXTPLUGIN_H
-#define QSGCONTEXTPLUGIN_H
-
-#include <QtCore/qplugin.h>
-#include <QtCore/qfactoryinterface.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGContext;
-
-struct Q_DECLARATIVE_EXPORT QSGContextFactoryInterface : public QFactoryInterface
-{
- virtual QSGContext *create(const QString &key) const = 0;
-};
-
-#define QSGContextFactoryInterface_iid \
- "com.trolltech.Qt.QSGContextFactoryInterface"
-Q_DECLARE_INTERFACE(QSGContextFactoryInterface, QSGContextFactoryInterface_iid)
-
-class Q_DECLARATIVE_EXPORT QSGContextPlugin : public QObject, public QSGContextFactoryInterface
-{
- Q_OBJECT
- Q_INTERFACES(QSGContextFactoryInterface:QFactoryInterface)
-public:
- explicit QSGContextPlugin(QObject *parent = 0);
- virtual ~QSGContextPlugin();
-
- virtual QStringList keys() const = 0;
- virtual QSGContext *create(const QString &key) const = 0;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGCONTEXTPLUGIN_H
diff --git a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
deleted file mode 100644
index 3dfa1bd269..0000000000
--- a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdefaultdistancefieldglyphcache_p.h"
-
-#include <private/qsgdistancefieldutil_p.h>
-#include <qopenglfunctions.h>
-
-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_textureData = textureData(c);
-}
-
-void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector<glyph_t> &glyphs)
-{
- int count = glyphs.count();
-
- // Avoid useless and costly glyph re-generation
- if (cacheIsFull() && !m_textureData->unusedGlyphs.isEmpty()) {
- for (int i = 0; i < count; ++i) {
- glyph_t glyphIndex = glyphs.at(i);
- if (containsGlyph(glyphIndex) && m_textureData->unusedGlyphs.contains(glyphIndex))
- m_textureData->unusedGlyphs.remove(glyphIndex);
- }
- }
-
- QList<GlyphPosition> glyphPositions;
- QVector<glyph_t> glyphsToRender;
-
- for (int i = 0; i < count; ++i) {
- glyph_t glyphIndex = glyphs.at(i);
-
- if (++m_textureData->glyphRefCount[glyphIndex] == 1)
- m_textureData->unusedGlyphs.remove(glyphIndex);
-
- if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
- continue;
-
- GlyphPosition p;
- p.glyph = glyphIndex;
- p.position = QPointF(m_textureData->currX, m_textureData->currY);
-
- if (!cacheIsFull()) {
- m_textureData->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
- if (m_textureData->currX >= maxTextureSize()) {
- m_textureData->currX = 0;
- m_textureData->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
- }
- } else {
- // Recycle glyphs
- if (!m_textureData->unusedGlyphs.isEmpty()) {
- glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
- TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
- p.position = QPointF(unusedCoord.x, unusedCoord.y);
- m_textureData->unusedGlyphs.remove(unusedGlyph);
- removeGlyph(unusedGlyph);
- }
- }
-
- if (p.position.y() < maxTextureSize()) {
- glyphPositions.append(p);
- glyphsToRender.append(glyphIndex);
- }
- }
-
- addGlyphPositions(glyphPositions);
- markGlyphsToRender(glyphsToRender);
-}
-
-void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage> &glyphs)
-{
- int requiredWidth = maxTextureSize();
- int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default..
- int requiredHeight = qMin(maxTextureSize(),
- qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
- QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows));
-
- resizeTexture((requiredWidth), (requiredHeight));
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
- 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);
-
- glyphTextures.append(glyphIndex);
-
- QImage glyph = it.value();
-
- if (useWorkaroundBrokenFBOReadback()) {
- uchar *inBits = glyph.scanLine(0);
- uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x);
- for (int y = 0; y < glyph.height(); ++y) {
- qMemCopy(outBits, inBits, glyph.width());
- inBits += glyph.bytesPerLine();
- outBits += m_textureData->image.bytesPerLine();
- }
- }
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
- }
-
- Texture t;
- t.textureId = m_textureData->texture;
- t.size = m_textureData->size;
- addGlyphTextures(glyphTextures, t);
-}
-
-void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector<glyph_t> &glyphs)
-{
- int count = glyphs.count();
- for (int i = 0; i < count; ++i) {
- glyph_t glyphIndex = glyphs.at(i);
- if (--m_textureData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
- m_textureData->unusedGlyphs.insert(glyphIndex);
- }
-}
-
-void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
-{
- if (useWorkaroundBrokenFBOReadback() && m_textureData->image.isNull())
- m_textureData->image = QImage(width, height, QImage::Format_Indexed8);
-
- while (glGetError() != GL_NO_ERROR) { }
-
- glGenTextures(1, &m_textureData->texture);
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- m_textureData->size = QSize(width, height);
-
- GLuint error = glGetError();
- if (error != GL_NO_ERROR) {
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &m_textureData->texture);
- m_textureData->texture = 0;
- }
-
-}
-
-void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
-{
- int oldWidth = m_textureData->size.width();
- int oldHeight = m_textureData->size.height();
- if (width == oldWidth && height == oldHeight)
- return;
-
- GLuint oldTexture = m_textureData->texture;
- createTexture(width, height);
-
- if (!oldTexture)
- return;
-
- updateTexture(oldTexture, m_textureData->texture, m_textureData->size);
-
- if (useWorkaroundBrokenFBOReadback()) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, m_textureData->image.constBits());
- m_textureData->image = m_textureData->image.copy(0, 0, width, height);
- glDeleteTextures(1, &oldTexture);
- return;
- }
-
- if (!m_textureData->blitProgram)
- m_textureData->createBlitProgram();
-
- Q_ASSERT(m_textureData->blitProgram);
-
- if (!m_textureData->fbo)
- ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo);
- ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo);
-
- GLuint tmp_texture;
- glGenTextures(1, &tmp_texture);
- glBindTexture(GL_TEXTURE_2D, tmp_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glBindTexture(GL_TEXTURE_2D, 0);
- ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tmp_texture, 0);
-
- ctx->functions()->glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, oldTexture);
-
- // save current render states
- GLboolean stencilTestEnabled;
- GLboolean depthTestEnabled;
- GLboolean scissorTestEnabled;
- GLboolean blendEnabled;
- GLint viewport[4];
- GLint oldProgram;
- glGetBooleanv(GL_STENCIL_TEST, &stencilTestEnabled);
- glGetBooleanv(GL_DEPTH_TEST, &depthTestEnabled);
- glGetBooleanv(GL_SCISSOR_TEST, &scissorTestEnabled);
- glGetBooleanv(GL_BLEND, &blendEnabled);
- glGetIntegerv(GL_VIEWPORT, &viewport[0]);
- glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram);
-
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
-
- 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);
-
- 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));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
-
- ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, 0);
- glDeleteTextures(1, &tmp_texture);
- glDeleteTextures(1, &oldTexture);
-
- ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- // restore render states
- if (stencilTestEnabled)
- glEnable(GL_STENCIL_TEST);
- if (depthTestEnabled)
- glEnable(GL_DEPTH_TEST);
- if (scissorTestEnabled)
- glEnable(GL_SCISSOR_TEST);
- if (blendEnabled)
- glEnable(GL_BLEND);
- glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
- ctx->functions()->glUseProgram(oldProgram);
-}
-
-bool QSGDefaultDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
-{
- static bool set = false;
- static bool useWorkaround = false;
- if (!set) {
- QOpenGLContextPrivate *ctx_p = static_cast<QOpenGLContextPrivate *>(QOpenGLContextPrivate::get(ctx));
- useWorkaround = ctx_p->workaround_brokenFBOReadBack;
- set = true;
- }
- return useWorkaround;
-}
-
-int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const
-{
- if (!m_maxTextureSize)
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
- return m_maxTextureSize;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
deleted file mode 100644
index 28860912c8..0000000000
--- a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
-#define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
-
-#include <QtGui/qopenglfunctions.h>
-#include <private/qsgadaptationlayer_p.h>
-#include <qopenglshaderprogram.h>
-#include <QtGui/private/qopenglengineshadersource_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_DECLARATIVE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
-{
-public:
- QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
-
- void requestGlyphs(const QVector<glyph_t> &glyphs);
- void storeGlyphs(const QHash<glyph_t, QImage> &glyphs);
- void releaseGlyphs(const QVector<glyph_t> &glyphs);
-
- bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
- bool useWorkaroundBrokenFBOReadback() const;
- int maxTextureSize() const;
-
-private:
- void createTexture(int width, int height);
- void resizeTexture(int width, int height);
-
- mutable int m_maxTextureSize;
-
- struct DistanceFieldTextureData : public QOpenGLSharedResource {
- GLuint texture;
- GLuint fbo;
- QSize size;
- QHash<glyph_t, quint32> glyphRefCount;
- QSet<glyph_t> unusedGlyphs;
- int currX;
- int currY;
- QImage image;
-
- QOpenGLShaderProgram *blitProgram;
- GLfloat blitVertexCoordinateArray[8];
- GLfloat blitTextureCoordinateArray[8];
-
- DistanceFieldTextureData(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
- , texture(0)
- , fbo(0)
- , currX(0)
- , currY(0)
- , blitProgram(0)
- {
- 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;
- }
-
- void invalidateResource()
- {
- texture = 0;
- fbo = 0;
- size = QSize();
- delete blitProgram;
- blitProgram = 0;
- }
-
- void freeResource(QOpenGLContext *ctx)
- {
- glDeleteTextures(1, &texture);
- ctx->functions()->glDeleteFramebuffers(1, &fbo);
- delete blitProgram;
- blitProgram = 0;
- }
-
- 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();
- }
- };
-
- DistanceFieldTextureData *textureData(QOpenGLContext *c);
- DistanceFieldTextureData *m_textureData;
- static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp b/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp
deleted file mode 100644
index 3476ab1665..0000000000
--- a/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdefaultglyphnode_p_p.h"
-
-#include <qopenglshaderprogram.h>
-
-#include <QtGui/private/qopengltextureglyphcache_p.h>
-#include <private/qfontengine_p.h>
-#include <private/qopenglextensions_p.h>
-
-#include <private/qsgtexture_p.h>
-
-#include <private/qrawfont_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGTextMaskMaterialData : public QSGMaterialShader
-{
-public:
- QSGTextMaskMaterialData();
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-private:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- int m_matrix_id;
- int m_color_id;
- int m_textureScale_id;
-};
-
-const char *QSGTextMaskMaterialData::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGTextMaskMaterialData::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color * texture2D(texture, sampleCoord).a; \n"
- "}";
-}
-
-char const *const *QSGTextMaskMaterialData::attributeNames() const
-{
- static char const *const attr[] = { "vCoord", "tCoord", 0 };
- return attr;
-}
-
-QSGTextMaskMaterialData::QSGTextMaskMaterialData()
-{
-}
-
-void QSGTextMaskMaterialData::initialize()
-{
- m_matrix_id = program()->uniformLocation("matrix");
- m_color_id = program()->uniformLocation("color");
- m_textureScale_id = program()->uniformLocation("textureScale");
-}
-
-void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
- QSGTextMaskMaterial *material = static_cast<QSGTextMaskMaterial *>(newEffect);
- QSGTextMaskMaterial *oldMaterial = static_cast<QSGTextMaskMaterial *>(oldEffect);
-
- if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
- QVector4D color(material->color().redF(), material->color().greenF(),
- material->color().blueF(), material->color().alphaF());
- color *= state.opacity();
- program()->setUniformValue(m_color_id, color);
- }
-
- bool updated = material->ensureUpToDate();
- Q_ASSERT(material->texture());
-
- Q_ASSERT(oldMaterial == 0 || oldMaterial->texture());
- if (updated
- || oldMaterial == 0
- || oldMaterial->texture()->textureId() != material->texture()->textureId()) {
- program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->cacheTextureWidth(),
- 1.0 / material->cacheTextureHeight()));
- glBindTexture(GL_TEXTURE_2D, material->texture()->textureId());
-
- // Set the mag/min filters to be linear. We only need to do this when the texture
- // has been recreated.
- if (updated) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- }
-
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
-}
-
-QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font)
- : m_texture(0), m_glyphCache(), m_font(font)
-{
- init();
-}
-
-QSGTextMaskMaterial::~QSGTextMaskMaterial()
-{
-}
-
-void QSGTextMaskMaterial::init()
-{
- Q_ASSERT(m_font.isValid());
-
- QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_A8;
- setFlag(Blending, true);
-
- QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- Q_ASSERT(ctx != 0);
-
- QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- if (fontD->fontEngine != 0) {
- m_glyphCache = fontD->fontEngine->glyphCache(ctx, type, QTransform());
- if (!m_glyphCache || m_glyphCache->cacheType() != type) {
- m_glyphCache = new QOpenGLTextureGlyphCache(type, QTransform());
- fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
- }
- }
-}
-
-void QSGTextMaskMaterial::populate(const QPointF &p,
- const QVector<quint32> &glyphIndexes,
- const QVector<QPointF> &glyphPositions,
- QSGGeometry *geometry,
- QRectF *boundingRect,
- QPointF *baseLine)
-{
- Q_ASSERT(m_font.isValid());
- QVector<QFixedPoint> fixedPointPositions;
- for (int i=0; i<glyphPositions.size(); ++i)
- fixedPointPositions.append(QFixedPoint::fromPointF(glyphPositions.at(i)));
-
- QTextureGlyphCache *cache = glyphCache();
-
- QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- cache->populate(fontD->fontEngine, glyphIndexes.size(), glyphIndexes.constData(),
- fixedPointPositions.data());
- cache->fillInPendingGlyphs();
-
- int margin = cache->glyphMargin();
-
- Q_ASSERT(geometry->indexType() == GL_UNSIGNED_SHORT);
- geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6);
- QVector4D *vp = (QVector4D *)geometry->vertexDataAsTexturedPoint2D();
- Q_ASSERT(geometry->sizeOfVertex() == sizeof(QVector4D));
- ushort *ip = geometry->indexDataAsUShort();
-
- QPointF position(p.x(), p.y() - m_font.ascent());
- bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions();
- for (int i=0; i<glyphIndexes.size(); ++i) {
- QFixed subPixelPosition;
- if (supportsSubPixelPositions)
- subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPositions.at(i).x()));
-
- QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition);
- const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
-
- QPointF glyphPosition = glyphPositions.at(i) + position;
- int x = qRound(glyphPosition.x()) + c.baseLineX - margin;
- int y = qRound(glyphPosition.y()) - c.baseLineY - margin;
-
- *boundingRect |= QRectF(x + margin, y + margin, c.w, c.h);
-
- float cx1 = x;
- float cx2 = x + c.w;
- float cy1 = y;
- float cy2 = y + c.h;
-
- float tx1 = c.x;
- float tx2 = (c.x + c.w);
- float ty1 = c.y;
- float ty2 = (c.y + c.h);
-
- if (baseLine->isNull())
- *baseLine = glyphPosition;
-
- vp[4 * i + 0] = QVector4D(cx1, cy1, tx1, ty1);
- vp[4 * i + 1] = QVector4D(cx2, cy1, tx2, ty1);
- vp[4 * i + 2] = QVector4D(cx1, cy2, tx1, ty2);
- vp[4 * i + 3] = QVector4D(cx2, cy2, tx2, ty2);
-
- int o = i * 4;
- ip[6 * i + 0] = o + 0;
- ip[6 * i + 1] = o + 2;
- ip[6 * i + 2] = o + 3;
- ip[6 * i + 3] = o + 3;
- ip[6 * i + 4] = o + 1;
- ip[6 * i + 5] = o + 0;
- }
-}
-
-QSGMaterialType *QSGTextMaskMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QOpenGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const
-{
- return static_cast<QOpenGLTextureGlyphCache*>(m_glyphCache.data());
-}
-
-QSGMaterialShader *QSGTextMaskMaterial::createShader() const
-{
- return new QSGTextMaskMaterialData;
-}
-
-int QSGTextMaskMaterial::compare(const QSGMaterial *o) const
-{
- Q_ASSERT(o && type() == o->type());
- const QSGTextMaskMaterial *other = static_cast<const QSGTextMaskMaterial *>(o);
- if (m_glyphCache != other->m_glyphCache)
- return m_glyphCache - other->m_glyphCache;
- QRgb c1 = m_color.rgba();
- QRgb c2 = other->m_color.rgba();
- return int(c2 < c1) - int(c1 < c2);
-}
-
-bool QSGTextMaskMaterial::ensureUpToDate()
-{
- QSize glyphCacheSize(glyphCache()->width(), glyphCache()->height());
- if (glyphCacheSize != m_size) {
- if (m_texture)
- delete m_texture;
- m_texture = new QSGPlainTexture();
- m_texture->setTextureId(glyphCache()->texture());
- m_texture->setTextureSize(QSize(glyphCache()->width(), glyphCache()->height()));
- m_texture->setOwnsTexture(false);
-
- m_size = glyphCacheSize;
-
- return true;
- } else {
- return false;
- }
-}
-
-int QSGTextMaskMaterial::cacheTextureWidth() const
-{
- return glyphCache()->width();
-}
-
-int QSGTextMaskMaterial::cacheTextureHeight() const
-{
- return glyphCache()->height();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p.h b/src/declarative/scenegraph/qsgdefaultglyphnode_p.h
deleted file mode 100644
index f9d163c425..0000000000
--- a/src/declarative/scenegraph/qsgdefaultglyphnode_p.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DEFAULT_GLYPHNODE_H
-#define DEFAULT_GLYPHNODE_H
-
-#include <private/qsgadaptationlayer_p.h>
-#include <qsgnode.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QGlyphs;
-class QSGTextMaskMaterial;
-class QSGDefaultGlyphNode: public QSGGlyphNode
-{
-public:
- QSGDefaultGlyphNode();
- ~QSGDefaultGlyphNode();
-
- virtual QPointF baseLine() const { return m_baseLine; }
- virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs);
- virtual void setColor(const QColor &color);
-
- virtual void setPreferredAntialiasingMode(AntialiasingMode) { }
- virtual void setStyle(QQuickText::TextStyle) { }
- virtual void setStyleColor(const QColor &) { }
-
- virtual void update() { }
-
-private:
- QGlyphRun m_glyphs;
- QPointF m_position;
- QColor m_color;
-
- QPointF m_baseLine;
- QSGTextMaskMaterial *m_material;
-
- QSGGeometry m_geometry;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // DEFAULT_GLYPHNODE_H
diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h b/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h
deleted file mode 100644
index d22bc33fea..0000000000
--- a/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 TEXTMASKMATERIAL_H
-#define TEXTMASKMATERIAL_H
-
-#include <qcolor.h>
-#include <qsgmaterial.h>
-#include <qsgtexture.h>
-#include <qsggeometry.h>
-#include <qshareddata.h>
-#include <private/qsgtexture_p.h>
-#include <qrawfont.h>
-
-QT_BEGIN_NAMESPACE
-
-class QFontEngineGlyphCache;
-class QOpenGLTextureGlyphCache;
-class QFontEngine;
-class Geometry;
-class QSGTextMaskMaterial: public QSGMaterial
-{
-public:
- QSGTextMaskMaterial(const QRawFont &font);
- ~QSGTextMaskMaterial();
-
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
-
- void setColor(const QColor &color) { m_color = color; }
- const QColor &color() const { return m_color; }
-
- QSGTexture *texture() const { return m_texture; }
-
- int cacheTextureWidth() const;
- int cacheTextureHeight() const;
-
- bool ensureUpToDate();
-
- QOpenGLTextureGlyphCache *glyphCache() const;
- void populate(const QPointF &position,
- const QVector<quint32> &glyphIndexes, const QVector<QPointF> &glyphPositions,
- QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine);
-
-private:
- void init();
-
- QSGPlainTexture *m_texture;
- QExplicitlySharedDataPointer<QFontEngineGlyphCache> m_glyphCache;
- QRawFont m_font;
- QColor m_color;
- QSize m_size;
-};
-
-QT_END_NAMESPACE
-
-#endif // TEXTMASKMATERIAL_H
diff --git a/src/declarative/scenegraph/qsgdefaultimagenode.cpp b/src/declarative/scenegraph/qsgdefaultimagenode.cpp
deleted file mode 100644
index f30a7e2675..0000000000
--- a/src/declarative/scenegraph/qsgdefaultimagenode.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdefaultimagenode_p.h"
-
-#include <private/qsgtextureprovider_p.h>
-
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qmath.h>
-#include <QtGui/qopenglfunctions.h>
-
-QT_BEGIN_NAMESPACE
-
-QSGDefaultImageNode::QSGDefaultImageNode()
- : m_sourceRect(0, 0, 1, 1)
- , m_dirtyGeometry(false)
- , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
-{
- setMaterial(&m_materialO);
- setOpaqueMaterial(&m_material);
- setGeometry(&m_geometry);
-
-#ifdef QML_RUNTIME_TESTING
- description = QLatin1String("image");
-#endif
-}
-
-void QSGDefaultImageNode::setTargetRect(const QRectF &rect)
-{
- if (rect == m_targetRect)
- return;
- m_targetRect = rect;
- m_dirtyGeometry = true;
-}
-
-void QSGDefaultImageNode::setSourceRect(const QRectF &rect)
-{
- if (rect == m_sourceRect)
- return;
- m_sourceRect = rect;
- m_dirtyGeometry = true;
-}
-
-
-void QSGDefaultImageNode::setFiltering(QSGTexture::Filtering filtering)
-{
- if (m_material.filtering() == filtering)
- return;
-
- m_material.setFiltering(filtering);
- m_materialO.setFiltering(filtering);
- markDirty(DirtyMaterial);
-}
-
-
-void QSGDefaultImageNode::setMipmapFiltering(QSGTexture::Filtering filtering)
-{
- if (m_material.mipmapFiltering() == filtering)
- return;
-
- m_material.setMipmapFiltering(filtering);
- m_materialO.setMipmapFiltering(filtering);
- markDirty(DirtyMaterial);
-}
-
-void QSGDefaultImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode)
-{
- if (m_material.verticalWrapMode() == wrapMode)
- return;
-
- m_material.setVerticalWrapMode(wrapMode);
- m_materialO.setVerticalWrapMode(wrapMode);
- markDirty(DirtyMaterial);
-}
-
-void QSGDefaultImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)
-{
- if (m_material.horizontalWrapMode() == wrapMode)
- return;
-
- m_material.setHorizontalWrapMode(wrapMode);
- m_materialO.setHorizontalWrapMode(wrapMode);
- markDirty(DirtyMaterial);
-}
-
-
-void QSGDefaultImageNode::setTexture(QSGTexture *texture)
-{
- if (texture == m_material.texture())
- return;
-
- m_material.setTexture(texture);
- m_materialO.setTexture(texture);
- // Texture cleanup
-// if (!texture.isNull())
-// m_material.setBlending(texture->hasAlphaChannel());
- markDirty(DirtyMaterial);
-
- // Because the texture can be a different part of the atlas, we need to update it...
- m_dirtyGeometry = true;
-}
-
-void QSGDefaultImageNode::update()
-{
- if (m_dirtyGeometry)
- updateGeometry();
-}
-
-void QSGDefaultImageNode::preprocess()
-{
- bool doDirty = false;
- QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
- if (t) {
- doDirty = t->updateTexture();
- updateGeometry();
- }
-// ### texture cleanup
-// bool alpha = m_material.blending();
-// if (!m_material->texture().isNull() && alpha != m_material.texture()->hasAlphaChannel()) {
-// m_material.setBlending(!alpha);
-// doDirty = true;
-// }
-
- if (doDirty)
- markDirty(DirtyMaterial);
-}
-
-inline static bool isPowerOfTwo(int x)
-{
- // Assumption: x >= 1
- return x == (x & -x);
-}
-
-namespace {
- struct X { float x, tx; };
- struct Y { float y, ty; };
-}
-
-void QSGDefaultImageNode::updateGeometry()
-{
- const QSGTexture *t = m_material.texture();
- if (!t) {
- m_geometry.allocate(4);
- m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, QRectF(), QRectF());
- } else {
- QRectF textureRect = t->textureSubRect();
-
- bool isSubRect = textureRect != QRectF(0, 0, 1, 1);
- const int ceilRight = qCeil(m_sourceRect.right());
- const int floorLeft = qFloor(m_sourceRect.left());
- const int ceilBottom = qCeil(m_sourceRect.bottom());
- const int floorTop = qFloor(m_sourceRect.top());
- const int hCells = ceilRight - floorLeft;
- const int vCells = ceilBottom - floorTop;
- bool isRepeating = hCells > 1 || vCells > 1;
-
-#ifdef QT_OPENGL_ES_2
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
-
- QSize size = t->textureSize();
- bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
-
- if (isRepeating && (isSubRect || (isNpot && !npotSupported))) {
-#else
- if (isRepeating && isSubRect) {
-#endif
- m_geometry.allocate(hCells * vCells * 4, hCells * vCells * 6);
- m_geometry.setDrawingMode(GL_TRIANGLES);
- QVarLengthArray<X, 32> xData(2 * hCells);
- QVarLengthArray<Y, 32> yData(2 * vCells);
- X *xs = xData.data();
- Y *ys = yData.data();
-
- xs->x = m_targetRect.left();
- xs->tx = textureRect.x() + (m_sourceRect.left() - floorLeft) * textureRect.width();
- ++xs;
- ys->y = m_targetRect.top();
- ys->ty = textureRect.y() + (m_sourceRect.top() - floorTop) * textureRect.height();
- ++ys;
-
- float a, b;
- b = m_targetRect.width() / m_sourceRect.width();
- a = m_targetRect.x() - m_sourceRect.x() * b;
-
- float tex_x1 = textureRect.x();
- float tex_x2 = textureRect.right();
- float tex_y1 = textureRect.y();
- float tex_y2 = textureRect.bottom();
- for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
- xs[0].x = xs[1].x = a + b * i;
- xs[0].tx = tex_x2;
- xs[1].tx = tex_x1;
- xs += 2;
- }
- b = m_targetRect.height() / m_sourceRect.height();
- a = m_targetRect.y() - m_sourceRect.y() * b;
- for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
- ys[0].y = ys[1].y = a + b * i;
- ys[0].ty = tex_y2;
- ys[1].ty = tex_y1;
- ys += 2;
- }
-
- xs->x = m_targetRect.right();
- xs->tx = textureRect.x() + (m_sourceRect.right() - ceilRight + 1) * textureRect.width();
-
- ys->y = m_targetRect.bottom();
- ys->ty = textureRect.y() + (m_sourceRect.bottom() - ceilBottom + 1) * textureRect.height();
-
- QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D();
- ys = yData.data();
- for (int j = 0; j < vCells; ++j, ys += 2) {
- xs = xData.data();
- for (int i = 0; i < hCells; ++i, xs += 2) {
- vertices[0].x = vertices[2].x = xs[0].x;
- vertices[0].tx = vertices[2].tx = xs[0].tx;
- vertices[1].x = vertices[3].x = xs[1].x;
- vertices[1].tx = vertices[3].tx = xs[1].tx;
-
- vertices[0].y = vertices[1].y = ys[0].y;
- vertices[0].ty = vertices[1].ty = ys[0].ty;
- vertices[2].y = vertices[3].y = ys[1].y;
- vertices[2].ty = vertices[3].ty = ys[1].ty;
-
- vertices += 4;
- }
- }
-
- quint16 *indices = m_geometry.indexDataAsUShort();
- for (int i = 0; i < 4 * vCells * hCells; i += 4) {
- *indices++ = i;
- *indices++ = i + 2;
- *indices++ = i + 3;
- *indices++ = i + 3;
- *indices++ = i + 1;
- *indices++ = i;
- }
- } else {
- QRectF sr(textureRect.x() + m_sourceRect.x() * textureRect.width(),
- textureRect.y() + m_sourceRect.y() * textureRect.height(),
- m_sourceRect.width() * textureRect.width(),
- m_sourceRect.height() * textureRect.height());
-
- m_geometry.allocate(4);
- m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr);
- }
- }
- markDirty(DirtyGeometry);
- m_dirtyGeometry = false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdefaultimagenode_p.h b/src/declarative/scenegraph/qsgdefaultimagenode_p.h
deleted file mode 100644
index db11cd9181..0000000000
--- a/src/declarative/scenegraph/qsgdefaultimagenode_p.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DEFAULT_PIXMAPNODE_H
-#define DEFAULT_PIXMAPNODE_H
-
-#include <private/qsgadaptationlayer_p.h>
-
-#include "qsgtexturematerial.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGDefaultImageNode : public QSGImageNode
-{
-public:
- QSGDefaultImageNode();
- virtual void setTargetRect(const QRectF &rect);
- virtual void setSourceRect(const QRectF &rect);
- virtual void setTexture(QSGTexture *t);
- virtual void update();
-
- virtual void setMipmapFiltering(QSGTexture::Filtering filtering);
- virtual void setFiltering(QSGTexture::Filtering filtering);
- virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode);
- virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode);
-
- virtual void preprocess();
-
-private:
- void updateGeometry();
-
- QRectF m_targetRect;
- QRectF m_sourceRect;
-
- QSGOpaqueTextureMaterial m_material;
- QSGTextureMaterial m_materialO;
-
- uint m_dirtyGeometry : 1;
-
- QSGGeometry m_geometry;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp b/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp
deleted file mode 100644
index 4753b6021e..0000000000
--- a/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdefaultrectanglenode_p.h"
-
-#include <qsgvertexcolormaterial.h>
-#include "qsgtexturematerial.h"
-
-#include <private/qsgcontext_p.h>
-
-#include <QtCore/qmath.h>
-#include <QtCore/qvarlengtharray.h>
-
-QT_BEGIN_NAMESPACE
-
-QSGDefaultRectangleNode::QSGDefaultRectangleNode(QSGContext *context)
- : m_border(0)
- , m_radius(0)
- , m_pen_width(0)
- , m_aligned(true)
- , m_gradient_is_opaque(true)
- , m_dirty_geometry(false)
- , m_default_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
- , m_context(context)
-{
- setGeometry(&m_default_geometry);
- setMaterial(&m_fill_material);
- m_border_material.setColor(QColor(0, 0, 0));
-
- m_material_type = TypeFlat;
-
-#ifdef QML_RUNTIME_TESTING
- description = QLatin1String("rectangle");
-#endif
-}
-
-QSGDefaultRectangleNode::~QSGDefaultRectangleNode()
-{
- if (m_material_type == TypeVertexGradient)
- delete material();
- delete m_border;
-}
-
-QSGGeometryNode *QSGDefaultRectangleNode::border()
-{
- if (!m_border) {
- m_border = new QSGGeometryNode;
- m_border->setMaterial(&m_border_material);
- QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
- m_border->setGeometry(geometry);
- m_border->setFlag(QSGNode::OwnsGeometry);
- }
- return m_border;
-}
-
-void QSGDefaultRectangleNode::setRect(const QRectF &rect)
-{
- if (rect == m_rect)
- return;
- m_rect = rect;
- m_dirty_geometry = true;
-}
-
-void QSGDefaultRectangleNode::setColor(const QColor &color)
-{
- if (color == m_fill_material.color())
- return;
- m_fill_material.setColor(color);
- if (m_gradient_stops.isEmpty()) {
- Q_ASSERT(m_material_type == TypeFlat);
- markDirty(DirtyMaterial);
- }
-}
-
-void QSGDefaultRectangleNode::setPenColor(const QColor &color)
-{
- if (color == m_border_material.color())
- return;
- m_border_material.setColor(color);
- if (m_border)
- m_border->markDirty(DirtyMaterial);
-}
-
-void QSGDefaultRectangleNode::setPenWidth(qreal width)
-{
- if (width == m_pen_width)
- return;
- m_pen_width = width;
- if (m_pen_width <= 0 && m_border && m_border->parent())
- removeChildNode(m_border);
- else if (m_pen_width > 0 && !border()->parent())
- appendChildNode(m_border);
- m_dirty_geometry = true;
-}
-
-
-void QSGDefaultRectangleNode::setGradientStops(const QGradientStops &stops)
-{
- if (stops.constData() == m_gradient_stops.constData())
- return;
-
- m_gradient_stops = stops;
-
- m_gradient_is_opaque = true;
- for (int i = 0; i < stops.size(); ++i)
- m_gradient_is_opaque &= stops.at(i).second.alpha() == 0xff;
-
- if (stops.isEmpty()) {
- // No gradient specified, use flat color.
- if (m_material_type != TypeFlat) {
- delete material();
-
- setMaterial(&m_fill_material);
- m_material_type = TypeFlat;
-
- setGeometry(&m_default_geometry);
- setFlag(OwnsGeometry, false);
- }
- } else {
- if (m_material_type == TypeFlat) {
- QSGVertexColorMaterial *material = new QSGVertexColorMaterial;
- setMaterial(material);
- m_material_type = TypeVertexGradient;
- QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0);
- setGeometry(g);
- setFlag(OwnsGeometry);
- }
- static_cast<QSGVertexColorMaterial *>(material())->setFlag(QSGMaterial::Blending, !m_gradient_is_opaque);
- }
-
- m_dirty_geometry = true;
-}
-
-void QSGDefaultRectangleNode::setRadius(qreal radius)
-{
- if (radius == m_radius)
- return;
- m_radius = radius;
- m_dirty_geometry = true;
-}
-
-void QSGDefaultRectangleNode::setAligned(bool aligned)
-{
- if (aligned == m_aligned)
- return;
- m_aligned = aligned;
- m_dirty_geometry = true;
-}
-
-void QSGDefaultRectangleNode::update()
-{
- if (m_dirty_geometry) {
- updateGeometry();
- m_dirty_geometry = false;
- }
-}
-
-struct Color4ub
-{
- unsigned char r, g, b, a;
-};
-
-Color4ub operator *(Color4ub c, float t) { c.a *= t; c.r *= t; c.g *= t; c.b *= t; return c; }
-Color4ub operator +(Color4ub a, Color4ub b) { a.a += b.a; a.r += b.r; a.g += b.g; a.b += b.b; return a; }
-
-static inline Color4ub colorToColor4ub(const QColor &c)
-{
- Color4ub color = { uchar(c.redF() * c.alphaF() * 255),
- uchar(c.greenF() * c.alphaF() * 255),
- uchar(c.blueF() * c.alphaF() * 255),
- uchar(c.alphaF() * 255)
- };
- return color;
-}
-
-struct Vertex
-{
- QVector2D position;
-};
-
-struct ColorVertex
-{
- QVector2D position;
- Color4ub color;
-};
-
-void QSGDefaultRectangleNode::updateGeometry()
-{
- qreal penWidth = m_aligned ? qreal(qRound(m_pen_width)) : m_pen_width;
-
- // fast path for the simple case...
- if ((penWidth == 0 || m_border_material.color().alpha() == 0)
- && m_radius == 0
- && m_material_type == TypeFlat) {
- QSGGeometry::updateRectGeometry(&m_default_geometry, m_rect);
- return;
- }
-
- QSGGeometry *fill = geometry();
-
- // Check that the vertex type matches the material.
- Q_ASSERT(m_material_type != TypeFlat || fill->sizeOfVertex() == sizeof(Vertex));
- Q_ASSERT(m_material_type != TypeVertexGradient || fill->sizeOfVertex() == sizeof(ColorVertex));
-
- QSGGeometry *borderGeometry = 0;
- if (m_border) {
- borderGeometry = m_border->geometry();
- Q_ASSERT(borderGeometry->sizeOfVertex() == sizeof(Vertex));
- }
-
- int fillVertexCount = 0;
-
- // Preallocate arrays for a rectangle with 18 segments per corner and 3 gradient stops.
- uchar *fillVertices = 0;
- Vertex *borderVertices = 0;
-
- Color4ub fillColor = colorToColor4ub(m_fill_material.color());
- const QGradientStops &stops = m_gradient_stops;
-
- if (m_radius > 0) {
- // Rounded corners.
-
- // Radius should never exceeds half of the width or half of the height
- qreal radius = qMin(qMin(m_rect.width() * qreal(0.5), m_rect.height() * qreal(0.5)), m_radius);
- QRectF innerRect = m_rect;
- innerRect.adjust(radius, radius, -radius, -radius);
- if (m_aligned && (int(penWidth) & 1)) {
- // Pen width is odd, so add the offset as documented.
- innerRect.moveLeft(innerRect.left() + qreal(0.5));
- innerRect.moveTop(innerRect.top() + qreal(0.5));
- }
-
- qreal innerRadius = radius - penWidth * qreal(0.5);
- qreal outerRadius = radius + penWidth * qreal(0.5);
-
- // Number of segments per corner, approximately one per 3 pixels.
- int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18);
-
- /*
-
- --+-__
- | segment
- | _+
- --+-__ _- \
- -+ segment
- --------+ \ <- gradient line
- +-----+
- | |
-
- */
-
- int nextGradientStop = 0;
- qreal gradientPos = (radius - innerRadius) / (innerRect.height() + 2 * radius);
- while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
- ++nextGradientStop;
- int lastGradientStop = stops.size() - 1;
- qreal lastGradientPos = (innerRect.height() + radius + innerRadius) / (innerRect.height() + 2 * radius);
- while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
- --lastGradientStop;
-
- int borderVertexHead = 0;
- int borderVertexTail = 0;
- if (penWidth) {
- // The reason I add extra vertices where the gradient lines intersect the border is
- // to avoid pixel sized gaps between the fill and the border caused by floating point
- // inaccuracies.
- borderGeometry->allocate((segments + 1) * 2 * 4 + (lastGradientStop - nextGradientStop + 1) * 4 + 2);
- borderVertexHead = borderVertexTail = (borderGeometry->vertexCount() >> 1) - 1;
- borderVertices = (Vertex *)borderGeometry->vertexData();
- }
-
- fill->allocate((segments + 1) * 4 + (lastGradientStop - nextGradientStop + 1) * 2);
- fillVertices = (uchar *)fill->vertexData();
-
- qreal py = 0; // previous inner y-coordinate.
- qreal plx = 0; // previous inner left x-coordinate.
- qreal prx = 0; // previous inner right x-coordinate.
-
- qreal angle = qreal(0.5) * M_PI / qreal(segments);
- qreal cosStep = qFastCos(angle);
- qreal sinStep = qFastSin(angle);
-
- for (int part = 0; part < 2; ++part) {
- qreal c = 1 - part;
- qreal s = part;
- for (int i = 0; i <= segments; ++i) {
- qreal y, lx, rx;
- if (innerRadius > 0) {
- y = (part ? innerRect.bottom() : innerRect.top()) - innerRadius * c; // current inner y-coordinate.
- lx = innerRect.left() - innerRadius * s; // current inner left x-coordinate.
- rx = innerRect.right() + innerRadius * s; // current inner right x-coordinate.
- gradientPos = ((part ? innerRect.height() : 0) + radius - innerRadius * c) / (innerRect.height() + 2 * radius);
- } else {
- y = (part ? innerRect.bottom() + innerRadius : innerRect.top() - innerRadius); // current inner y-coordinate.
- lx = innerRect.left() - innerRadius; // current inner left x-coordinate.
- rx = innerRect.right() + innerRadius; // current inner right x-coordinate.
- gradientPos = ((part ? innerRect.height() + innerRadius : -innerRadius) + radius) / (innerRect.height() + 2 * radius);
- }
- qreal Y = (part ? innerRect.bottom() : innerRect.top()) - outerRadius * c; // current outer y-coordinate.
- qreal lX = innerRect.left() - outerRadius * s; // current outer left x-coordinate.
- qreal rX = innerRect.right() + outerRadius * s; // current outer right x-coordinate.
-
- while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
- // Insert vertices at gradient stops.
- qreal gy = (innerRect.top() - radius) + stops.at(nextGradientStop).first * (innerRect.height() + 2 * radius);
- Q_ASSERT(fillVertexCount >= 2);
- qreal t = (gy - py) / (y - py);
- qreal glx = plx * (1 - t) + t * lx;
- qreal grx = prx * (1 - t) + t * rx;
-
- if (penWidth) {
- const Vertex &first = borderVertices[borderVertexHead];
- borderVertices[--borderVertexHead].position = QVector2D(glx, gy);
- borderVertices[--borderVertexHead] = first;
-
- const Vertex &last = borderVertices[borderVertexTail - 2];
- borderVertices[borderVertexTail++] = last;
- borderVertices[borderVertexTail++].position = QVector2D(grx, gy);
- }
-
- ColorVertex *vertices = (ColorVertex *)fillVertices;
-
- fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
- vertices[fillVertexCount].position = QVector2D(grx, gy);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- vertices[fillVertexCount].position = QVector2D(glx, gy);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
-
- ++nextGradientStop;
- }
-
- if (penWidth) {
- borderVertices[--borderVertexHead].position = QVector2D(lx, y);
- borderVertices[--borderVertexHead].position = QVector2D(lX, Y);
- borderVertices[borderVertexTail++].position = QVector2D(rX, Y);
- borderVertices[borderVertexTail++].position = QVector2D(rx, y);
- }
-
- if (stops.isEmpty()) {
- Q_ASSERT(m_material_type == TypeFlat);
- Vertex *vertices = (Vertex *)fillVertices;
- vertices[fillVertexCount++].position = QVector2D(rx, y);
- vertices[fillVertexCount++].position = QVector2D(lx, y);
- } else {
- if (nextGradientStop == 0) {
- fillColor = colorToColor4ub(stops.at(0).second);
- } else if (nextGradientStop == stops.size()) {
- fillColor = colorToColor4ub(stops.last().second);
- } else {
- const QGradientStop &prev = stops.at(nextGradientStop - 1);
- const QGradientStop &next = stops.at(nextGradientStop);
- qreal t = (gradientPos - prev.first) / (next.first - prev.first);
- fillColor = (colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t);
- }
-
- ColorVertex *vertices = (ColorVertex *)fillVertices;
- vertices[fillVertexCount].position = QVector2D(rx, y);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- vertices[fillVertexCount].position = QVector2D(lx, y);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- }
- py = y;
- plx = lx;
- prx = rx;
-
- // Rotate
- qreal tmp = c;
- c = c * cosStep - s * sinStep;
- s = s * cosStep + tmp * sinStep;
- }
- }
-
- if (penWidth) {
- // Close border.
- const Vertex &first = borderVertices[borderVertexHead];
- const Vertex &second = borderVertices[borderVertexHead + 1];
- borderVertices[borderVertexTail++] = first;
- borderVertices[borderVertexTail++] = second;
-
- Q_ASSERT(borderVertexHead == 0 && borderVertexTail == borderGeometry->vertexCount());
- }
- Q_ASSERT(fillVertexCount == fill->vertexCount());
-
- } else {
-
- // Straight corners.
- QRectF innerRect = m_rect;
- QRectF outerRect = m_rect;
-
- qreal halfPenWidth = 0;
- if (penWidth) {
- if (m_aligned && (int(penWidth) & 1)) {
- // Pen width is odd, so add the offset as documented.
- innerRect.moveLeft(innerRect.left() + qreal(0.5));
- innerRect.moveTop(innerRect.top() + qreal(0.5));
- outerRect = innerRect;
- }
- halfPenWidth = penWidth * qreal(0.5);
- innerRect.adjust(halfPenWidth, halfPenWidth, -halfPenWidth, -halfPenWidth);
- outerRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
- }
-
- int nextGradientStop = 0;
- qreal gradientPos = halfPenWidth / m_rect.height();
- while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
- ++nextGradientStop;
- int lastGradientStop = stops.size() - 1;
- qreal lastGradientPos = (m_rect.height() - halfPenWidth) / m_rect.height();
- while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
- --lastGradientStop;
-
- int borderVertexCount = 0;
- if (penWidth) {
- borderGeometry->allocate((1 + lastGradientStop - nextGradientStop) * 4 + 10);
- borderVertices = (Vertex *)borderGeometry->vertexData();
- }
- fill->allocate((3 + lastGradientStop - nextGradientStop) * 2);
- fillVertices = (uchar *)fill->vertexData();
-
- QVarLengthArray<qreal, 16> ys(3 + lastGradientStop - nextGradientStop);
- int yCount = 0;
-
- for (int part = 0; part < 2; ++part) {
- qreal y = (part ? innerRect.bottom() : innerRect.top());
- gradientPos = (y - innerRect.top() + halfPenWidth) / m_rect.height();
-
- while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
- // Insert vertices at gradient stops.
- qreal gy = (innerRect.top() - halfPenWidth) + stops.at(nextGradientStop).first * m_rect.height();
- Q_ASSERT(fillVertexCount >= 2);
-
- ColorVertex *vertices = (ColorVertex *)fillVertices;
-
- fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
- vertices[fillVertexCount].position = QVector2D(innerRect.right(), gy);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- vertices[fillVertexCount].position = QVector2D(innerRect.left(), gy);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
-
- ys[yCount++] = gy;
-
- ++nextGradientStop;
- }
-
- if (stops.isEmpty()) {
- Q_ASSERT(m_material_type == TypeFlat);
- Vertex *vertices = (Vertex *)fillVertices;
- vertices[fillVertexCount++].position = QVector2D(innerRect.right(), y);
- vertices[fillVertexCount++].position = QVector2D(innerRect.left(), y);
- } else {
- if (nextGradientStop == 0) {
- fillColor = colorToColor4ub(stops.at(0).second);
- } else if (nextGradientStop == stops.size()) {
- fillColor = colorToColor4ub(stops.last().second);
- } else {
- const QGradientStop &prev = stops.at(nextGradientStop - 1);
- const QGradientStop &next = stops.at(nextGradientStop);
- qreal t = (gradientPos - prev.first) / (next.first - prev.first);
- fillColor = (colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t);
- }
-
- ColorVertex *vertices = (ColorVertex *)fillVertices;
- vertices[fillVertexCount].position = QVector2D(innerRect.right(), y);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- vertices[fillVertexCount].position = QVector2D(innerRect.left(), y);
- vertices[fillVertexCount].color = fillColor;
- ++fillVertexCount;
- }
-
- ys[yCount++] = y;
- }
-
- if (penWidth) {
- borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.top());
- borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), ys[0]);
- for (int i = 1; i < fillVertexCount / 2; ++i) {
- borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.bottom());
- borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), ys[i]);
- }
-
- borderVertices[borderVertexCount++].position = QVector2D(outerRect.left(), outerRect.bottom());
- borderVertices[borderVertexCount++].position = QVector2D(innerRect.left(), ys[fillVertexCount / 2 - 1]);
- for (int i = fillVertexCount / 2 - 2; i >= 0; --i) {
- borderVertices[borderVertexCount++].position = QVector2D(outerRect.left(), outerRect.top());
- borderVertices[borderVertexCount++].position = QVector2D(innerRect.left(), ys[i]);
- }
-
- borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.top());
- borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), innerRect.top());
-
- Q_ASSERT(borderVertexCount == borderGeometry->vertexCount());
- }
- Q_ASSERT(fillVertexCount == fill->vertexCount());
- }
-
- markDirty(DirtyGeometry);
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdefaultrectanglenode_p.h b/src/declarative/scenegraph/qsgdefaultrectanglenode_p.h
deleted file mode 100644
index 6a197136cf..0000000000
--- a/src/declarative/scenegraph/qsgdefaultrectanglenode_p.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DEFAULT_RECTANGLENODE_H
-#define DEFAULT_RECTANGLENODE_H
-
-#include <private/qsgadaptationlayer_p.h>
-
-#include "qsgflatcolormaterial.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGMaterial;
-class QSGContext;
-
-class QSGDefaultRectangleNode : public QSGRectangleNode
-{
-public:
- QSGDefaultRectangleNode(QSGContext *context);
- ~QSGDefaultRectangleNode();
-
- virtual void setRect(const QRectF &rect);
- virtual void setColor(const QColor &color);
- virtual void setPenColor(const QColor &color);
- virtual void setPenWidth(qreal width);
- virtual void setGradientStops(const QGradientStops &stops);
- virtual void setRadius(qreal radius);
- virtual void setAligned(bool aligned);
- virtual void update();
-
-private:
- enum {
- TypeFlat,
- TypeVertexGradient
- };
- QSGGeometryNode *border();
-
- void updateGeometry();
- void updateGradientTexture();
-
- QSGGeometryNode *m_border;
- QSGFlatColorMaterial m_border_material;
- QSGFlatColorMaterial m_fill_material;
-
- QRectF m_rect;
- QGradientStops m_gradient_stops;
- qreal m_radius;
- qreal m_pen_width;
-
- uint m_aligned : 1;
- uint m_gradient_is_opaque : 1;
- uint m_dirty_geometry : 1;
-
- uint m_material_type : 2; // Only goes up to 3
-
- QSGGeometry m_default_geometry;
-
- QSGContext *m_context;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
deleted file mode 100644
index e4a39e484b..0000000000
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdistancefieldglyphnode_p.h"
-#include "qsgdistancefieldglyphnode_p_p.h"
-#include <private/qsgdistancefieldutil_p.h>
-#include <private/qsgcontext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager)
- : m_material(0)
- , m_glyph_cacheManager(cacheManager)
- , m_glyph_cache(0)
- , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
- , m_style(QQuickText::Normal)
- , m_antialiasingMode(GrayAntialiasing)
- , m_dirtyGeometry(false)
- , m_dirtyMaterial(false)
-{
- m_geometry.setDrawingMode(GL_TRIANGLES);
- setGeometry(&m_geometry);
- setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode());
-#ifdef QML_RUNTIME_TESTING
- description = QLatin1String("glyphs");
-#endif
-}
-
-QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
-{
- delete m_material;
- if (m_glyph_cache) {
- m_glyph_cache->release(m_glyphs.glyphIndexes());
- m_glyph_cache->unregisterGlyphNode(this);
- }
-}
-
-void QSGDistanceFieldGlyphNode::setColor(const QColor &color)
-{
- m_color = color;
- if (m_material != 0) {
- m_material->setColor(color);
- markDirty(DirtyMaterial);
- }
-}
-
-void QSGDistanceFieldGlyphNode::setPreferredAntialiasingMode(AntialiasingMode mode)
-{
- if (mode == m_antialiasingMode)
- return;
- m_antialiasingMode = mode;
- m_dirtyMaterial = true;
-}
-
-void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
-{
- QRawFont font = glyphs.rawFont();
- m_position = QPointF(position.x(), position.y() - font.ascent());
- m_glyphs = glyphs;
-
- QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
- m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
- if (m_glyph_cache != oldCache) {
- if (oldCache)
- oldCache->unregisterGlyphNode(this);
- m_glyph_cache->registerGlyphNode(this);
- }
- m_glyph_cache->populate(glyphs.glyphIndexes());
-
- const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
- const QVector<QPointF> &glyphPositions = m_glyphs.positions();
- for (int i = 0; i < glyphIndexes.size(); ++i) {
- GlyphInfo g;
- g.glyphIndex = glyphIndexes.at(i);
- g.position = glyphPositions.at(i);
- m_glyphsToAdd.append(g);
- }
-
- m_dirtyGeometry = true;
- m_dirtyMaterial = true;
-}
-
-void QSGDistanceFieldGlyphNode::setStyle(QQuickText::TextStyle style)
-{
- if (m_style == style)
- return;
- m_style = style;
- m_dirtyMaterial = true;
-}
-
-void QSGDistanceFieldGlyphNode::setStyleColor(const QColor &color)
-{
- if (m_styleColor == color)
- return;
- m_styleColor = color;
- m_dirtyMaterial = true;
-}
-
-void QSGDistanceFieldGlyphNode::update()
-{
- if (m_dirtyMaterial)
- updateMaterial();
- if (m_dirtyGeometry)
- updateGeometry();
-}
-
-void QSGDistanceFieldGlyphNode::updateGeometry()
-{
- Q_ASSERT(m_glyph_cache);
-
- if (m_glyphsToAdd.isEmpty())
- return;
-
- QSGGeometry *g = geometry();
-
- Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT);
-
- int oldVertexCount = g->vertexCount();
- int oldIndexCount = g->indexCount();
-
- QVector<QSGGeometry::TexturedPoint2D> vp;
- vp.reserve(m_glyphsToAdd.size() * 4);
- QVector<ushort> ip;
- ip.reserve(m_glyphsToAdd.size() * 6);
-
- QPointF margins(2, 2);
- QPointF texMargins = margins / m_glyph_cache->fontScale();
-
- const QSGDistanceFieldGlyphCache::Texture *textureToUse = 0;
-
- QLinkedList<GlyphInfo>::iterator it = m_glyphsToAdd.begin();
- while (it != m_glyphsToAdd.end()) {
- quint32 glyphIndex = it->glyphIndex;
- QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
-
- if (c.isNull()) {
- if (!c.isValid())
- ++it;
- else
- it = m_glyphsToAdd.erase(it);
- continue;
- }
-
- const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
- if (!texture->textureId) {
- ++it;
- continue;
- }
-
- QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
-
- if (!textureToUse)
- textureToUse = texture;
-
- metrics.width += margins.x() * 2;
- metrics.height += margins.y() * 2;
- metrics.baselineX -= margins.x();
- metrics.baselineY += margins.y();
- c.xMargin -= texMargins.x();
- c.yMargin -= texMargins.y();
- c.width += texMargins.x() * 2;
- c.height += texMargins.y() * 2;
-
- const QPointF &glyphPosition = it->position;
- qreal x = glyphPosition.x() + metrics.baselineX + m_position.x();
- qreal y = glyphPosition.y() - metrics.baselineY + m_position.y();
-
- m_boundingRect |= QRectF(x, y, metrics.width, metrics.height);
-
- float cx1 = x;
- float cx2 = x + metrics.width;
- float cy1 = y;
- float cy2 = y + metrics.height;
-
- float tx1 = c.x + c.xMargin;
- float tx2 = tx1 + c.width;
- float ty1 = c.y + c.yMargin;
- float ty2 = ty1 + c.height;
-
- if (m_baseLine.isNull())
- m_baseLine = glyphPosition;
-
- int i = vp.size();
-
- QSGGeometry::TexturedPoint2D v1;
- v1.set(cx1, cy1, tx1, ty1);
- QSGGeometry::TexturedPoint2D v2;
- v2.set(cx2, cy1, tx2, ty1);
- QSGGeometry::TexturedPoint2D v3;
- v3.set(cx1, cy2, tx1, ty2);
- QSGGeometry::TexturedPoint2D v4;
- v4.set(cx2, cy2, tx2, ty2);
- vp.append(v1);
- vp.append(v2);
- vp.append(v3);
- vp.append(v4);
-
- int o = i + oldVertexCount;
- ip.append(o + 0);
- ip.append(o + 2);
- ip.append(o + 3);
- ip.append(o + 3);
- ip.append(o + 1);
- ip.append(o + 0);
-
- it = m_glyphsToAdd.erase(it);
- }
-
- if (vp.isEmpty())
- return;
-
- void *data = 0;
- if (oldVertexCount && oldIndexCount) {
- int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)
- + oldIndexCount * sizeof(quint16);
- data = qMalloc(byteSize);
- memcpy(data, g->vertexData(), byteSize);
- }
-
- g->allocate(oldVertexCount + vp.size(), oldIndexCount + ip.size());
-
- if (data) {
- memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D));
- memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D),
- oldIndexCount * sizeof(quint16));
- qFree(data);
- }
-
- memcpy(g->vertexDataAsTexturedPoint2D() + oldVertexCount, vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
- memcpy(g->indexDataAsUShort() + oldIndexCount, ip.constData(), ip.size() * sizeof(quint16));
-
- setBoundingRect(m_boundingRect);
- markDirty(DirtyGeometry);
- m_dirtyGeometry = false;
-
- m_material->setTexture(textureToUse);
-}
-
-void QSGDistanceFieldGlyphNode::updateMaterial()
-{
- delete m_material;
-
- if (m_style == QQuickText::Normal) {
- switch (m_antialiasingMode) {
- case HighQualitySubPixelAntialiasing:
- m_material = new QSGHiQSubPixelDistanceFieldTextMaterial;
- break;
- case LowQualitySubPixelAntialiasing:
- m_material = new QSGLoQSubPixelDistanceFieldTextMaterial;
- break;
- case GrayAntialiasing:
- default:
- m_material = new QSGDistanceFieldTextMaterial;
- break;
- }
- } else {
- QSGDistanceFieldStyledTextMaterial *material;
- if (m_style == QQuickText::Outline) {
- material = new QSGDistanceFieldOutlineTextMaterial;
- } else {
- QSGDistanceFieldShiftedStyleTextMaterial *sMaterial = new QSGDistanceFieldShiftedStyleTextMaterial;
- if (m_style == QQuickText::Raised)
- sMaterial->setShift(QPointF(0.0, 1.0));
- else
- sMaterial->setShift(QPointF(0.0, -1.0));
- material = sMaterial;
- }
- material->setStyleColor(m_styleColor);
- m_material = material;
- }
-
- m_material->setGlyphCache(m_glyph_cache);
- m_material->setColor(m_color);
- setMaterial(m_material);
- m_dirtyMaterial = false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
deleted file mode 100644
index a506e23cc1..0000000000
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ /dev/null
@@ -1,725 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdistancefieldglyphnode_p_p.h"
-#include <private/qsgdistancefieldutil_p.h>
-#include <private/qsgtexture_p.h>
-#include <QtGui/qopenglfunctions.h>
-#include <qmath.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader
-{
-public:
- QSGDistanceFieldTextMaterialShader();
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-
-protected:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
-
- float m_fontScale;
- float m_matrixScale;
-
- int m_matrix_id;
- int m_textureScale_id;
- int m_alphaMin_id;
- int m_alphaMax_id;
- int m_color_id;
-};
-
-const char *QSGDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform highp float alphaMin; \n"
- "uniform highp float alphaMax; \n"
- "void main() { \n"
- " gl_FragColor = color * smoothstep(alphaMin, \n"
- " alphaMax, \n"
- " texture2D(texture, sampleCoord).a); \n"
- "}";
-}
-
-char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const {
- static char const *const attr[] = { "vCoord", "tCoord", 0 };
- return attr;
-}
-
-QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
- : m_fontScale(1.0)
- , m_matrixScale(1.0)
-{
-}
-
-void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
-{
- float combinedScale = m_fontScale * m_matrixScale;
- float base = thresholdFunc(combinedScale);
- float range = spreadFunc(combinedScale);
-
- float alphaMin = qMax(0.0f, base - range);
- float alphaMax = qMin(base + range, 1.0f);
- program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
- program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
-}
-
-void QSGDistanceFieldTextMaterialShader::initialize()
-{
- QSGMaterialShader::initialize();
- m_matrix_id = program()->uniformLocation("matrix");
- m_textureScale_id = program()->uniformLocation("textureScale");
- m_color_id = program()->uniformLocation("color");
- m_alphaMin_id = program()->uniformLocation("alphaMin");
- m_alphaMax_id = program()->uniformLocation("alphaMax");
-}
-
-void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
- QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
- QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
-
- bool updated = material->updateCache();
-
- if (oldMaterial == 0
- || material->color() != oldMaterial->color()
- || state.isOpacityDirty()) {
- QVector4D color(material->color().redF(), material->color().greenF(),
- material->color().blueF(), material->color().alphaF());
- color *= state.opacity();
- program()->setUniformValue(m_color_id, color);
- }
-
- bool updateRange = false;
- if (oldMaterial == 0
- || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()) {
- m_fontScale = material->glyphCache()->fontScale();
- updateRange = true;
- }
- if (state.isMatrixDirty()) {
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
- m_matrixScale = qSqrt(qAbs(state.modelViewMatrix().determinant()));
- updateRange = true;
- }
- if (updateRange) {
- updateAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
- material->glyphCache()->manager()->antialiasingSpreadFunc());
- }
-
- Q_ASSERT(material->glyphCache());
-
- if (updated
- || oldMaterial == 0
- || oldMaterial->texture()->textureId != material->texture()->textureId) {
- program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->textureSize().width(),
- 1.0 / material->textureSize().height()));
- glBindTexture(GL_TEXTURE_2D, material->texture()->textureId);
-
- if (updated) {
- // Set the mag/min filters to be linear. We only need to do this when the texture
- // has been recreated.
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
-}
-
-QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
- : m_glyph_cache(0)
- , m_texture(0)
-{
- setFlag(Blending, true);
-}
-
-QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
-{
-}
-
-QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
-{
- return new QSGDistanceFieldTextMaterialShader;
-}
-
-bool QSGDistanceFieldTextMaterial::updateCache()
-{
- m_glyph_cache->update();
- if (!m_texture)
- m_texture = m_glyph_cache->glyphTexture(-1); // invalid texture
- QSize glyphCacheSize = m_texture->size;
- if (glyphCacheSize != m_size) {
- m_size = glyphCacheSize;
-
- return true;
- } else {
- return false;
- }
-}
-
-int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
-{
- Q_ASSERT(o && type() == o->type());
- 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);
- }
- QRgb c1 = m_color.rgba();
- QRgb c2 = other->m_color.rgba();
- return int(c2 < c1) - int(c1 < c2);
-}
-
-
-class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMaterialShader
-{
-public:
- DistanceFieldStyledTextMaterialShader();
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
-
-protected:
- virtual void initialize();
- virtual const char *fragmentShader() const = 0;
-
- int m_styleColor_id;
-};
-
-DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
- : QSGDistanceFieldTextMaterialShader()
-{
-}
-
-void DistanceFieldStyledTextMaterialShader::initialize()
-{
- QSGDistanceFieldTextMaterialShader::initialize();
- m_styleColor_id = program()->uniformLocation("styleColor");
-}
-
-void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
-
- QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect);
- QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect);
-
- if (oldMaterial == 0
- || material->styleColor() != oldMaterial->styleColor()
- || (state.isOpacityDirty())) {
- QVector4D color(material->styleColor().redF(), material->styleColor().greenF(),
- material->styleColor().blueF(), material->styleColor().alphaF());
- color *= state.opacity();
- program()->setUniformValue(m_styleColor_id, color);
- }
-}
-
-QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
- : QSGDistanceFieldTextMaterial()
-{
-}
-
-QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
-{
-}
-
-int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
-{
- Q_ASSERT(o && type() == o->type());
- const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o);
- if (m_styleColor != other->m_styleColor) {
- QRgb c1 = m_styleColor.rgba();
- QRgb c2 = other->m_styleColor.rgba();
- return int(c2 < c1) - int(c1 < c2);
- }
- return QSGDistanceFieldTextMaterial::compare(o);
-}
-
-
-class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader
-{
-public:
- DistanceFieldOutlineTextMaterialShader();
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
-
-protected:
- virtual void initialize();
- virtual const char *fragmentShader() const;
-
- void updateOutlineAlphaRange(int dfRadius);
-
- int m_outlineAlphaMax0_id;
- int m_outlineAlphaMax1_id;
-};
-
-const char *DistanceFieldOutlineTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "uniform highp float alphaMin; \n"
- "uniform highp float alphaMax; \n"
- "uniform highp float outlineAlphaMax0; \n"
- "uniform highp float outlineAlphaMax1; \n"
- "void main() { \n"
- " mediump float d = texture2D(texture, sampleCoord).a; \n"
- " gl_FragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d)) \n"
- " * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d); \n"
- "}";
-}
-
-DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
- : DistanceFieldStyledTextMaterialShader()
-{
-}
-
-void DistanceFieldOutlineTextMaterialShader::initialize()
-{
- DistanceFieldStyledTextMaterialShader::initialize();
- m_outlineAlphaMax0_id = program()->uniformLocation("outlineAlphaMax0");
- m_outlineAlphaMax1_id = program()->uniformLocation("outlineAlphaMax1");
-}
-
-void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius)
-{
- qreal outlineLimit = qMax(qreal(0.2), qreal(0.5 - 0.5 / dfRadius / m_fontScale));
-
- qreal combinedScale = m_fontScale * m_matrixScale;
- qreal alphaMin = qMax(0.0, 0.5 - 0.07 / combinedScale);
- qreal styleAlphaMin0 = qMax(0.0, outlineLimit - 0.07 / combinedScale);
- qreal styleAlphaMin1 = qMin(qreal(outlineLimit + 0.07 / combinedScale), alphaMin);
- program()->setUniformValue(m_outlineAlphaMax0_id, GLfloat(styleAlphaMin0));
- program()->setUniformValue(m_outlineAlphaMax1_id, GLfloat(styleAlphaMin1));
-}
-
-void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
-
- QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect);
- QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect);
-
- if (oldMaterial == 0
- || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()
- || state.isMatrixDirty())
- updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
-}
-
-
-QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
- : QSGDistanceFieldStyledTextMaterial()
-{
-}
-
-QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial()
-{
-}
-
-QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const
-{
- return new DistanceFieldOutlineTextMaterialShader;
-}
-
-
-class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader
-{
-public:
- DistanceFieldShiftedStyleTextMaterialShader();
-
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
-
-protected:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- void updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF& shift);
-
- int m_shift_id;
-};
-
-DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
- : DistanceFieldStyledTextMaterialShader()
-{
-}
-
-void DistanceFieldShiftedStyleTextMaterialShader::initialize()
-{
- DistanceFieldStyledTextMaterialShader::initialize();
- m_shift_id = program()->uniformLocation("shift");
-}
-
-void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
-
- QSGDistanceFieldShiftedStyleTextMaterial *material = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newEffect);
- QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect);
-
- if (oldMaterial == 0
- || oldMaterial->glyphCache()->fontScale() != material->glyphCache()->fontScale()
- || oldMaterial->shift() != material->shift()
- || oldMaterial->textureSize() != material->textureSize()) {
- updateShift(material->glyphCache(), material->shift());
- }
-}
-
-void DistanceFieldShiftedStyleTextMaterialShader::updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF &shift)
-{
- QPointF texel(1.0 / cache->fontScale() * shift.x(),
- 1.0 / cache->fontScale() * shift.y());
- program()->setUniformValue(m_shift_id, texel);
-}
-
-const char *DistanceFieldShiftedStyleTextMaterialShader::vertexShader() const
-{
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "uniform highp vec2 shift; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *DistanceFieldShiftedStyleTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "uniform highp float alphaMin; \n"
- "uniform highp float alphaMax; \n"
- "void main() { \n"
- " highp float a = smoothstep(alphaMin, alphaMax, texture2D(texture, sampleCoord).a);\n"
- " highp vec4 shifted = styleColor * smoothstep(alphaMin, \n"
- " alphaMax, \n"
- " texture2D(texture, shiftedSampleCoord).a); \n"
- " gl_FragColor = mix(shifted, color, a); \n"
- "}";
-}
-
-QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
- : QSGDistanceFieldStyledTextMaterial()
-{
-}
-
-QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial()
-{
-}
-
-QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const
-{
- return new DistanceFieldShiftedStyleTextMaterialShader;
-}
-
-
-class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
-{
-public:
- virtual void initialize();
- virtual void activate();
- virtual void deactivate();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
-
-protected:
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
-private:
- int m_fontScale_id;
- int m_vecDelta_id;
-};
-
-const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp float fontScale; \n"
- "uniform highp vec4 vecDelta; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec3 sampleFarLeft; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "varying highp vec3 sampleFarRight; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- // Calculate neighbour pixel position in item space.
- " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
- " highp vec3 farLeft = vCoord.xyw - 0.667 * wDelta; \n"
- " highp vec3 nearLeft = vCoord.xyw - 0.333 * wDelta; \n"
- " highp vec3 nearRight = vCoord.xyw + 0.333 * wDelta; \n"
- " highp vec3 farRight = vCoord.xyw + 0.667 * wDelta; \n"
- // Calculate neighbour texture coordinate.
- " highp vec2 scale = textureScale / fontScale; \n"
- " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
- " sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z); \n"
- " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
- " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
- " sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z); \n"
- "}";
-}
-
-const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec3 sampleFarLeft; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "varying highp vec3 sampleFarRight; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform highp float alphaMin; \n"
- "uniform highp float alphaMax; \n"
- "void main() { \n"
- " highp vec4 n; \n"
- " n.x = texture2DProj(texture, sampleFarLeft).a; \n"
- " n.y = texture2DProj(texture, sampleNearLeft).a; \n"
- " highp float c = texture2D(texture, sampleCoord).a; \n"
- " n.z = texture2DProj(texture, sampleNearRight).a; \n"
- " n.w = texture2DProj(texture, sampleFarRight).a; \n"
-#if 0
- // Blurrier, faster.
- " n = smoothstep(alphaMin, alphaMax, n); \n"
- " c = smoothstep(alphaMin, alphaMax, c); \n"
-#else
- // Sharper, slower.
- " highp vec2 d = min(abs(n.yw - n.xz) * 2., 0.67); \n"
- " highp vec2 lo = mix(vec2(alphaMin), vec2(0.5), d); \n"
- " highp vec2 hi = mix(vec2(alphaMax), vec2(0.5), d); \n"
- " n = smoothstep(lo.xxyy, hi.xxyy, n); \n"
- " c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c); \n"
-#endif
- " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
- "}";
-}
-
-//const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
-// return
-// "#extension GL_OES_standard_derivatives: enable \n"
-// "varying highp vec2 sampleCoord; \n"
-// "uniform sampler2D texture; \n"
-// "uniform lowp vec4 color; \n"
-// "uniform highp float alphaMin; \n"
-// "uniform highp float alphaMax; \n"
-// "void main() { \n"
-// " highp vec2 delta = dFdx(sampleCoord); \n"
-// " highp vec4 n; \n"
-// " n.x = texture2D(texture, sampleCoord - 0.667 * delta).a; \n"
-// " n.y = texture2D(texture, sampleCoord - 0.333 * delta).a; \n"
-// " highp float c = texture2D(texture, sampleCoord).a; \n"
-// " n.z = texture2D(texture, sampleCoord + 0.333 * delta).a; \n"
-// " n.w = texture2D(texture, sampleCoord + 0.667 * delta).a; \n"
-// " n = smoothstep(alphaMin, alphaMax, n); \n"
-// " c = smoothstep(alphaMin, alphaMax, c); \n"
-// " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
-// "}";
-//}
-
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
-{
- QSGDistanceFieldTextMaterialShader::initialize();
- m_fontScale_id = program()->uniformLocation("fontScale");
- m_vecDelta_id = program()->uniformLocation("vecDelta");
-}
-
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate()
-{
- QSGDistanceFieldTextMaterialShader::activate();
- glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
-}
-
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate()
-{
- QSGDistanceFieldTextMaterialShader::deactivate();
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-}
-
-void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
- QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
- QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
-
- if (oldMaterial == 0 || material->color() != oldMaterial->color()) {
- QColor c = material->color();
- 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 || state.isMatrixDirty()) {
- int viewportWidth = state.viewportRect().width();
- QMatrix4x4 mat = state.combinedMatrix().inverted();
- program()->setUniformValue(m_vecDelta_id, mat.column(0) * (qreal(2) / viewportWidth));
- }
-
- QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
-}
-
-QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
-{
- return new QSGHiQSubPixelDistanceFieldTextMaterialShader;
-}
-
-
-class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
-{
-protected:
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-};
-
-const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp float fontScale; \n"
- "uniform highp vec4 vecDelta; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "void main() { \n"
- " highp vec2 sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- // Calculate neighbour pixel position in item space.
- " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
- " highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta; \n"
- " highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta; \n"
- // Calculate neighbour texture coordinate.
- " highp vec2 scale = textureScale / fontScale; \n"
- " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
- " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
- " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
- "}";
-}
-
-const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "uniform sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform highp float alphaMin; \n"
- "uniform highp float alphaMax; \n"
- "void main() { \n"
- " highp vec2 n; \n"
- " n.x = texture2DProj(texture, sampleNearLeft).a; \n"
- " n.y = texture2DProj(texture, sampleNearRight).a; \n"
- " n = smoothstep(alphaMin, alphaMax, n); \n"
- " highp float c = 0.5 * (n.x + n.y); \n"
- " gl_FragColor = vec4(n.x, c, n.y, c) * color.w; \n"
- "}";
-}
-
-QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const
-{
- return new QSGLoQSubPixelDistanceFieldTextMaterialShader;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
deleted file mode 100644
index f4877b0a1d..0000000000
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DISTANCEFIELD_GLYPHNODE_H
-#define DISTANCEFIELD_GLYPHNODE_H
-
-#include <private/qsgadaptationlayer_p.h>
-#include "qsgtexture.h"
-
-#include <private/qquicktext_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGDistanceFieldGlyphCacheManager;
-class QSGDistanceFieldTextMaterial;
-class QSGDistanceFieldGlyphNode: public QSGGlyphNode
-{
-public:
- QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager);
- ~QSGDistanceFieldGlyphNode();
-
- virtual QPointF baseLine() const { return m_baseLine; }
- virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs);
- virtual void setColor(const QColor &color);
-
- virtual void setPreferredAntialiasingMode(AntialiasingMode mode);
-
- virtual void setStyle(QQuickText::TextStyle style);
- virtual void setStyleColor(const QColor &color);
-
- virtual void update();
-
- void updateGeometry();
-
-private:
- void updateMaterial();
-
- QColor m_color;
- QPointF m_baseLine;
- QSGDistanceFieldTextMaterial *m_material;
- QPointF m_position;
- QGlyphRun m_glyphs;
- QSGDistanceFieldGlyphCacheManager *m_glyph_cacheManager;
- QSGDistanceFieldGlyphCache *m_glyph_cache;
- QSGGeometry m_geometry;
- QQuickText::TextStyle m_style;
- QColor m_styleColor;
- AntialiasingMode m_antialiasingMode;
- QRectF m_boundingRect;
-
- struct GlyphInfo {
- quint32 glyphIndex;
- QPointF position;
- };
- QLinkedList<GlyphInfo> m_glyphsToAdd;
-
- uint m_dirtyGeometry: 1;
- uint m_dirtyMaterial: 1;
-};
-
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // DISTANCEFIELD_GLYPHNODE_H
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
deleted file mode 100644
index c8c73bfac0..0000000000
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 DISTANCEFIELDTEXTMATERIAL_H
-#define DISTANCEFIELDTEXTMATERIAL_H
-
-#include <qsgmaterial.h>
-#include "qsgdistancefieldglyphnode_p.h"
-#include "qsgadaptationlayer_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QSGDistanceFieldTextMaterial: public QSGMaterial
-{
-public:
- QSGDistanceFieldTextMaterial();
- ~QSGDistanceFieldTextMaterial();
-
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
-
- void setColor(const QColor &color) { m_color = color; }
- const QColor &color() const { return m_color; }
-
- void setGlyphCache(QSGDistanceFieldGlyphCache *a) { m_glyph_cache = a; }
- QSGDistanceFieldGlyphCache *glyphCache() const { return m_glyph_cache; }
-
- void setTexture(const QSGDistanceFieldGlyphCache::Texture * tex) { m_texture = tex; }
- const QSGDistanceFieldGlyphCache::Texture * texture() const { return m_texture; }
-
- QSize textureSize() const { return m_size; }
-
- bool updateCache();
-
-protected:
- QSize m_size;
- QColor m_color;
- QSGDistanceFieldGlyphCache *m_glyph_cache;
- const QSGDistanceFieldGlyphCache::Texture *m_texture;
-};
-
-class QSGDistanceFieldStyledTextMaterial : public QSGDistanceFieldTextMaterial
-{
-public:
- QSGDistanceFieldStyledTextMaterial();
- ~QSGDistanceFieldStyledTextMaterial();
-
- virtual QSGMaterialType *type() const = 0;
- virtual QSGMaterialShader *createShader() const = 0;
- virtual int compare(const QSGMaterial *other) const;
-
- void setStyleColor(const QColor &color) { m_styleColor = color; }
- const QColor &styleColor() const { return m_styleColor; }
-
-protected:
- QColor m_styleColor;
-};
-
-class QSGDistanceFieldOutlineTextMaterial : public QSGDistanceFieldStyledTextMaterial
-{
-public:
- QSGDistanceFieldOutlineTextMaterial();
- ~QSGDistanceFieldOutlineTextMaterial();
-
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-};
-
-class QSGDistanceFieldShiftedStyleTextMaterial : public QSGDistanceFieldStyledTextMaterial
-{
-public:
- QSGDistanceFieldShiftedStyleTextMaterial();
- ~QSGDistanceFieldShiftedStyleTextMaterial();
-
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-
- void setShift(const QPointF &shift) { m_shift = shift; }
- const QPointF &shift() const { return m_shift; }
-
-protected:
- QPointF m_shift;
-};
-
-class QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
-{
-public:
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-};
-
-class QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
-{
-public:
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-};
-
-QT_END_NAMESPACE
-
-#endif // DISTANCEFIELDTEXTMATERIAL_H
diff --git a/src/declarative/scenegraph/qsgflashnode_p.h b/src/declarative/scenegraph/qsgflashnode_p.h
deleted file mode 100644
index 0967fa8901..0000000000
--- a/src/declarative/scenegraph/qsgflashnode_p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGFLASHNODE_H
-#define QSGFLASHNODE_H
-
-#include <QSGSimpleRectNode>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGFlashNode : public QSGSimpleRectNode
-{
-public:
- QSGFlashNode();
-
- void preprocess();
-
-private:
- int m_counter;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGFLASHNODE_H
-
diff --git a/src/declarative/scenegraph/util/qsgareaallocator_p.h b/src/declarative/scenegraph/util/qsgareaallocator_p.h
deleted file mode 100644
index fd79d4c67a..0000000000
--- a/src/declarative/scenegraph/util/qsgareaallocator_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 AREAALLOCATOR_H
-#define AREAALLOCATOR_H
-
-#include <QtCore/qsize.h>
-
-QT_BEGIN_NAMESPACE
-
-class QRect;
-class QPoint;
-struct QSGAreaAllocatorNode;
-class Q_DECLARATIVE_EXPORT QSGAreaAllocator
-{
-public:
- QSGAreaAllocator(const QSize &size);
- ~QSGAreaAllocator();
-
- QRect allocate(const QSize &size);
- bool deallocate(const QRect &rect);
- bool isEmpty() const { return m_root == 0; }
- QSize size() const { return m_size; }
-private:
- bool allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, QSGAreaAllocatorNode *node);
- bool deallocateInNode(const QPoint &pos, QSGAreaAllocatorNode *node);
- void mergeNodeWithNeighbors(QSGAreaAllocatorNode *node);
-
- QSGAreaAllocatorNode *m_root;
- QSize m_size;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/declarative/scenegraph/util/qsgdistancefieldutil.cpp b/src/declarative/scenegraph/util/qsgdistancefieldutil.cpp
deleted file mode 100644
index 3429162d6b..0000000000
--- a/src/declarative/scenegraph/util/qsgdistancefieldutil.cpp
+++ /dev/null
@@ -1,805 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgdistancefieldutil_p.h"
-
-#include <qmath.h>
-#include <private/qsgpathsimplifier_p.h>
-#include <private/qsgadaptationlayer_p.h>
-#include <QtGui/private/qopenglengineshadersource_p.h>
-#include <private/qsgcontext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-static float defaultThresholdFunc(float glyphScale)
-{
- static float base = qgetenv("QT_DF_BASE").isEmpty() ? 0.5f : qgetenv("QT_DF_BASE").toFloat();
- static float baseDev = qgetenv("QT_DF_BASEDEVIATION").isEmpty() ? 0.065f : qgetenv("QT_DF_BASEDEVIATION").toFloat();
- static float devScaleMin = qgetenv("QT_DF_SCALEFORMAXDEV").isEmpty() ? 0.15f : qgetenv("QT_DF_SCALEFORMAXDEV").toFloat();
- static float devScaleMax = qgetenv("QT_DF_SCALEFORNODEV").isEmpty() ? 0.3f : qgetenv("QT_DF_SCALEFORNODEV").toFloat();
- return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
-}
-
-static float defaultAntialiasingSpreadFunc(float glyphScale)
-{
- static float range = qgetenv("QT_DF_RANGE").isEmpty() ? 0.06f : qgetenv("QT_DF_RANGE").toFloat();
- return range / glyphScale;
-}
-
-namespace
-{
- enum FillHDir
- {
- LeftToRight,
- RightToLeft
- };
-
- enum FillVDir
- {
- TopDown,
- BottomUp
- };
-
- enum FillClip
- {
- NoClip,
- Clip
- };
-}
-
-template <FillClip clip, FillHDir dir>
-inline void fillLine(qint32 *, int, int, int, qint32, qint32)
-{
-}
-
-template <>
-inline void fillLine<Clip, LeftToRight>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
-{
- int fromX = qMax(0, lx >> 8);
- int toX = qMin(width, rx >> 8);
- int x = toX - fromX;
- if (x <= 0)
- return;
- qint32 val = d + (((fromX << 8) + 0xff - lx) * dd >> 8);
- line += fromX;
- do {
- *line = abs(val) < abs(*line) ? val : *line;
- val += dd;
- ++line;
- } while (--x);
-}
-
-template <>
-inline void fillLine<Clip, RightToLeft>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
-{
- int fromX = qMax(0, lx >> 8);
- int toX = qMin(width, rx >> 8);
- int x = toX - fromX;
- if (x <= 0)
- return;
- qint32 val = d + (((toX << 8) + 0xff - rx) * dd >> 8);
- line += toX;
- do {
- val -= dd;
- --line;
- *line = abs(val) < abs(*line) ? val : *line;
- } while (--x);
-}
-
-template <>
-inline void fillLine<NoClip, LeftToRight>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
-{
- int fromX = lx >> 8;
- int toX = rx >> 8;
- int x = toX - fromX;
- if (x <= 0)
- return;
- qint32 val = d + ((~lx & 0xff) * dd >> 8);
- line += fromX;
- do {
- *line = abs(val) < abs(*line) ? val : *line;
- val += dd;
- ++line;
- } while (--x);
-}
-
-template <>
-inline void fillLine<NoClip, RightToLeft>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
-{
- int fromX = lx >> 8;
- int toX = rx >> 8;
- int x = toX - fromX;
- if (x <= 0)
- return;
- qint32 val = d + ((~rx & 0xff) * dd >> 8);
- line += toX;
- do {
- val -= dd;
- --line;
- *line = abs(val) < abs(*line) ? val : *line;
- } while (--x);
-}
-
-template <FillClip clip, FillVDir vDir, FillHDir hDir>
-inline void fillLines(qint32 *bits, int width, int height, int upperY, int lowerY,
- int &lx, int ldx, int &rx, int rdx, qint32 &d, qint32 ddy, qint32 ddx)
-{
- Q_UNUSED(height);
- Q_ASSERT(upperY < lowerY);
- int y = lowerY - upperY;
- if (vDir == TopDown) {
- qint32 *line = bits + upperY * width;
- do {
- fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
- lx += ldx;
- d += ddy;
- rx += rdx;
- line += width;
- } while (--y);
- } else {
- qint32 *line = bits + lowerY * width;
- do {
- lx -= ldx;
- d -= ddy;
- rx -= rdx;
- line -= width;
- fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
- } while (--y);
- }
-}
-
-template <FillClip clip>
-void drawTriangle(qint32 *bits, int width, int height, const QPoint *center,
- const QPoint *v1, const QPoint *v2, qint32 value)
-{
- const int y1 = clip == Clip ? qBound(0, v1->y() >> 8, height) : v1->y() >> 8;
- const int y2 = clip == Clip ? qBound(0, v2->y() >> 8, height) : v2->y() >> 8;
- const int yC = clip == Clip ? qBound(0, center->y() >> 8, height) : center->y() >> 8;
-
- const int v1Frac = clip == Clip ? (y1 << 8) + 0xff - v1->y() : ~v2->y() & 0xff;
- const int v2Frac = clip == Clip ? (y2 << 8) + 0xff - v2->y() : ~v1->y() & 0xff;
- const int centerFrac = clip == Clip ? (yC << 8) + 0xff - center->y() : ~center->y() & 0xff;
-
- int dx1 = 0, x1 = 0, dx2 = 0, x2 = 0;
- qint32 dd1, d1, dd2, d2;
- if (v1->y() != center->y()) {
- dx1 = ((v1->x() - center->x()) << 8) / (v1->y() - center->y());
- x1 = center->x() + centerFrac * (v1->x() - center->x()) / (v1->y() - center->y());
- }
- if (v2->y() != center->y()) {
- dx2 = ((v2->x() - center->x()) << 8) / (v2->y() - center->y());
- x2 = center->x() + centerFrac * (v2->x() - center->x()) / (v2->y() - center->y());
- }
-
- const qint32 div = (v2->x() - center->x()) * (v1->y() - center->y())
- - (v2->y() - center->y()) * (v1->x() - center->x());
- const qint32 dd = div ? qint32((qint64(value * (v1->y() - v2->y())) << 8) / div) : 0;
-
- if (y2 < yC) {
- if (y1 < yC) {
- // Center at the bottom.
- if (y2 < y1) {
- // y2 < y1 < yC
- // Long right edge.
- d1 = centerFrac * value / (v1->y() - center->y());
- dd1 = ((value << 8) / (v1->y() - center->y()));
- fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y1, yC, x1, dx1,
- x2, dx2, d1, dd1, dd);
- dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, y1, x1, dx1,
- x2, dx2, value, 0, dd);
- } else {
- // y1 <= y2 < yC
- // Long left edge.
- d2 = centerFrac * value / (v2->y() - center->y());
- dd2 = ((value << 8) / (v2->y() - center->y()));
- fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y2, yC, x1, dx1,
- x2, dx2, d2, dd2, dd);
- if (y1 != y2) {
- dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, y2, x1, dx1,
- x2, dx2, value, 0, dd);
- }
- }
- } else {
- // y2 < yC <= y1
- // Center to the right.
- int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- int xUp, xDn;
- xUp = xDn = v2->x() + (clip == Clip ? (yC << 8) + 0xff - v2->y()
- : (center->y() | 0xff) - v2->y())
- * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, yC, xUp, dx,
- x2, dx2, value, 0, dd);
- if (yC != y1)
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y1, xDn, dx,
- x1, dx1, value, 0, dd);
- }
- } else {
- if (y1 < yC) {
- // y1 < yC <= y2
- // Center to the left.
- int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- int xUp, xDn;
- xUp = xDn = v1->x() + (clip == Clip ? (yC << 8) + 0xff - v1->y()
- : (center->y() | 0xff) - v1->y())
- * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, yC, x1, dx1,
- xUp, dx, value, 0, dd);
- if (yC != y2)
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y2, x2, dx2,
- xDn, dx, value, 0, dd);
- } else {
- // Center at the top.
- if (y2 < y1) {
- // yC <= y2 < y1
- // Long right edge.
- if (yC != y2) {
- d2 = centerFrac * value / (v2->y() - center->y());
- dd2 = ((value << 8) / (v2->y() - center->y()));
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y2, x2, dx2,
- x1, dx1, d2, dd2, dd);
- }
- dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, y2, y1, x2, dx2,
- x1, dx1, value, 0, dd);
- } else {
- // Long left edge.
- // yC <= y1 <= y2
- if (yC != y1) {
- d1 = centerFrac * value / (v1->y() - center->y());
- dd1 = ((value << 8) / (v1->y() - center->y()));
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y1, x2, dx2,
- x1, dx1, d1, dd1, dd);
- }
- if (y1 != y2) {
- dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
- x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, y1, y2, x2, dx2,
- x1, dx1, value, 0, dd);
- }
- }
- }
- }
-}
-
-template <FillClip clip>
-void drawRectangle(qint32 *bits, int width, int height,
- const QPoint *int1, const QPoint *center1, const QPoint *ext1,
- const QPoint *int2, const QPoint *center2, const QPoint *ext2,
- qint32 extValue)
-{
- if (center1->y() > center2->y()) {
- qSwap(center1, center2);
- qSwap(int1, ext2);
- qSwap(ext1, int2);
- extValue = -extValue;
- }
-
- Q_ASSERT(ext1->x() - center1->x() == center1->x() - int1->x());
- Q_ASSERT(ext1->y() - center1->y() == center1->y() - int1->y());
- Q_ASSERT(ext2->x() - center2->x() == center2->x() - int2->x());
- Q_ASSERT(ext2->y() - center2->y() == center2->y() - int2->y());
-
- const int yc1 = clip == Clip ? qBound(0, center1->y() >> 8, height) : center1->y() >> 8;
- const int yc2 = clip == Clip ? qBound(0, center2->y() >> 8, height) : center2->y() >> 8;
- const int yi1 = clip == Clip ? qBound(0, int1->y() >> 8, height) : int1->y() >> 8;
- const int yi2 = clip == Clip ? qBound(0, int2->y() >> 8, height) : int2->y() >> 8;
- const int ye1 = clip == Clip ? qBound(0, ext1->y() >> 8, height) : ext1->y() >> 8;
- const int ye2 = clip == Clip ? qBound(0, ext2->y() >> 8, height) : ext2->y() >> 8;
-
- const int center1Frac = clip == Clip ? (yc1 << 8) + 0xff - center1->y() : ~center1->y() & 0xff;
- const int center2Frac = clip == Clip ? (yc2 << 8) + 0xff - center2->y() : ~center2->y() & 0xff;
- const int int1Frac = clip == Clip ? (yi1 << 8) + 0xff - int1->y() : ~int1->y() & 0xff;
- const int ext1Frac = clip == Clip ? (ye1 << 8) + 0xff - ext1->y() : ~ext1->y() & 0xff;
-
- int dxC = 0, dxE = 0; // cap slope, edge slope
- qint32 ddC = 0;
- if (ext1->y() != int1->y()) {
- dxC = ((ext1->x() - int1->x()) << 8) / (ext1->y() - int1->y());
- ddC = (extValue << 9) / (ext1->y() - int1->y());
- }
- if (ext1->y() != ext2->y())
- dxE = ((ext1->x() - ext2->x()) << 8) / (ext1->y() - ext2->y());
-
- const qint32 div = (ext1->x() - int1->x()) * (ext2->y() - int1->y())
- - (ext1->y() - int1->y()) * (ext2->x() - int1->x());
- const qint32 dd = div ? qint32((qint64(extValue * (ext2->y() - ext1->y())) << 9) / div) : 0;
-
- int xe1, xe2, xc1, xc2;
- qint32 d;
-
- qint32 intValue = -extValue;
-
- if (center2->x() < center1->x()) {
- // Leaning to the right. '/'
- if (int1->y() < ext2->y()) {
- // Mostly vertical.
- Q_ASSERT(ext1->y() != ext2->y());
- xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- if (ye1 != yi1) {
- xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc2 += (ye1 - yc1) * dxC;
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, yi1, xe1, dxE,
- xc2, dxC, extValue, 0, dd);
- }
- if (yi1 != ye2)
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi1, ye2, xe1, dxE,
- xe2, dxE, extValue, 0, dd);
- if (ye2 != yi2) {
- xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc1 += (ye2 - yc2) * dxC;
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye2, yi2, xc1, dxC,
- xe2, dxE, intValue, 0, dd);
- }
- } else {
- // Mostly horizontal.
- Q_ASSERT(ext1->y() != int1->y());
- xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc1 += (ye2 - yc2) * dxC;
- xc2 += (ye1 - yc1) * dxC;
- if (ye1 != ye2) {
- xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
- xc2, dxC, extValue, 0, dd);
- }
- if (ye2 != yi1) {
- d = (clip == Clip ? (ye2 << 8) + 0xff - center2->y()
- : (ext2->y() | 0xff) - center2->y())
- * 2 * extValue / (ext1->y() - int1->y());
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye2, yi1, xc1, dxC,
- xc2, dxC, d, ddC, dd);
- }
- if (yi1 != yi2) {
- xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
- xe2, dxE, intValue, 0, dd);
- }
- }
- } else {
- // Leaning to the left. '\'
- if (ext1->y() < int2->y()) {
- // Mostly vertical.
- Q_ASSERT(ext1->y() != ext2->y());
- xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- if (yi1 != ye1) {
- xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc1 += (yi1 - yc1) * dxC;
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, ye1, xc1, dxC,
- xe2, dxE, intValue, 0, dd);
- }
- if (ye1 != yi2)
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye1, yi2, xe1, dxE,
- xe2, dxE, intValue, 0, dd);
- if (yi2 != ye2) {
- xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc2 += (yi2 - yc2) * dxC;
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi2, ye2, xe1, dxE,
- xc2, dxC, extValue, 0, dd);
- }
- } else {
- // Mostly horizontal.
- Q_ASSERT(ext1->y() != int1->y());
- xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
- xc1 += (yi1 - yc1) * dxC;
- xc2 += (yi2 - yc2) * dxC;
- if (yi1 != yi2) {
- xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
- xe2, dxE, intValue, 0, dd);
- }
- if (yi2 != ye1) {
- d = (clip == Clip ? (yi2 << 8) + 0xff - center2->y()
- : (int2->y() | 0xff) - center2->y())
- * 2 * extValue / (ext1->y() - int1->y());
- fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi2, ye1, xc1, dxC,
- xc2, dxC, d, ddC, dd);
- }
- if (ye1 != ye2) {
- xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
- fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
- xc2, dxC, extValue, 0, dd);
- }
- }
- }
-}
-
-static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vertices,
- const quint32 *indices, int indexCount, qint32 value)
-{
- Q_ASSERT(indexCount != 0);
- Q_ASSERT(height <= 128);
- QVarLengthArray<quint8, 16> scans[128];
- int first = 0;
- for (int i = 1; i < indexCount; ++i) {
- quint32 idx1 = indices[i - 1];
- quint32 idx2 = indices[i];
- Q_ASSERT(idx1 != quint32(-1));
- if (idx2 == quint32(-1)) {
- idx2 = indices[first];
- Q_ASSERT(idx2 != quint32(-1));
- first = ++i;
- }
- const QPoint *v1 = &vertices[idx1];
- const QPoint *v2 = &vertices[idx2];
- if (v2->y() < v1->y())
- qSwap(v1, v2);
- int fromY = qMax(0, v1->y() >> 8);
- int toY = qMin(height, v2->y() >> 8);
- if (fromY >= toY)
- continue;
- int dx = ((v2->x() - v1->x()) << 8) / (v2->y() - v1->y());
- int x = v1->x() + ((fromY << 8) + 0xff - v1->y()) * (v2->x() - v1->x()) / (v2->y() - v1->y());
- for (int y = fromY; y < toY; ++y) {
- quint32 c = quint32(x >> 8);
- if (c < quint32(width))
- scans[y].append(quint8(c));
- x += dx;
- }
- }
- for (int i = 0; i < height; ++i) {
- quint8 *scanline = scans[i].data();
- int size = scans[i].size();
- for (int j = 1; j < size; ++j) {
- int k = j;
- quint8 value = scanline[k];
- for (; k != 0 && value < scanline[k - 1]; --k)
- scanline[k] = scanline[k - 1];
- scanline[k] = value;
- }
- qint32 *line = bits + i * width;
- int j = 0;
- for (; j + 1 < size; j += 2) {
- for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
- line[x] = value;
- }
- if (j < size) {
- for (int x = scanline[j]; x < width; ++x)
- line[x] = value;
- }
- }
-}
-
-static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfScale, int offs)
-{
- QImage image(imgSize, imgSize, QImage::Format_Indexed8);
-
- if (path.isEmpty()) {
- image.fill(0);
- return image;
- }
-
- QTransform transform;
- transform.translate(offs, offs);
- transform.scale(qreal(1) / dfScale, qreal(1) / dfScale);
-
- QDataBuffer<quint32> pathIndices(0);
- QDataBuffer<QPoint> pathVertices(0);
- qSimplifyPath(path, pathVertices, pathIndices, transform);
-
- const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5
- const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5
-
- QScopedArrayPointer<qint32> bits(new qint32[imgSize * imgSize]);
- for (int i = 0; i < imgSize * imgSize; ++i)
- bits[i] = exteriorColor;
-
- const qreal angleStep = qreal(15 * 3.141592653589793238 / 180);
- const QPoint rotation(qRound(cos(angleStep) * 0x4000),
- qRound(sin(angleStep) * 0x4000)); // 2:14 signed
-
- const quint32 *indices = pathIndices.data();
- QVarLengthArray<QPoint> normals;
- QVarLengthArray<QPoint> vertices;
- QVarLengthArray<bool> isConvex;
- QVarLengthArray<bool> needsClipping;
-
- drawPolygons(bits.data(), imgSize, imgSize, pathVertices.data(), indices, pathIndices.size(),
- interiorColor);
-
- int index = 0;
-
- while (index < pathIndices.size()) {
- normals.clear();
- vertices.clear();
- needsClipping.clear();
-
- // Find end of polygon.
- int end = index;
- while (indices[end] != quint32(-1))
- ++end;
-
- // Calculate vertex normals.
- for (int next = index, prev = end - 1; next < end; prev = next++) {
- quint32 fromVertexIndex = indices[prev];
- quint32 toVertexIndex = indices[next];
-
- const QPoint &from = pathVertices.at(fromVertexIndex);
- const QPoint &to = pathVertices.at(toVertexIndex);
-
- QPoint n(to.y() - from.y(), from.x() - to.x());
- if (n.x() == 0 && n.y() == 0)
- continue;
- int scale = qRound((offs << 16) / sqrt(qreal(n.x() * n.x() + n.y() * n.y()))); // 8:16
- n.rx() = n.x() * scale >> 8;
- n.ry() = n.y() * scale >> 8;
- normals.append(n);
- QPoint v(to.x() + 0x7f, to.y() + 0x7f);
- vertices.append(v);
- needsClipping.append((to.x() < offs << 8) || (to.x() >= (imgSize - offs) << 8)
- || (to.y() < offs << 8) || (to.y() >= (imgSize - offs) << 8));
- }
-
- isConvex.resize(normals.count());
- for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
- isConvex[prev] = normals.at(prev).x() * normals.at(next).y()
- - normals.at(prev).y() * normals.at(next).x() < 0;
- }
-
- // Draw quads.
- for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
- QPoint n = normals.at(next);
- QPoint intPrev = vertices.at(prev);
- QPoint extPrev = vertices.at(prev);
- QPoint intNext = vertices.at(next);
- QPoint extNext = vertices.at(next);
-
- extPrev.rx() -= n.x();
- extPrev.ry() -= n.y();
- intPrev.rx() += n.x();
- intPrev.ry() += n.y();
- extNext.rx() -= n.x();
- extNext.ry() -= n.y();
- intNext.rx() += n.x();
- intNext.ry() += n.y();
-
- if (needsClipping[prev] || needsClipping[next]) {
- drawRectangle<Clip>(bits.data(), imgSize, imgSize,
- &intPrev, &vertices.at(prev), &extPrev,
- &intNext, &vertices.at(next), &extNext,
- exteriorColor);
- } else {
- drawRectangle<NoClip>(bits.data(), imgSize, imgSize,
- &intPrev, &vertices.at(prev), &extPrev,
- &intNext, &vertices.at(next), &extNext,
- exteriorColor);
- }
-
- if (isConvex.at(prev)) {
- QPoint p = extPrev;
- if (needsClipping[prev]) {
- for (;;) {
- QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
- (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
- n = rn;
- if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
- p.rx() = vertices.at(prev).x() - normals.at(prev).x();
- p.ry() = vertices.at(prev).y() - normals.at(prev).y();
- drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &extPrev, &p, exteriorColor);
- break;
- }
-
- p.rx() = vertices.at(prev).x() - n.x();
- p.ry() = vertices.at(prev).y() - n.y();
- drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &extPrev, &p, exteriorColor);
- extPrev = p;
- }
- } else {
- for (;;) {
- QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
- (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
- n = rn;
- if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
- p.rx() = vertices.at(prev).x() - normals.at(prev).x();
- p.ry() = vertices.at(prev).y() - normals.at(prev).y();
- drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &extPrev, &p, exteriorColor);
- break;
- }
-
- p.rx() = vertices.at(prev).x() - n.x();
- p.ry() = vertices.at(prev).y() - n.y();
- drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &extPrev, &p, exteriorColor);
- extPrev = p;
- }
- }
- } else {
- QPoint p = intPrev;
- if (needsClipping[prev]) {
- for (;;) {
- QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
- (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
- n = rn;
- if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
- p.rx() = vertices.at(prev).x() + normals.at(prev).x();
- p.ry() = vertices.at(prev).y() + normals.at(prev).y();
- drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &p, &intPrev, interiorColor);
- break;
- }
-
- p.rx() = vertices.at(prev).x() + n.x();
- p.ry() = vertices.at(prev).y() + n.y();
- drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &p, &intPrev, interiorColor);
- intPrev = p;
- }
- } else {
- for (;;) {
- QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
- (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
- n = rn;
- if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
- p.rx() = vertices.at(prev).x() + normals.at(prev).x();
- p.ry() = vertices.at(prev).y() + normals.at(prev).y();
- drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &p, &intPrev, interiorColor);
- break;
- }
-
- p.rx() = vertices.at(prev).x() + n.x();
- p.ry() = vertices.at(prev).y() + n.y();
- drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
- &p, &intPrev, interiorColor);
- intPrev = p;
- }
- }
- }
- }
-
- index = end + 1;
- }
-
- const qint32 *inLine = bits.data();
- uchar *outLine = image.bits();
- int padding = image.bytesPerLine() - image.width();
- for (int y = 0; y < imgSize; ++y) {
- for (int x = 0; x < imgSize; ++x, ++inLine, ++outLine)
- *outLine = uchar((0x7f80 - *inLine) >> 8);
- outLine += padding;
- }
-
- return image;
-}
-
-bool qt_fontHasNarrowOutlines(const QRawFont &f)
-{
- QRawFont font = f;
- font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);
- Q_ASSERT(font.isValid());
-
- QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O"));
- if (glyphIndices.size() < 1)
- return false;
-
- QImage im = font.alphaMapForGlyph(glyphIndices.at(0), QRawFont::PixelAntialiasing);
- if (im.isNull())
- return false;
-
- int minHThick = 999;
- int minVThick = 999;
-
- int thick = 0;
- bool in = false;
- int y = (im.height() + 1) / 2;
- for (int x = 0; x < im.width(); ++x) {
- int a = qAlpha(im.pixel(x, y));
- if (a > 127) {
- in = true;
- ++thick;
- } else if (in) {
- in = false;
- minHThick = qMin(minHThick, thick);
- thick = 0;
- }
- }
-
- thick = 0;
- in = false;
- int x = (im.width() + 1) / 2;
- for (int y = 0; y < im.height(); ++y) {
- int a = qAlpha(im.pixel(x, y));
- if (a > 127) {
- in = true;
- ++thick;
- } else if (in) {
- in = false;
- minVThick = qMin(minVThick, thick);
- thick = 0;
- }
- }
-
- return minHThick == 1 || minVThick == 1;
-}
-
-QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution)
-{
- QRawFont renderFont = font;
- renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(doubleResolution) * QT_DISTANCEFIELD_SCALE(doubleResolution));
-
- QPainterPath path = renderFont.pathForGlyph(glyph);
- path.translate(-path.boundingRect().topLeft());
- path.setFillRule(Qt::WindingFill);
-
- QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution),
- path,
- QT_DISTANCEFIELD_SCALE(doubleResolution),
- QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution));
- return im;
-}
-
-QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QSGContext *c)
- : sgCtx(c)
- , m_threshold_func(defaultThresholdFunc)
- , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
-{
-#ifndef QT_OPENGL_ES
- m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
-#else
- m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
-#endif
-}
-
-QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
-{
- qDeleteAll(m_caches.values());
-}
-
-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();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h b/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h
deleted file mode 100644
index 93dffab76e..0000000000
--- a/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGDISTANCEFIELDUTIL_H
-#define QSGDISTANCEFIELDUTIL_H
-
-#include <qrawfont.h>
-#include <private/qfontengine_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54
-#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64
-#define QT_DISTANCEFIELD_DEFAULT_SCALE 16
-#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80
-#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000
-
-#define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \
- (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \
- QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE)
-#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \
- (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \
- QT_DISTANCEFIELD_DEFAULT_TILESIZE)
-#define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \
- (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \
- QT_DISTANCEFIELD_DEFAULT_SCALE)
-#define QT_DISTANCEFIELD_RADIUS(NarrowOutlineFont) \
- (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \
- QT_DISTANCEFIELD_DEFAULT_RADIUS)
-
-
-typedef float (*ThresholdFunc)(float glyphScale);
-typedef float (*AntialiasingSpreadFunc)(float glyphScale);
-
-bool qt_fontHasNarrowOutlines(const QRawFont &f);
-QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution);
-
-
-class QOpenGLShaderProgram;
-class QSGDistanceFieldGlyphCache;
-class QSGContext;
-
-class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCacheManager
-{
-public:
- QSGDistanceFieldGlyphCacheManager(QSGContext *c);
- ~QSGDistanceFieldGlyphCacheManager();
-
- QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
-
- QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
- void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
-
- ThresholdFunc thresholdFunc() const { return m_threshold_func; }
- void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
-
- AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
- void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
-
-private:
- QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
-
- QSGContext *sgCtx;
-
- QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
- ThresholdFunc m_threshold_func;
- AntialiasingSpreadFunc m_antialiasingSpread_func;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSGDISTANCEFIELDUTIL_H
diff --git a/src/declarative/scenegraph/util/qsgengine.cpp b/src/declarative/scenegraph/util/qsgengine.cpp
deleted file mode 100644
index 88eeebc472..0000000000
--- a/src/declarative/scenegraph/util/qsgengine.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgengine.h"
-
-#include <qquickcanvas.h>
-
-#include <private/qobject_p.h>
-#include <QtGui/QColor>
-
-QT_BEGIN_NAMESPACE
-
-class QSGEnginePrivate : public QObjectPrivate
-{
-public:
- QSGEnginePrivate()
- : canvas(0)
- {
- }
-
- QQuickCanvas *canvas;
-};
-
-/*!
- \class QSGEngine
- \deprecated
- */
-
-QSGEngine::QSGEngine(QObject *parent) :
- QObject(*(new QSGEnginePrivate), parent)
-{
-}
-
-
-QSGEngine::~QSGEngine()
-{
-}
-
-
-void QSGEngine::setCanvas(QQuickCanvas *canvas)
-{
- d_func()->canvas = canvas;
- connect(canvas, SIGNAL(afterRendering()), this, SIGNAL(afterRendering()));
- connect(canvas, SIGNAL(beforeRendering()), this, SIGNAL(beforeRendering()));
-}
-
-void QSGEngine::setClearBeforeRendering(bool enabled)
-{
- d_func()->canvas->setClearBeforeRendering(enabled);
-}
-
-bool QSGEngine::clearBeforeRendering() const
-{
- return d_func()->canvas->clearBeforeRendering();
-}
-
-QSGTexture *QSGEngine::createTextureFromImage(const QImage &image) const
-{
- return d_func()->canvas->createTextureFromImage(image);
-}
-
-QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, TextureOptions options) const
-{
- return d_func()->canvas->createTextureFromId(id, size, QQuickCanvas::CreateTextureOptions((int) options));
-}
-
-void QSGEngine::setClearColor(const QColor &color)
-{
- d_func()->canvas->setClearColor(color);
-}
-
-QColor QSGEngine::clearColor() const
-{
- return d_func()->canvas->clearColor();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgengine.h b/src/declarative/scenegraph/util/qsgengine.h
deleted file mode 100644
index 0cbbcddfec..0000000000
--- a/src/declarative/scenegraph/util/qsgengine.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGENGINE_H
-#define QSGENGINE_H
-
-#include <QObject>
-
-#include <qsgtexture.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGEnginePrivate;
-
-class QQuickCanvas;
-
-class Q_DECLARATIVE_EXPORT QSGEngine : public QObject
-{
- Q_OBJECT
-
- Q_DECLARE_PRIVATE(QSGEngine)
-
-public:
-
- enum TextureOption {
- TextureHasAlphaChannel = 0x0001,
- TextureHasMipmaps = 0x0002,
- TextureOwnsGLTexture = 0x0004
- };
- Q_DECLARE_FLAGS(TextureOptions, TextureOption)
-
- QSGTexture *createTextureFromImage(const QImage &image) const;
- QSGTexture *createTextureFromId(uint id, const QSize &size, TextureOptions options = TextureOption(0)) const;
-
- void setClearBeforeRendering(bool enabled);
- bool clearBeforeRendering() const;
-
- void setClearColor(const QColor &color);
- QColor clearColor() const;
-
-Q_SIGNALS:
- void beforeRendering();
- void afterRendering();
-
-private:
- QSGEngine(QObject *parent = 0);
- ~QSGEngine();
-
- friend class QSGContext;
- friend class QSGContextPrivate;
- friend class QQuickCanvasPrivate;
- void setCanvas(QQuickCanvas *canvas);
-
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGENGINE_H
diff --git a/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp b/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp
deleted file mode 100644
index ee73616e4f..0000000000
--- a/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgflatcolormaterial.h"
-
-#include <qopenglshaderprogram.h>
-
-QT_BEGIN_NAMESPACE
-
-class FlatColorMaterialShader : public QSGMaterialShader
-{
-public:
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-
- static QSGMaterialType type;
-
-private:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- int m_matrix_id;
- int m_color_id;
-};
-
-QSGMaterialType FlatColorMaterialShader::type;
-
-void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
-
- QSGFlatColorMaterial *oldMaterial = static_cast<QSGFlatColorMaterial *>(oldEffect);
- QSGFlatColorMaterial *newMaterial = static_cast<QSGFlatColorMaterial *>(newEffect);
-
- const QColor &c = newMaterial->color();
-
- if (oldMaterial == 0 || c != oldMaterial->color() || state.isOpacityDirty()) {
- float opacity = state.opacity();
- QVector4D v(c.redF() * c.alphaF() * opacity,
- c.greenF() * c.alphaF() * opacity,
- c.blueF() * c.alphaF() * opacity,
- c.alphaF() * opacity);
- program()->setUniformValue(m_color_id, v);
- }
-
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
-}
-
-char const *const *FlatColorMaterialShader::attributeNames() const
-{
- static char const *const attr[] = { "vCoord", 0 };
- return attr;
-}
-
-void FlatColorMaterialShader::initialize()
-{
- m_matrix_id = program()->uniformLocation("matrix");
- m_color_id = program()->uniformLocation("color");
-}
-
-const char *FlatColorMaterialShader::vertexShader() const {
- return
- "attribute highp vec4 vCoord; \n"
- "uniform highp mat4 matrix; \n"
- "void main() { \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *FlatColorMaterialShader::fragmentShader() const {
- return
- "uniform lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color; \n"
- "}";
-}
-
-
-
-/*!
- \class QSGFlatColorMaterial
- \brief The QSGFlatColorMaterial class provides a convenient way of rendering
- solid colored geometry in the scene graph.
-
- \inmodule QtDeclarative
-
- The flat color material will fill every pixel in a geometry using
- a solid color. The color can contain transparency.
-
- The geometry to be rendered with a flat color material requires
- vertices in attribute location 0 in the QSGGeometry object to render
- correctly. The QSGGeometry::defaultAttributes_Point2D() returns an attribute
- set compatible with this material.
-
- The flat color material respects both current opacity and current matrix
- when updating it's rendering state.
- */
-
-
-/*!
- Constructs a new flat color material.
-
- The default color is white.
- */
-
-QSGFlatColorMaterial::QSGFlatColorMaterial() : m_color(QColor(255, 255, 255))
-{
-}
-
-
-
-/*!
- \fn QColor QSGFlatColorMaterial::color() const
-
- Returns this flat color material's color.
-
- The default color is white.
- */
-
-
-
-/*!
- Sets this flat color material's color to \a color.
- */
-
-void QSGFlatColorMaterial::setColor(const QColor &color)
-{
- m_color = color;
- setFlag(Blending, m_color.alpha() != 0xff);
-}
-
-
-
-/*!
- \internal
- */
-
-QSGMaterialType *QSGFlatColorMaterial::type() const
-{
- return &FlatColorMaterialShader::type;
-}
-
-
-
-/*!
- \internal
- */
-
-QSGMaterialShader *QSGFlatColorMaterial::createShader() const
-{
- return new FlatColorMaterialShader;
-}
-
-
-int QSGFlatColorMaterial::compare(const QSGMaterial *other) const
-{
- const QSGFlatColorMaterial *flat = static_cast<const QSGFlatColorMaterial *>(other);
- return m_color.rgba() - flat->color().rgba();
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgflatcolormaterial.h b/src/declarative/scenegraph/util/qsgflatcolormaterial.h
deleted file mode 100644
index f6345b6483..0000000000
--- a/src/declarative/scenegraph/util/qsgflatcolormaterial.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 FLATCOLORMATERIAL_H
-#define FLATCOLORMATERIAL_H
-
-#include <qsgmaterial.h>
-#include <qcolor.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGFlatColorMaterial : public QSGMaterial
-{
-public:
- QSGFlatColorMaterial();
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-
- void setColor(const QColor &color);
- const QColor &color() const { return m_color; }
-
- int compare(const QSGMaterial *other) const;
-
-private:
- QColor m_color;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // FLATCOLORMATERIAL_H
diff --git a/src/declarative/scenegraph/util/qsgpainternode.cpp b/src/declarative/scenegraph/util/qsgpainternode.cpp
deleted file mode 100644
index f3e5202241..0000000000
--- a/src/declarative/scenegraph/util/qsgpainternode.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgpainternode_p.h"
-
-#include <private/qquickpainteditem_p.h>
-
-#include <private/qsgcontext_p.h>
-#include <private/qopenglextensions_p.h>
-#include <qopenglframebufferobject.h>
-#include <qopenglfunctions.h>
-#include <qopenglpaintdevice.h>
-#include <qmath.h>
-#include <qpainter.h>
-
-QT_BEGIN_NAMESPACE
-
-#define QT_MINIMUM_DYNAMIC_FBO_SIZE 64
-
-static inline int qt_next_power_of_two(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
-QSGPainterTexture::QSGPainterTexture()
- : QSGPlainTexture()
-{
-
-}
-
-void QSGPainterTexture::bind()
-{
- if (m_dirty_rect.isNull()) {
- QSGPlainTexture::bind();
- return;
- }
-
- bool oldMipmapsGenerated = m_mipmaps_generated;
- m_mipmaps_generated = true;
- QSGPlainTexture::bind();
- m_mipmaps_generated = oldMipmapsGenerated;
-
- QImage subImage = m_image.copy(m_dirty_rect);
-
- int w = m_dirty_rect.width();
- int h = m_dirty_rect.height();
-
-#ifdef QT_OPENGL_ES
- glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
- GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
-#else
- glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
- GL_BGRA, GL_UNSIGNED_BYTE, subImage.constBits());
-#endif
-
- if (m_has_mipmaps && !m_mipmaps_generated) {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
- m_mipmaps_generated = true;
- }
-
- m_dirty_texture = false;
- m_dirty_bind_options = false;
-
- m_dirty_rect = QRect();
-}
-
-QSGPainterNode::QSGPainterNode(QQuickPaintedItem *item)
- : QSGGeometryNode()
- , m_preferredRenderTarget(QQuickPaintedItem::Image)
- , m_actualRenderTarget(QQuickPaintedItem::Image)
- , m_item(item)
- , m_fbo(0)
- , m_multisampledFbo(0)
- , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- , m_texture(0)
- , m_gl_device(0)
- , m_size(1, 1)
- , m_dirtyContents(false)
- , m_opaquePainting(false)
- , m_linear_filtering(false)
- , m_mipmapping(false)
- , m_smoothPainting(false)
- , m_extensionsChecked(false)
- , m_multisamplingSupported(false)
- , m_fastFBOResizing(false)
- , m_fillColor(Qt::transparent)
- , m_contentsScale(1.0)
- , m_dirtyGeometry(false)
- , m_dirtyRenderTarget(false)
- , m_dirtyTexture(false)
-{
- m_context = static_cast<QQuickPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphContext();
-
- setMaterial(&m_materialO);
- setOpaqueMaterial(&m_material);
- setGeometry(&m_geometry);
-}
-
-QSGPainterNode::~QSGPainterNode()
-{
- delete m_texture;
- delete m_fbo;
- delete m_multisampledFbo;
- delete m_gl_device;
-}
-
-void QSGPainterNode::paint()
-{
- QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
-
- QPainter painter;
- if (m_actualRenderTarget == QQuickPaintedItem::Image)
- painter.begin(&m_image);
- else {
- if (!m_gl_device) {
- m_gl_device = new QOpenGLPaintDevice(m_fboSize);
- m_gl_device->setPaintFlipped(true);
- }
-
- if (m_multisampledFbo)
- m_multisampledFbo->bind();
- else
- m_fbo->bind();
-
- painter.begin(m_gl_device);
- }
-
- if (m_smoothPainting) {
- painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
- | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
- }
-
- painter.scale(m_contentsScale, m_contentsScale);
-
- QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
- qFloor(dirtyRect.y()/m_contentsScale),
- qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
- qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
-
- if (!m_dirtyRect.isNull())
- painter.setClipRect(sclip);
-
- painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(sclip, m_fillColor);
- painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
-
- m_item->paint(&painter);
- painter.end();
-
- if (m_actualRenderTarget == QQuickPaintedItem::Image) {
- m_texture->setImage(m_image);
- m_texture->setDirtyRect(dirtyRect);
- } else if (m_multisampledFbo) {
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
- }
-
- if (m_multisampledFbo)
- m_multisampledFbo->release();
- else if (m_fbo)
- m_fbo->release();
-
- m_dirtyRect = QRect();
-}
-
-void QSGPainterNode::update()
-{
- if (m_dirtyRenderTarget)
- updateRenderTarget();
- if (m_dirtyGeometry)
- updateGeometry();
- if (m_dirtyTexture)
- updateTexture();
-
- if (m_dirtyContents)
- paint();
-
- m_dirtyGeometry = false;
- m_dirtyRenderTarget = false;
- m_dirtyTexture = false;
- m_dirtyContents = false;
-}
-
-void QSGPainterNode::updateTexture()
-{
- m_texture->setHasMipmaps(m_mipmapping);
- m_texture->setHasAlphaChannel(!m_opaquePainting);
- m_material.setTexture(m_texture);
- m_materialO.setTexture(m_texture);
-
- markDirty(DirtyMaterial);
-}
-
-void QSGPainterNode::updateGeometry()
-{
- QRectF source;
- if (m_actualRenderTarget == QQuickPaintedItem::Image)
- source = QRectF(0, 0, 1, 1);
- else
- source = QRectF(0, 0, qreal(m_size.width()) / m_fboSize.width(), qreal(m_size.height()) / m_fboSize.height());
- QRectF dest(0, 0, m_size.width(), m_size.height());
- if (m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject)
- dest = QRectF(QPointF(0, m_size.height()), QPointF(m_size.width(), 0));
- QSGGeometry::updateTexturedRectGeometry(&m_geometry,
- dest,
- source);
- markDirty(DirtyGeometry);
-}
-
-void QSGPainterNode::updateRenderTarget()
-{
- if (!m_extensionsChecked) {
- QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
- m_multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample")
- && extensions.contains("GL_EXT_framebuffer_blit");
- m_extensionsChecked = true;
- }
-
- m_dirtyContents = true;
-
- QQuickPaintedItem::RenderTarget oldTarget = m_actualRenderTarget;
- if (m_preferredRenderTarget == QQuickPaintedItem::Image) {
- m_actualRenderTarget = QQuickPaintedItem::Image;
- } else {
- if (!m_multisamplingSupported && m_smoothPainting)
- m_actualRenderTarget = QQuickPaintedItem::Image;
- else
- m_actualRenderTarget = m_preferredRenderTarget;
- }
- if (oldTarget != m_actualRenderTarget) {
- m_image = QImage();
- delete m_fbo;
- delete m_multisampledFbo;
- m_fbo = m_multisampledFbo = 0;
- }
-
- if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject ||
- m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) {
- const QOpenGLContext *ctx = m_context->glContext();
- if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
- return;
-
- if (m_fboSize.isEmpty())
- updateFBOSize();
-
- delete m_fbo;
- delete m_multisampledFbo;
- m_fbo = m_multisampledFbo = 0;
-
- if (m_smoothPainting && ctx->format().samples() && m_multisamplingSupported) {
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setSamples(8);
- m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
- m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- } else {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
- }
- } else {
- if (!m_image.isNull() && !m_dirtyGeometry)
- return;
-
- m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
- m_image.fill(Qt::transparent);
- }
-
- QSGPainterTexture *texture = new QSGPainterTexture;
- if (m_actualRenderTarget == QQuickPaintedItem::Image) {
- texture->setOwnsTexture(true);
- texture->setTextureSize(m_size);
- } else {
- texture->setTextureId(m_fbo->texture());
- texture->setOwnsTexture(false);
- texture->setTextureSize(m_fboSize);
- }
-
- if (m_texture)
- delete m_texture;
-
- texture->setTextureSize(m_size);
- m_texture = texture;
-}
-
-void QSGPainterNode::updateFBOSize()
-{
- int fboWidth;
- int fboHeight;
- if (m_fastFBOResizing) {
- fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.width()));
- fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.height()));
- } else {
- QSize minimumFBOSize = m_context->minimumFBOSize();
- fboWidth = qMax(minimumFBOSize.width(), m_size.width());
- fboHeight = qMax(minimumFBOSize.height(), m_size.height());
- }
-
- m_fboSize = QSize(fboWidth, fboHeight);
-}
-
-void QSGPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target)
-{
- if (m_preferredRenderTarget == target)
- return;
-
- m_preferredRenderTarget = target;
-
- m_dirtyRenderTarget = true;
- m_dirtyGeometry = true;
- m_dirtyTexture = true;
-}
-
-void QSGPainterNode::setSize(const QSize &size)
-{
- if (size == m_size)
- return;
-
- m_size = size;
- updateFBOSize();
-
- if (m_fbo)
- m_dirtyRenderTarget = m_fbo->size() != m_fboSize || m_dirtyRenderTarget;
- else
- m_dirtyRenderTarget = true;
- m_dirtyGeometry = true;
- m_dirtyTexture = true;
-}
-
-void QSGPainterNode::setDirty(const QRect &dirtyRect)
-{
- m_dirtyContents = true;
- m_dirtyRect = dirtyRect;
-
- if (m_mipmapping)
- m_dirtyTexture = true;
-
- markDirty(DirtyMaterial);
-}
-
-void QSGPainterNode::setOpaquePainting(bool opaque)
-{
- if (opaque == m_opaquePainting)
- return;
-
- m_opaquePainting = opaque;
- m_dirtyTexture = true;
-}
-
-void QSGPainterNode::setLinearFiltering(bool linearFiltering)
-{
- if (linearFiltering == m_linear_filtering)
- return;
-
- m_linear_filtering = linearFiltering;
-
- m_material.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
- m_materialO.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
- markDirty(DirtyMaterial);
-}
-
-void QSGPainterNode::setMipmapping(bool mipmapping)
-{
- if (mipmapping == m_mipmapping)
- return;
-
- m_mipmapping = mipmapping;
- m_material.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
- m_materialO.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
- m_dirtyTexture = true;
-}
-
-void QSGPainterNode::setSmoothPainting(bool s)
-{
- if (s == m_smoothPainting)
- return;
-
- m_smoothPainting = s;
- m_dirtyRenderTarget = true;
-}
-
-void QSGPainterNode::setFillColor(const QColor &c)
-{
- if (c == m_fillColor)
- return;
-
- m_fillColor = c;
- markDirty(DirtyMaterial);
-}
-
-void QSGPainterNode::setContentsScale(qreal s)
-{
- if (s == m_contentsScale)
- return;
-
- m_contentsScale = s;
- markDirty(DirtyMaterial);
-}
-
-void QSGPainterNode::setFastFBOResizing(bool dynamic)
-{
- m_fastFBOResizing = dynamic;
-}
-
-QImage QSGPainterNode::toImage() const
-{
- if (m_actualRenderTarget == QQuickPaintedItem::Image)
- return m_image;
- else
- return m_fbo->toImage();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgpainternode_p.h b/src/declarative/scenegraph/util/qsgpainternode_p.h
deleted file mode 100644
index 8e95107efc..0000000000
--- a/src/declarative/scenegraph/util/qsgpainternode_p.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGPAINTERNODE_P_H
-#define QSGPAINTERNODE_P_H
-
-#include "qsgnode.h"
-#include "qsgtexturematerial.h"
-#include "qsgtexture_p.h"
-
-#include <qquickpainteditem.h>
-
-#include <QtGui/qcolor.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QOpenGLFramebufferObject;
-class QOpenGLPaintDevice;
-
-class Q_DECLARATIVE_EXPORT QSGPainterTexture : public QSGPlainTexture
-{
-public:
- QSGPainterTexture();
-
- void setDirtyRect(const QRect &rect) { m_dirty_rect = rect; }
-
- void bind();
-
-private:
- QRect m_dirty_rect;
-};
-
-class Q_DECLARATIVE_EXPORT QSGPainterNode : public QSGGeometryNode
-{
-public:
- QSGPainterNode(QQuickPaintedItem *item);
- virtual ~QSGPainterNode();
-
- void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target);
-
- void setSize(const QSize &size);
- QSize size() const { return m_size; }
-
- void setDirty(const QRect &dirtyRect = QRect());
-
- void setOpaquePainting(bool opaque);
- bool opaquePainting() const { return m_opaquePainting; }
-
- void setLinearFiltering(bool linearFiltering);
- bool linearFiltering() const { return m_linear_filtering; }
-
- void setMipmapping(bool mipmapping);
- bool mipmapping() const { return m_mipmapping; }
-
- void setSmoothPainting(bool s);
- bool smoothPainting() const { return m_smoothPainting; }
-
- void setFillColor(const QColor &c);
- QColor fillColor() const { return m_fillColor; }
-
- void setContentsScale(qreal s);
- qreal contentsScale() const { return m_contentsScale; }
-
- void setFastFBOResizing(bool dynamic);
- bool fastFBOResizing() const { return m_fastFBOResizing; }
-
- QImage toImage() const;
- void update();
-
- void paint();
-
-private:
- void updateTexture();
- void updateGeometry();
- void updateRenderTarget();
- void updateFBOSize();
-
- QSGContext *m_context;
-
- QQuickPaintedItem::RenderTarget m_preferredRenderTarget;
- QQuickPaintedItem::RenderTarget m_actualRenderTarget;
-
- QQuickPaintedItem *m_item;
-
- QOpenGLFramebufferObject *m_fbo;
- QOpenGLFramebufferObject *m_multisampledFbo;
- QImage m_image;
-
- QSGOpaqueTextureMaterial m_material;
- QSGTextureMaterial m_materialO;
- QSGGeometry m_geometry;
- QSGPainterTexture *m_texture;
- QOpenGLPaintDevice *m_gl_device;
-
- QSize m_size;
- QSize m_fboSize;
- bool m_dirtyContents;
- QRect m_dirtyRect;
- bool m_opaquePainting;
- bool m_linear_filtering;
- bool m_mipmapping;
- bool m_smoothPainting;
- bool m_extensionsChecked;
- bool m_multisamplingSupported;
- bool m_fastFBOResizing;
- QColor m_fillColor;
- qreal m_contentsScale;
-
- bool m_dirtyGeometry;
- bool m_dirtyRenderTarget;
- bool m_dirtyTexture;
-};
-
-QT_END_HEADER
-
-QT_END_NAMESPACE
-
-#endif // QSGPAINTERNODE_P_H
diff --git a/src/declarative/scenegraph/util/qsgsimplematerial.h b/src/declarative/scenegraph/util/qsgsimplematerial.h
deleted file mode 100644
index b9e453abec..0000000000
--- a/src/declarative/scenegraph/util/qsgsimplematerial.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGSIMPLEMATERIAL_H
-#define QSGSIMPLEMATERIAL_H
-
-#include <qsgmaterial.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-template <typename State>
-class QSGSimpleMaterialShader : public QSGMaterialShader
-{
-public:
- void initialize() {
- QSGMaterialShader::initialize();
-
- m_id_matrix = program()->uniformLocation(uniformMatrixName());
- if (m_id_matrix < 0) {
- qFatal("QSGSimpleMaterialShader does not implement 'uniform highp mat4 %s;' in its vertex shader",
- uniformMatrixName());
- }
-
- const char *opacity = uniformOpacityName();
- if (opacity) {
- m_id_opacity = program()->uniformLocation(uniformOpacityName());
- if (m_id_opacity < 0) {
- qFatal("QSGSimpleMaterialShader does not implement 'uniform lowp float %s' in its fragment shader",
- uniformOpacityName());
- }
- } else {
- m_id_opacity = -1;
- }
-
- resolveUniforms();
- }
-
- const char *uniformMatrixName() const { return "qt_Matrix"; }
- const char *uniformOpacityName() const { return "qt_Opacity"; }
-
- void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
-
- virtual void updateState(const State *newState, const State *oldState) = 0;
-
- virtual void resolveUniforms() {}
-
- virtual QList<QByteArray> attributes() const = 0;
-
- char const *const *attributeNames() const
- {
- if (m_attribute_pointers.size())
- return m_attribute_pointers.constData();
-
- QList<QByteArray> names = attributes();
-
- // Calculate the total number of bytes needed, so we don't get rellocs and
- // bad pointers while copying over the individual names.
- // Add an extra byte pr entry for the '\0' char.
- int total = 0;
- for (int i=0; i<names.size(); ++i)
- total += names.at(i).size() + 1;
- m_attribute_name_data.reserve(total);
-
- // Copy over the names
- for (int i=0; i<names.size(); ++i) {
- m_attribute_pointers << m_attribute_name_data.constData() + m_attribute_name_data.size();
- m_attribute_name_data.append(names.at(i));
- m_attribute_name_data.append('\0');
- }
-
- // Append the "null" terminator
- m_attribute_pointers << 0;
-
- return m_attribute_pointers.constData();
- }
-
-private:
- int m_id_matrix;
- int m_id_opacity;
-
- mutable QByteArray m_attribute_name_data;
- mutable QVector<const char *> m_attribute_pointers;
-};
-
-#define QSG_DECLARE_SIMPLE_SHADER(Shader, State) \
-static QSGMaterialShader *createShader() \
-{ \
- return new Shader; \
-} \
-public: \
-static QSGSimpleMaterial<State> *createMaterial() \
-{ \
- return new QSGSimpleMaterial<State>(createShader); \
-}
-
-
-typedef QSGMaterialShader *(*PtrShaderCreateFunc)();
-
-
-template <typename State>
-class QSGSimpleMaterial : public QSGMaterial
-{
-
-public:
- QSGSimpleMaterial(const State &state, PtrShaderCreateFunc func)
- : m_state(state)
- , m_func(func)
- {
- }
-
- QSGSimpleMaterial(PtrShaderCreateFunc func)
- : m_func(func)
- {
- }
-
- QSGMaterialShader *createShader() const { return m_func(); }
- QSGMaterialType *type() const { return &m_type; }
-
- State *state() { return &m_state; }
- const State *state() const { return &m_state; }
-
-private:
- static QSGMaterialType m_type;
- State m_state;
- PtrShaderCreateFunc m_func;
-};
-
-#define QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State) \
-static QSGMaterialShader *createShader() \
-{ \
- return new Shader; \
-} \
-public: \
-static QSGSimpleMaterialComparableMaterial<State> *createMaterial() \
-{ \
- return new QSGSimpleMaterialComparableMaterial<State>(createShader); \
-}
-
-template <typename State>
-class QSGSimpleMaterialComparableMaterial : public QSGSimpleMaterial<State>
-{
-
-public:
- QSGSimpleMaterialComparableMaterial(const State &state, PtrShaderCreateFunc func)
- : QSGSimpleMaterial<State>(state, func) {}
-
- QSGSimpleMaterialComparableMaterial(PtrShaderCreateFunc func)
- : QSGSimpleMaterial<State>(func) {}
-
- int compare(const QSGMaterial *other) const {
- return QSGSimpleMaterialComparableMaterial<State>::state()->compare(static_cast<const QSGSimpleMaterialComparableMaterial<State> *>(other)->state());
- }
-};
-
-
-template <typename State>
-QSGMaterialType QSGSimpleMaterial<State>::m_type;
-
-
-template <typename State>
-Q_INLINE_TEMPLATE void QSGSimpleMaterialShader<State>::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
-{
- if (state.isMatrixDirty())
- program()->setUniformValue(m_id_matrix, state.combinedMatrix());
- if (state.isOpacityDirty() && m_id_opacity >= 0)
- program()->setUniformValue(m_id_opacity, state.opacity());
-
- State *ns = static_cast<QSGSimpleMaterial<State> *>(newMaterial)->state();
- State *old = 0;
- if (oldMaterial)
- old = static_cast<QSGSimpleMaterial<State> *>(oldMaterial)->state();
- updateState(ns, old);
-}
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-
-#endif
diff --git a/src/declarative/scenegraph/util/qsgsimplerectnode.h b/src/declarative/scenegraph/util/qsgsimplerectnode.h
deleted file mode 100644
index c06db07f93..0000000000
--- a/src/declarative/scenegraph/util/qsgsimplerectnode.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 SOLIDRECTNODE_H
-#define SOLIDRECTNODE_H
-
-#include "qsgnode.h"
-#include "qsgflatcolormaterial.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGSimpleRectNode : public QSGGeometryNode
-{
-public:
- QSGSimpleRectNode(const QRectF &rect, const QColor &color);
- QSGSimpleRectNode();
-
- void setRect(const QRectF &rect);
- inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
- QRectF rect() const;
-
- void setColor(const QColor &color);
- QColor color() const;
-
-private:
- QSGFlatColorMaterial m_material;
- QSGGeometry m_geometry;
- void *reserved;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // SOLIDRECTNODE_H
diff --git a/src/declarative/scenegraph/util/qsgsimpletexturenode.cpp b/src/declarative/scenegraph/util/qsgsimpletexturenode.cpp
deleted file mode 100644
index a0d6616371..0000000000
--- a/src/declarative/scenegraph/util/qsgsimpletexturenode.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgsimpletexturenode.h"
-
-QT_BEGIN_NAMESPACE
-
-static void qsgsimpletexturenode_update(QSGGeometry *g,
- QSGTexture *texture,
- const QRectF &rect)
-{
- if (!texture)
- return;
-
- QSize ts = texture->textureSize();
- QRectF sourceRect(0, 0, ts.width(), ts.height());
- QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect));
-}
-
-/*!
- \class QSGSimpleTextureNode
- \brief The QSGSimpleTextureNode class is provided for convenience to easily draw
- textured content using the QML scene graph.
-
- \inmodule QtDeclarative
-
- \warning The simple texture node class must have a texture before being
- added to the scene graph to be rendered.
-*/
-
-/*!
- Constructs a new simple texture node
- */
-QSGSimpleTextureNode::QSGSimpleTextureNode()
- : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
-{
- setGeometry(&m_geometry);
- setMaterial(&m_material);
- setOpaqueMaterial(&m_opaque_material);
-}
-
-/*!
- Sets the filtering to be used for this texture node to \a filtering.
-
- For smooth scaling, use QSGTexture::Linear; for normal scaling, use
- QSGTexture::Nearest.
- */
-void QSGSimpleTextureNode::setFiltering(QSGTexture::Filtering filtering)
-{
- if (m_material.filtering() == filtering)
- return;
-
- m_material.setFiltering(filtering);
- m_opaque_material.setFiltering(filtering);
- markDirty(DirtyMaterial);
-}
-
-
-/*!
- Returns the filtering currently set on this texture node
- */
-QSGTexture::Filtering QSGSimpleTextureNode::filtering() const
-{
- return m_material.filtering();
-}
-
-
-/*!
- Sets the target rect of this texture node to \a r
- */
-void QSGSimpleTextureNode::setRect(const QRectF &r)
-{
- if (m_rect == r)
- return;
- m_rect = r;
- qsgsimpletexturenode_update(&m_geometry, texture(), m_rect);
- markDirty(DirtyGeometry);
-}
-
-
-/*!
- Returns the target rect of this texture node.
- */
-QRectF QSGSimpleTextureNode::rect() const
-{
- return m_rect;
-}
-
-/*!
- Sets the texture of this texture node to \a texture.
-
- \warning A texture node must have a texture before being added
- to the scenegraph to be rendered.
- */
-void QSGSimpleTextureNode::setTexture(QSGTexture *texture)
-{
- if (m_material.texture() == texture)
- return;
- m_material.setTexture(texture);
- m_opaque_material.setTexture(texture);
- qsgsimpletexturenode_update(&m_geometry, texture, m_rect);
- markDirty(DirtyMaterial);
-}
-
-
-
-/*!
- Returns the texture for this texture node
- */
-QSGTexture *QSGSimpleTextureNode::texture() const
-{
- return m_material.texture();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgsimpletexturenode.h b/src/declarative/scenegraph/util/qsgsimpletexturenode.h
deleted file mode 100644
index db58c30b5f..0000000000
--- a/src/declarative/scenegraph/util/qsgsimpletexturenode.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGSIMPLETEXTURENODE_H
-#define QSGSIMPLETEXTURENODE_H
-
-#include "qsgnode.h"
-#include "qsggeometry.h"
-#include "qsgtexturematerial.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGSimpleTextureNode : public QSGGeometryNode
-{
-public:
- QSGSimpleTextureNode();
-
- void setRect(const QRectF &rect);
- inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
- QRectF rect() const;
-
- void setTexture(QSGTexture *texture);
- QSGTexture *texture() const;
-
- void setFiltering(QSGTexture::Filtering filtering);
- QSGTexture::Filtering filtering() const;
-
-private:
- QSGGeometry m_geometry;
- QSGOpaqueTextureMaterial m_opaque_material;
- QSGTextureMaterial m_material;
-
- QRectF m_rect;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGSIMPLETEXTURENODE_H
diff --git a/src/declarative/scenegraph/util/qsgtexture.cpp b/src/declarative/scenegraph/util/qsgtexture.cpp
deleted file mode 100644
index e2219e54f5..0000000000
--- a/src/declarative/scenegraph/util/qsgtexture.cpp
+++ /dev/null
@@ -1,541 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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$
-**
-****************************************************************************/
-
-#define GL_GLEXT_PROTOTYPES
-
-#include <private/qsgtexture_p.h>
-#include <qopenglfunctions.h>
-#include <private/qsgcontext_p.h>
-#include <qthread.h>
-#include <private/qdeclarativedebugtrace_p.h>
-
-#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC))
-#include <execinfo.h>
-#include <QHash>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-inline static bool isPowerOfTwo(int x)
-{
- // Assumption: x >= 1
- return x == (x & -x);
-}
-
-QSGTexturePrivate::QSGTexturePrivate()
- : wrapChanged(false)
- , filteringChanged(false)
- , horizontalWrap(QSGTexture::ClampToEdge)
- , verticalWrap(QSGTexture::ClampToEdge)
- , mipmapMode(QSGTexture::None)
- , filterMode(QSGTexture::Nearest)
-{
-}
-
-#ifndef QT_NO_DEBUG
-
-static int qt_debug_texture_count = 0;
-
-#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
-
-#define BACKTRACE_SIZE 20
-class SGTextureTraceItem
-{
-public:
- void *backTrace[BACKTRACE_SIZE];
- size_t backTraceSize;
-};
-
-static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
-#endif
-
-inline static void qt_debug_print_texture_count()
-{
- qDebug("Number of leaked textures: %i", qt_debug_texture_count);
- qt_debug_texture_count = -1;
-
-#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
- if (qmlDebugLeakBacktrace()) {
- while (!qt_debug_allocated_textures.isEmpty()) {
- QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
- QSGTexture* texture = it.key();
- SGTextureTraceItem* item = it.value();
-
- qt_debug_allocated_textures.erase(it);
-
- qDebug() << "------";
- qDebug() << "Leaked" << texture << "backtrace:";
-
- char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
-
- if (symbols) {
- for (int i=0; i<(int) item->backTraceSize; i++)
- qDebug("Backtrace <%02d>: %s", i, symbols[i]);
- free(symbols);
- }
-
- qDebug() << "------";
-
- delete item;
- }
- }
-#endif
-}
-
-inline static void qt_debug_add_texture(QSGTexture* texture)
-{
-#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
- if (qmlDebugLeakBacktrace()) {
- SGTextureTraceItem* item = new SGTextureTraceItem;
- item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
- qt_debug_allocated_textures.insert(texture, item);
- }
-#else
- Q_UNUSED(texture);
-#endif // Q_OS_LINUX
-
- ++qt_debug_texture_count;
-
- static bool atexit_registered = false;
- if (!atexit_registered) {
- atexit(qt_debug_print_texture_count);
- atexit_registered = true;
- }
-}
-
-static void qt_debug_remove_texture(QSGTexture* texture)
-{
-#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
- if (qmlDebugLeakBacktrace()) {
- SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
- if (item) {
- qt_debug_allocated_textures.remove(texture);
- delete item;
- }
- }
-#else
- Q_UNUSED(texture)
-#endif
-
- --qt_debug_texture_count;
-
- if (qt_debug_texture_count < 0)
- qDebug("Material destroyed after qt_debug_print_texture_count() was called.");
-}
-
-#endif // QT_NO_DEBUG
-
-
-QSGTexture::QSGTexture()
- : QObject(*(new QSGTexturePrivate))
-{
-#ifndef QT_NO_DEBUG
- qt_debug_add_texture(this);
-#endif
-}
-
-QSGTexture::~QSGTexture()
-{
-#ifndef QT_NO_DEBUG
- qt_debug_remove_texture(this);
-#endif
-}
-
-
-/*!
- \fn void QSGTexture::bind()
-
- Call this function to bind this texture to the current texture
- target.
-
- Binding a texture may also include uploading the texture data from
- a previously set QImage.
-
- \warning This function can only be called from the rendering thread.
- */
-
-/*!
- This function returns a copy of the current texture which is removed
- from its atlas.
-
- The current texture remains unchanged, so texture coordinates do not
- need to be updated.
-
- Removing a texture from an atlas is primarily useful when passing
- it to a shader that operates on the texture coordinates 0-1 instead
- of the texture subrect inside the atlas.
-
- If the texture is not part of a texture atlas, this function returns 0.
-
- Implementations of this function are recommended to return the same instance
- for multiple calls to limit memory usage.
-
- \warning This function can only be called from the rendering thread.
- */
-
-QSGTexture *QSGTexture::removedFromAtlas() const
-{
- Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
- return 0;
-}
-
-/*!
- Returns weither this texture is part of an atlas or not.
-
- The default implementation returns false.
- */
-bool QSGTexture::isAtlasTexture() const
-{
- return false;
-}
-
-/*!
- \fn int QSGTexture::textureId() const
-
- Returns the OpenGL texture id for this texture.
-
- The default value is 0, indicating that it is an invalid texture id.
-
- The function should at all times return the correct texture id.
-
- \warning This function can only be called from the rendering thread.
- */
-
-
-
-/*!
- Returns the rectangle inside textureSize() that this texture
- represents in normalized coordinates.
-
- The default implementation returns a rect at position (0, 0) with
- width and height of 1.
- */
-QRectF QSGTexture::textureSubRect() const
-{
- return QRectF(0, 0, 1, 1);
-}
-
-/*!
- \fn bool QSGTexture::hasMipmaps() const
-
- Returns true if the texture data contains mipmap levels.
- */
-
-
-/*!
- Sets the mipmap sampling mode to be used for the upcoming bind() call to \a filter.
-
- Setting the mipmap filtering has no effect it the texture does not have mipmaps.
-
- \sa hasMipmaps()
- */
-void QSGTexture::setMipmapFiltering(Filtering filter)
-{
- Q_D(QSGTexture);
- if (d->mipmapMode != (uint) filter) {
- d->mipmapMode = filter;
- d->filteringChanged = true;
- }
-}
-
-/*!
- Returns whether mipmapping should be used when sampling from this texture.
- */
-QSGTexture::Filtering QSGTexture::mipmapFiltering() const
-{
- return (QSGTexture::Filtering) d_func()->mipmapMode;
-}
-
-
-/*!
- Sets the sampling mode to be used for the upcoming bind() call to \a filter.
- */
-void QSGTexture::setFiltering(QSGTexture::Filtering filter)
-{
- Q_D(QSGTexture);
- if (d->filterMode != (uint) filter) {
- d->filterMode = filter;
- d->filteringChanged = true;
- }
-}
-
-QSGTexture::Filtering QSGTexture::filtering() const
-{
- return (QSGTexture::Filtering) d_func()->filterMode;
-}
-
-
-
-/*!
- Sets the horizontal wrap mode to be used for the upcoming bind() call to \a hwrap
- */
-
-void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
-{
- Q_D(QSGTexture);
- if ((uint) hwrap != d->horizontalWrap) {
- d->horizontalWrap = hwrap;
- d->wrapChanged = true;
- }
-}
-
-QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
-{
- return (QSGTexture::WrapMode) d_func()->horizontalWrap;
-}
-
-
-
-void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
-{
- Q_D(QSGTexture);
- if ((uint) vwrap != d->verticalWrap) {
- d->verticalWrap = vwrap;
- d->wrapChanged = true;
- }
-}
-
-QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
-{
- return (QSGTexture::WrapMode) d_func()->verticalWrap;
-}
-
-
-/*!
- Update the texture state to match the filtering, mipmap and wrap options
- currently set.
-
- If \a force is true, all properties will be updated regardless of weither
- they have changed or not.
- */
-void QSGTexture::updateBindOptions(bool force)
-{
- Q_D(QSGTexture);
- if (force || d->filteringChanged) {
- bool linear = d->filterMode == Linear;
- GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
- GLint magFilter = linear ? GL_LINEAR : GL_NEAREST;
-
- if (hasMipmaps()) {
- if (d->mipmapMode == Nearest)
- minFilter = linear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST;
- else if (d->mipmapMode == Linear)
- minFilter = linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
- d->filteringChanged = false;
- }
-
- if (force || d->wrapChanged) {
-#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2)
- if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) {
- bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
- QSize size = textureSize();
- bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
- if (!npotSupported && isNpot)
- qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
- }
-#endif
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, d->horizontalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, d->verticalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
- d->wrapChanged = false;
- }
-}
-
-QSGPlainTexture::QSGPlainTexture()
- : QSGTexture()
- , m_texture_id(0)
- , m_has_alpha(false)
- , m_has_mipmaps(false)
- , m_dirty_bind_options(false)
- , m_owns_texture(true)
- , m_mipmaps_generated(false)
-{
-}
-
-
-QSGPlainTexture::~QSGPlainTexture()
-{
- if (m_texture_id && m_owns_texture)
- glDeleteTextures(1, &m_texture_id);
-}
-
-#ifdef QT_OPENGL_ES
-static void swizzleBGRAToRGBA(QImage *image)
-{
- const int width = image->width();
- const int height = image->height();
- for (int i = 0; i < height; ++i) {
- uint *p = (uint *) image->scanLine(i);
- for (int x = 0; x < width; ++x)
- p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
- }
-}
-#endif
-
-void QSGPlainTexture::setImage(const QImage &image)
-{
- m_image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
-#ifdef QT_OPENGL_ES
- swizzleBGRAToRGBA(&m_image);
-#endif
-
- m_texture_size = image.size();
- m_has_alpha = image.hasAlphaChannel();
- m_dirty_texture = true;
- m_dirty_bind_options = true;
- }
-
-int QSGPlainTexture::textureId() const
-{
- if (m_dirty_texture) {
- if (m_image.isNull()) {
- // The actual texture and id will be updated/deleted in a later bind()
- // or ~QSGPlainTexture so just keep it minimal here.
- return 0;
- } else {
- // Generate a texture id for use later and return it.
- glGenTextures(1, &const_cast<QSGPlainTexture *>(this)->m_texture_id);
- return m_texture_id;
- }
- }
- return m_texture_id;
-}
-
-void QSGPlainTexture::setTextureId(int id)
-{
- if (m_texture_id && m_owns_texture)
- glDeleteTextures(1, &m_texture_id);
-
- m_texture_id = id;
- m_dirty_texture = false;
- m_dirty_bind_options = true;
- m_image = QImage();
- m_mipmaps_generated = false;
-}
-
-void QSGPlainTexture::setHasMipmaps(bool mm)
-{
- m_has_mipmaps = mm;
- m_mipmaps_generated = false;
-}
-
-
-void QSGPlainTexture::bind()
-{
- if (!m_dirty_texture) {
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
- if (m_has_mipmaps && !m_mipmaps_generated) {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
- m_mipmaps_generated = true;
- }
- updateBindOptions(m_dirty_bind_options);
- m_dirty_bind_options = false;
- return;
- }
-
- m_dirty_texture = false;
-
-
- if (m_image.isNull()) {
- if (m_texture_id && m_owns_texture)
- glDeleteTextures(1, &m_texture_id);
- m_texture_id = 0;
- m_texture_size = QSize();
- m_has_mipmaps = false;
- m_has_alpha = false;
- return;
- }
-
- if (m_texture_id == 0)
- glGenTextures(1, &m_texture_id);
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
-
- // ### TODO: check for out-of-memory situations...
- int w = m_image.width();
- int h = m_image.height();
-
-#ifdef QT_OPENGL_ES
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_image.constBits());
-#else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_image.constBits());
-#endif
-
- if (m_has_mipmaps) {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
- m_mipmaps_generated = true;
- }
-
- m_texture_size = QSize(w, h);
- m_texture_rect = QRectF(0, 0, 1, 1);
-
- updateBindOptions(m_dirty_bind_options);
- m_dirty_bind_options = false;
-}
-
-
-/*!
- \class QSGDynamicTexture
- \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
- such as content that is rendered to FBO's.
-
- To update the content of the texture, call updateTexture() explicitly. Simply calling bind()
- will not update the texture.
- */
-
-
-/*!
- \fn bool QSGDynamicTexture::updateTexture()
-
- Call this function to explicitely update the dynamic texture. Calling bind() will bind
- the content that was previously updated.
-
- The function returns true if the texture was changed as a resul of the update; otherwise
- returns false.
- */
-
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgtexture.h b/src/declarative/scenegraph/util/qsgtexture.h
deleted file mode 100644
index 1a49fb941e..0000000000
--- a/src/declarative/scenegraph/util/qsgtexture.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGTEXTURE_H
-#define QSGTEXTURE_H
-
-#include <QObject>
-#include <QImage>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGTexturePrivate;
-class Q_DECLARATIVE_EXPORT QSGTexture : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QSGTexture)
-
-public:
- QSGTexture();
- ~QSGTexture();
-
- enum WrapMode {
- Repeat,
- ClampToEdge
- };
-
- enum Filtering {
- None,
- Nearest,
- Linear
- };
-
- virtual int textureId() const = 0;
- virtual QSize textureSize() const = 0;
- virtual bool hasAlphaChannel() const = 0;
- virtual bool hasMipmaps() const = 0;
-
- virtual QRectF textureSubRect() const;
-
- virtual bool isAtlasTexture() const;
-
- virtual QSGTexture *removedFromAtlas() const;
-
- virtual void bind() = 0;
- void updateBindOptions(bool force = false);
-
- void setMipmapFiltering(Filtering filter);
- QSGTexture::Filtering mipmapFiltering() const;
-
- void setFiltering(Filtering filter);
- QSGTexture::Filtering filtering() const;
-
- void setHorizontalWrapMode(WrapMode hwrap);
- QSGTexture::WrapMode horizontalWrapMode() const;
-
- void setVerticalWrapMode(WrapMode vwrap);
- QSGTexture::WrapMode verticalWrapMode() const;
-
- inline QRectF convertToNormalizedSourceRect(const QRectF &rect) const;
-
-protected:
- QSGTexture(QSGTexturePrivate &dd);
-};
-
-QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
-{
- QSize s = textureSize();
- QRectF r = textureSubRect();
-
- qreal sx = r.width() / s.width();
- qreal sy = r.height() / s.height();
-
- return QRectF(r.x() + rect.x() * sx,
- r.y() + rect.y() * sy,
- rect.width() * sx,
- rect.height() * sy);
-}
-
-
-class Q_DECLARATIVE_EXPORT QSGDynamicTexture : public QSGTexture
-{
- Q_OBJECT
-public:
- virtual bool updateTexture() = 0;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/util/qsgtexture_p.h b/src/declarative/scenegraph/util/qsgtexture_p.h
deleted file mode 100644
index f14508fd25..0000000000
--- a/src/declarative/scenegraph/util/qsgtexture_p.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGTEXTURE_P_H
-#define QSGTEXTURE_P_H
-
-#include <private/qobject_p.h>
-
-#include <QtGui/qopengl.h>
-
-#include "qsgtexture.h"
-#include <private/qsgcontext_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGTexturePrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QSGTexture);
-public:
- QSGTexturePrivate();
-
- uint wrapChanged : 1;
- uint filteringChanged : 1;
-
- uint horizontalWrap : 1;
- uint verticalWrap : 1;
- uint mipmapMode : 2;
- uint filterMode : 2;
-};
-
-class Q_DECLARATIVE_EXPORT QSGPlainTexture : public QSGTexture
-{
- Q_OBJECT
-public:
- QSGPlainTexture();
- virtual ~QSGPlainTexture();
-
- void setOwnsTexture(bool owns) { m_owns_texture = owns; }
- bool ownsTexture() const { return m_owns_texture; }
-
- void setTextureId(int id);
- int textureId() const;
- void setTextureSize(const QSize &size) { m_texture_size = size; }
- QSize textureSize() const { return m_texture_size; }
-
- void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
- bool hasAlphaChannel() const { return m_has_alpha; }
-
- void setHasMipmaps(bool mm);
- bool hasMipmaps() const { return m_has_mipmaps; }
-
- void setImage(const QImage &image);
- const QImage &image() { return m_image; }
-
- virtual void bind();
-
- static QSGPlainTexture *fromImage(const QImage &image) {
- QSGPlainTexture *t = new QSGPlainTexture();
- t->setImage(image);
- return t;
- }
-
-protected:
- QImage m_image;
-
- GLuint m_texture_id;
- QSize m_texture_size;
- QRectF m_texture_rect;
-
- uint m_has_alpha : 1;
- uint m_has_mipmaps : 1;
- uint m_dirty_texture : 1;
- uint m_dirty_bind_options : 1;
- uint m_owns_texture : 1;
- uint m_mipmaps_generated : 1;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSGTEXTURE_P_H
diff --git a/src/declarative/scenegraph/util/qsgtexturematerial.h b/src/declarative/scenegraph/util/qsgtexturematerial.h
deleted file mode 100644
index be6ba7a8ab..0000000000
--- a/src/declarative/scenegraph/util/qsgtexturematerial.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 TEXTUREMATERIAL_H
-#define TEXTUREMATERIAL_H
-
-#include "qsgmaterial.h"
-#include <qsgtexture.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class Q_DECLARATIVE_EXPORT QSGOpaqueTextureMaterial : public QSGMaterial
-{
-public:
- QSGOpaqueTextureMaterial();
-
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
-
- void setTexture(QSGTexture *texture);
- QSGTexture *texture() const { return m_texture; }
-
- void setMipmapFiltering(QSGTexture::Filtering filtering) { m_mipmap_filtering = filtering; }
- QSGTexture::Filtering mipmapFiltering() const { return (QSGTexture::Filtering) m_mipmap_filtering; }
-
- void setFiltering(QSGTexture::Filtering filtering) { m_filtering = filtering; }
- QSGTexture::Filtering filtering() const { return (QSGTexture::Filtering) m_filtering; }
-
- void setHorizontalWrapMode(QSGTexture::WrapMode mode) { m_horizontal_wrap = mode; }
- QSGTexture::WrapMode horizontalWrapMode() const { return (QSGTexture::WrapMode) m_horizontal_wrap; }
-
- void setVerticalWrapMode(QSGTexture::WrapMode mode) { m_vertical_wrap = mode; }
- QSGTexture::WrapMode verticalWrapMode() const { return (QSGTexture::WrapMode) m_vertical_wrap; }
-
-protected:
- QSGTexture *m_texture;
-
- uint m_filtering: 2;
- uint m_mipmap_filtering: 2;
- uint m_horizontal_wrap : 1;
- uint m_vertical_wrap: 1;
-
- uint m_reserved : 26;
-};
-
-
-class Q_DECLARATIVE_EXPORT QSGTextureMaterial : public QSGOpaqueTextureMaterial
-{
-public:
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // TEXTUREMATERIAL_H
diff --git a/src/declarative/scenegraph/util/qsgtexturematerial_p.h b/src/declarative/scenegraph/util/qsgtexturematerial_p.h
deleted file mode 100644
index a549f841d8..0000000000
--- a/src/declarative/scenegraph/util/qsgtexturematerial_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 TEXTUREMATERIAL_P_H
-#define TEXTUREMATERIAL_P_H
-
-#include "qsgtexturematerial.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGOpaqueTextureMaterialShader : public QSGMaterialShader
-{
-public:
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-
- static QSGMaterialType type;
-
-protected:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- int m_matrix_id;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSGTEXTUREMATERIAL_P_H
diff --git a/src/declarative/scenegraph/util/qsgtextureprovider_p.h b/src/declarative/scenegraph/util/qsgtextureprovider_p.h
deleted file mode 100644
index ebb6ca8507..0000000000
--- a/src/declarative/scenegraph/util/qsgtextureprovider_p.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QSGTEXTUREPROVIDER_H
-#define QSGTEXTUREPROVIDER_H
-
-#include "qsgtexture.h"
-#include "qobject.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGTextureProvider : public QObject
-{
- Q_OBJECT
-public:
- virtual QSGTexture *texture() const = 0;
-
-Q_SIGNALS:
- void textureChanged();
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp b/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp
deleted file mode 100644
index 78cef55215..0000000000
--- a/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qsgvertexcolormaterial.h"
-
-#include <qopenglshaderprogram.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGVertexColorMaterialShader : public QSGMaterialShader
-{
-public:
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
-
- static QSGMaterialType type;
-
-private:
- virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
- int m_matrix_id;
- int m_opacity_id;
-};
-
-QSGMaterialType QSGVertexColorMaterialShader::type;
-
-void QSGVertexColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
-{
- if (!(newEffect->flags() & QSGMaterial::Blending) || state.isOpacityDirty())
- program()->setUniformValue(m_opacity_id, state.opacity());
-
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
-}
-
-char const *const *QSGVertexColorMaterialShader::attributeNames() const
-{
- static const char *const attr[] = { "vertexCoord", "vertexColor", 0 };
- return attr;
-}
-
-void QSGVertexColorMaterialShader::initialize()
-{
- m_matrix_id = program()->uniformLocation("matrix");
- m_opacity_id = program()->uniformLocation("opacity");
-}
-
-const char *QSGVertexColorMaterialShader::vertexShader() const {
- return
- "attribute highp vec4 vertexCoord; \n"
- "attribute highp vec4 vertexColor; \n"
- "uniform highp mat4 matrix; \n"
- "uniform highp float opacity; \n"
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " gl_Position = matrix * vertexCoord; \n"
- " color = vertexColor * opacity; \n"
- "}";
-}
-
-const char *QSGVertexColorMaterialShader::fragmentShader() const {
- return
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color; \n"
- "}";
-}
-
-
-
-/*!
- \class QSGVertexColorMaterial
- \brief The QSGVertexColorMaterial class provides a convenient way of rendering per-vertex
- colored geometry in the scene graph.
-
- \inmodule QtDeclarative
-
- The vertex color material will give each vertex in a geometry a color. Pixels between
- vertices will be linearly interpolated. The colors can contain transparency.
-
- The geometry to be rendered with vertex color must have the following layout. Attribute
- position 0 must contain vertices. Attribute position 1 must contain colors, a tuple of
- 4 values with RGBA layout. Both floats in the range of 0 to 1 and unsigned bytes in
- the range 0 to 255 are valid for the color values. The
- QSGGeometry::defaultAttributes_ColoredPoint2D() constructs an attribute set
- compatible with this material.
-
- The vertex color material respects both current opacity and current matrix when
- updating it's rendering state.
- */
-
-
-QSGVertexColorMaterial::QSGVertexColorMaterial()
-{
- setFlag(Blending, true);
-}
-
-
-/*!
- int QSGVertexColorMaterial::compare() const
-
- As the vertex color material has all its state in the vertex attributes,
- all materials will be equal.
-
- \internal
- */
-
-int QSGVertexColorMaterial::compare(const QSGMaterial * /* other */) const
-{
- return 0;
-}
-
-/*!
- \internal
- */
-
-QSGMaterialType *QSGVertexColorMaterial::type() const
-{
- return &QSGVertexColorMaterialShader::type;
-}
-
-
-
-/*!
- \internal
- */
-
-QSGMaterialShader *QSGVertexColorMaterial::createShader() const
-{
- return new QSGVertexColorMaterialShader;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgvertexcolormaterial.h b/src/declarative/scenegraph/util/qsgvertexcolormaterial.h
deleted file mode 100644
index c244f63834..0000000000
--- a/src/declarative/scenegraph/util/qsgvertexcolormaterial.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 VERTEXCOLORMATERIAL_H
-#define VERTEXCOLORMATERIAL_H
-
-#include <qsgmaterial.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class Q_DECLARATIVE_EXPORT QSGVertexColorMaterial : public QSGMaterial
-{
-public:
- QSGVertexColorMaterial();
-
- int compare(const QSGMaterial *other) const;
-
-protected:
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // VERTEXCOLORMATERIAL_H
diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h
deleted file mode 100644
index c84af5a53e..0000000000
--- a/src/declarative/util/qdeclarativeanimation_p.h
+++ /dev/null
@@ -1,458 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEANIMATION_H
-#define QDECLARATIVEANIMATION_H
-
-#include "qdeclarativestate_p.h"
-#include <QtGui/qvector3d.h>
-
-#include <qdeclarativepropertyvaluesource.h>
-#include <qdeclarative.h>
-#include <qdeclarativescriptstring.h>
-
-#include <QtCore/qvariant.h>
-#include <QtCore/qeasingcurve.h>
-#include <QtCore/QAbstractAnimation>
-#include <QtGui/qcolor.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeAbstractAnimationPrivate;
-class QDeclarativeAnimationGroup;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeAbstractAnimation)
-
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_INTERFACES(QDeclarativePropertyValueSource)
- Q_ENUMS(Loops)
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
- Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged)
- Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopCountChanged)
- Q_CLASSINFO("DefaultMethod", "start()")
-
-public:
- QDeclarativeAbstractAnimation(QObject *parent=0);
- virtual ~QDeclarativeAbstractAnimation();
-
- enum Loops { Infinite = -2 };
-
- bool isRunning() const;
- void setRunning(bool);
- bool isPaused() const;
- void setPaused(bool);
- bool alwaysRunToEnd() const;
- void setAlwaysRunToEnd(bool);
-
- int loops() const;
- void setLoops(int);
-
- int currentTime();
- void setCurrentTime(int);
-
- QDeclarativeAnimationGroup *group() const;
- void setGroup(QDeclarativeAnimationGroup *);
-
- void setDefaultTarget(const QDeclarativeProperty &);
- void setDisableUserControl();
-
- void classBegin();
- void componentComplete();
-
-Q_SIGNALS:
- void started();
- void completed();
- void runningChanged(bool);
- void pausedChanged(bool);
- void alwaysRunToEndChanged(bool);
- void loopCountChanged(int);
-
-public Q_SLOTS:
- void restart();
- void start();
- void pause();
- void resume();
- void stop();
- void complete();
-
-protected:
- QDeclarativeAbstractAnimation(QDeclarativeAbstractAnimationPrivate &dd, QObject *parent);
-
-public:
- enum TransitionDirection { Forward, Backward };
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation() = 0;
-
-private Q_SLOTS:
- void timelineComplete();
- void componentFinalized();
-private:
- virtual void setTarget(const QDeclarativeProperty &);
- void notifyRunningChanged(bool running);
- friend class QDeclarativeBehavior;
-
-
-};
-
-class QDeclarativePauseAnimationPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativePauseAnimation : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePauseAnimation)
-
- Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
-
-public:
- QDeclarativePauseAnimation(QObject *parent=0);
- virtual ~QDeclarativePauseAnimation();
-
- int duration() const;
- void setDuration(int);
-
-Q_SIGNALS:
- void durationChanged(int);
-
-protected:
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QDeclarativeScriptActionPrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeScriptAction : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeScriptAction)
-
- Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
- Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName)
-
-public:
- QDeclarativeScriptAction(QObject *parent=0);
- virtual ~QDeclarativeScriptAction();
-
- QDeclarativeScriptString script() const;
- void setScript(const QDeclarativeScriptString &);
-
- QString stateChangeScriptName() const;
- void setStateChangeScriptName(const QString &);
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QDeclarativePropertyActionPrivate;
-class QDeclarativePropertyAction : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyAction)
-
- Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
- Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
- Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
- Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
- Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
-
-public:
- QDeclarativePropertyAction(QObject *parent=0);
- virtual ~QDeclarativePropertyAction();
-
- QObject *target() const;
- void setTarget(QObject *);
-
- QString property() const;
- void setProperty(const QString &);
-
- QString properties() const;
- void setProperties(const QString &);
-
- QDeclarativeListProperty<QObject> targets();
- QDeclarativeListProperty<QObject> exclude();
-
- QVariant value() const;
- void setValue(const QVariant &);
-
-Q_SIGNALS:
- void valueChanged(const QVariant &);
- void propertiesChanged(const QString &);
- void targetChanged();
- void propertyChanged();
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QDeclarativePropertyAnimationPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativePropertyAnimation : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
-
- Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
- Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged)
- Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged)
- Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
- Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
- Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
- Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
- Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
-
-public:
- QDeclarativePropertyAnimation(QObject *parent=0);
- virtual ~QDeclarativePropertyAnimation();
-
- virtual int duration() const;
- virtual void setDuration(int);
-
- QVariant from() const;
- void setFrom(const QVariant &);
-
- QVariant to() const;
- void setTo(const QVariant &);
-
- QEasingCurve easing() const;
- void setEasing(const QEasingCurve &);
-
- QObject *target() const;
- void setTarget(QObject *);
-
- QString property() const;
- void setProperty(const QString &);
-
- QString properties() const;
- void setProperties(const QString &);
-
- QDeclarativeListProperty<QObject> targets();
- QDeclarativeListProperty<QObject> exclude();
-
-protected:
- QDeclarativePropertyAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent);
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-
-Q_SIGNALS:
- void durationChanged(int);
- void fromChanged(QVariant);
- void toChanged(QVariant);
- void easingChanged(const QEasingCurve &);
- void propertiesChanged(const QString &);
- void targetChanged();
- void propertyChanged();
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeColorAnimation : public QDeclarativePropertyAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
- Q_PROPERTY(QColor from READ from WRITE setFrom)
- Q_PROPERTY(QColor to READ to WRITE setTo)
-
-public:
- QDeclarativeColorAnimation(QObject *parent=0);
- virtual ~QDeclarativeColorAnimation();
-
- QColor from() const;
- void setFrom(const QColor &);
-
- QColor to() const;
- void setTo(const QColor &);
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeNumberAnimation : public QDeclarativePropertyAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
-
- Q_PROPERTY(qreal from READ from WRITE setFrom)
- Q_PROPERTY(qreal to READ to WRITE setTo)
-
-public:
- QDeclarativeNumberAnimation(QObject *parent=0);
- virtual ~QDeclarativeNumberAnimation();
-
- qreal from() const;
- void setFrom(qreal);
-
- qreal to() const;
- void setTo(qreal);
-
-protected:
- QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent);
-
-private:
- void init();
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
-
- Q_PROPERTY(QVector3D from READ from WRITE setFrom)
- Q_PROPERTY(QVector3D to READ to WRITE setTo)
-
-public:
- QDeclarativeVector3dAnimation(QObject *parent=0);
- virtual ~QDeclarativeVector3dAnimation();
-
- QVector3D from() const;
- void setFrom(QVector3D);
-
- QVector3D to() const;
- void setTo(QVector3D);
-};
-
-class QDeclarativeRotationAnimationPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeRotationAnimation : public QDeclarativePropertyAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeRotationAnimation)
- Q_ENUMS(RotationDirection)
-
- Q_PROPERTY(qreal from READ from WRITE setFrom)
- Q_PROPERTY(qreal to READ to WRITE setTo)
- Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
-
-public:
- QDeclarativeRotationAnimation(QObject *parent=0);
- virtual ~QDeclarativeRotationAnimation();
-
- qreal from() const;
- void setFrom(qreal);
-
- qreal to() const;
- void setTo(qreal);
-
- enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
- RotationDirection direction() const;
- void setDirection(RotationDirection direction);
-
-Q_SIGNALS:
- void directionChanged();
-};
-
-class QDeclarativeAnimationGroupPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeAnimationGroup : public QDeclarativeAbstractAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
-
- Q_CLASSINFO("DefaultProperty", "animations")
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations)
-
-public:
- QDeclarativeAnimationGroup(QObject *parent);
- virtual ~QDeclarativeAnimationGroup();
-
- QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations();
- friend class QDeclarativeAbstractAnimation;
-
-protected:
- QDeclarativeAnimationGroup(QDeclarativeAnimationGroupPrivate &dd, QObject *parent);
-};
-
-class QDeclarativeSequentialAnimation : public QDeclarativeAnimationGroup
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
-
-public:
- QDeclarativeSequentialAnimation(QObject *parent=0);
- virtual ~QDeclarativeSequentialAnimation();
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-class QDeclarativeParallelAnimation : public QDeclarativeAnimationGroup
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
-
-public:
- QDeclarativeParallelAnimation(QObject *parent=0);
- virtual ~QDeclarativeParallelAnimation();
-
-protected:
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- virtual QAbstractAnimation *qtAnimation();
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeAbstractAnimation)
-QML_DECLARE_TYPE(QDeclarativePauseAnimation)
-QML_DECLARE_TYPE(QDeclarativeScriptAction)
-QML_DECLARE_TYPE(QDeclarativePropertyAction)
-QML_DECLARE_TYPE(QDeclarativePropertyAnimation)
-QML_DECLARE_TYPE(QDeclarativeColorAnimation)
-QML_DECLARE_TYPE(QDeclarativeNumberAnimation)
-QML_DECLARE_TYPE(QDeclarativeSequentialAnimation)
-QML_DECLARE_TYPE(QDeclarativeParallelAnimation)
-QML_DECLARE_TYPE(QDeclarativeVector3dAnimation)
-QML_DECLARE_TYPE(QDeclarativeRotationAnimation)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEANIMATION_H
diff --git a/src/declarative/util/qdeclarativebehavior_p.h b/src/declarative/util/qdeclarativebehavior_p.h
deleted file mode 100644
index 613461abb1..0000000000
--- a/src/declarative/util/qdeclarativebehavior_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEBEHAVIOR_H
-#define QDECLARATIVEBEHAVIOR_H
-
-#include <private/qdeclarativeglobal_p.h>
-
-#include <private/qdeclarativepropertyvalueinterceptor_p.h>
-#include <qdeclarative.h>
-#include <QtCore/QAbstractAnimation>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeAbstractAnimation;
-class QDeclarativeBehaviorPrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBehavior : public QObject, public QDeclarativePropertyValueInterceptor
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeBehavior)
-
- Q_INTERFACES(QDeclarativePropertyValueInterceptor)
- Q_CLASSINFO("DefaultProperty", "animation")
- Q_PROPERTY(QDeclarativeAbstractAnimation *animation READ animation WRITE setAnimation)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- Q_CLASSINFO("DeferredPropertyNames", "animation")
-
-public:
- QDeclarativeBehavior(QObject *parent=0);
- ~QDeclarativeBehavior();
-
- virtual void setTarget(const QDeclarativeProperty &);
- virtual void write(const QVariant &value);
-
- QDeclarativeAbstractAnimation *animation();
- void setAnimation(QDeclarativeAbstractAnimation *);
-
- bool enabled() const;
- void setEnabled(bool enabled);
-
-Q_SIGNALS:
- void enabledChanged();
-
-private Q_SLOTS:
- void componentFinalized();
- void qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State);
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeBehavior)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEBEHAVIOR_H
diff --git a/src/declarative/util/qdeclarativebind_p.h b/src/declarative/util/qdeclarativebind_p.h
deleted file mode 100644
index 38f15a9328..0000000000
--- a/src/declarative/util/qdeclarativebind_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEBIND_H
-#define QDECLARATIVEBIND_H
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeBindPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeBind : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeBind)
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_INTERFACES(QDeclarativePropertyValueSource)
- Q_PROPERTY(QObject *target READ object WRITE setObject)
- Q_PROPERTY(QString property READ property WRITE setProperty)
- Q_PROPERTY(QVariant value READ value WRITE setValue)
- Q_PROPERTY(bool when READ when WRITE setWhen)
-
-public:
- QDeclarativeBind(QObject *parent=0);
- ~QDeclarativeBind();
-
- bool when() const;
- void setWhen(bool);
-
- QObject *object();
- void setObject(QObject *);
-
- QString property() const;
- void setProperty(const QString &);
-
- QVariant value() const;
- void setValue(const QVariant &);
-
-protected:
- virtual void setTarget(const QDeclarativeProperty &);
- virtual void classBegin();
- virtual void componentComplete();
-
-private:
- void eval();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeBind)
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/util/qdeclarativeconnections_p.h b/src/declarative/util/qdeclarativeconnections_p.h
deleted file mode 100644
index 86e1341689..0000000000
--- a/src/declarative/util/qdeclarativeconnections_p.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVECONNECTIONS_H
-#define QDECLARATIVECONNECTIONS_H
-
-#include <qdeclarative.h>
-#include <private/qdeclarativecustomparser_p.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qstring.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeBoundSignal;
-class QDeclarativeContext;
-class QDeclarativeConnectionsPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeConnections : public QObject, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeConnections)
-
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
-
-public:
- QDeclarativeConnections(QObject *parent=0);
- ~QDeclarativeConnections();
-
- QObject *target() const;
- void setTarget(QObject *);
-
- bool ignoreUnknownSignals() const;
- void setIgnoreUnknownSignals(bool ignore);
-
-Q_SIGNALS:
- void targetChanged();
-
-private:
- void connectSignals();
- void classBegin();
- void componentComplete();
-};
-
-class QDeclarativeConnectionsParser : public QDeclarativeCustomParser
-{
-public:
- virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
- virtual void setCustomData(QObject *, const QByteArray &);
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeConnections)
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/util/qdeclarativefontloader_p.h b/src/declarative/util/qdeclarativefontloader_p.h
deleted file mode 100644
index 26cad5eff4..0000000000
--- a/src/declarative/util/qdeclarativefontloader_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEFONTLOADER_H
-#define QDECLARATIVEFONTLOADER_H
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qurl.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeFontLoaderPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeFontLoader : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeFontLoader)
- Q_ENUMS(Status)
-
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(Status status READ status NOTIFY statusChanged)
-
-public:
- enum Status { Null = 0, Ready, Loading, Error };
-
- QDeclarativeFontLoader(QObject *parent = 0);
- ~QDeclarativeFontLoader();
-
- QUrl source() const;
- void setSource(const QUrl &url);
-
- QString name() const;
- void setName(const QString &name);
-
- Status status() const;
-
-private Q_SLOTS:
- void updateFontInfo(const QString&, QDeclarativeFontLoader::Status);
-
-Q_SIGNALS:
- void sourceChanged();
- void nameChanged();
- void statusChanged();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeFontLoader)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEFONTLOADER_H
-
diff --git a/src/declarative/util/qdeclarativelistaccessor_p.h b/src/declarative/util/qdeclarativelistaccessor_p.h
deleted file mode 100644
index f13dca8fcf..0000000000
--- a/src/declarative/util/qdeclarativelistaccessor_p.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVELISTACCESSOR_H
-#define QDECLARATIVELISTACCESSOR_H
-
-#include <QtCore/QVariant>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeEngine;
-class Q_AUTOTEST_EXPORT QDeclarativeListAccessor
-{
-public:
- QDeclarativeListAccessor();
- ~QDeclarativeListAccessor();
-
- QVariant list() const;
- void setList(const QVariant &, QDeclarativeEngine * = 0);
-
- bool isValid() const;
-
- int count() const;
- QVariant at(int) const;
-
- enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer };
- Type type() const { return m_type; }
-
-private:
- Type m_type;
- QVariant d;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QDECLARATIVELISTACCESSOR_H
diff --git a/src/declarative/util/qdeclarativepackage_p.h b/src/declarative/util/qdeclarativepackage_p.h
deleted file mode 100644
index 8ae88488d0..0000000000
--- a/src/declarative/util/qdeclarativepackage_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEPACKAGE_H
-#define QDECLARATIVEPACKAGE_H
-
-#include <qdeclarative.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativePackagePrivate;
-class QDeclarativePackageAttached;
-class Q_AUTOTEST_EXPORT QDeclarativePackage : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePackage)
-
- Q_CLASSINFO("DefaultProperty", "data")
- Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data)
-
-public:
- QDeclarativePackage(QObject *parent=0);
- virtual ~QDeclarativePackage();
-
- QDeclarativeListProperty<QObject> data();
-
- QObject *part(const QString & = QString());
- bool hasPart(const QString &);
-
- static QDeclarativePackageAttached *qmlAttachedProperties(QObject *);
-};
-
-class QDeclarativePackageAttached : public QObject
-{
-Q_OBJECT
-Q_PROPERTY(QString name READ name WRITE setName)
-public:
- QDeclarativePackageAttached(QObject *parent);
- virtual ~QDeclarativePackageAttached();
-
- QString name() const;
- void setName(const QString &n);
-
- static QHash<QObject *, QDeclarativePackageAttached *> attached;
-private:
- QString _name;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativePackage)
-QML_DECLARE_TYPEINFO(QDeclarativePackage, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEPACKAGE_H
diff --git a/src/declarative/util/qdeclarativepath_p.h b/src/declarative/util/qdeclarativepath_p.h
deleted file mode 100644
index 537afb3b0b..0000000000
--- a/src/declarative/util/qdeclarativepath_p.h
+++ /dev/null
@@ -1,452 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEPATH_H
-#define QDECLARATIVEPATH_H
-
-#include <qdeclarative.h>
-
-#include <private/qdeclarativenullablevalue_p_p.h>
-#include <private/qbezier_p.h>
-
-#include <QtCore/QObject>
-#include <QtGui/QPainterPath>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeCurve;
-struct QDeclarativePathData
-{
- int index;
- QPointF endPoint;
- QList<QDeclarativeCurve*> curves;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathElement : public QObject
-{
- Q_OBJECT
-public:
- QDeclarativePathElement(QObject *parent=0) : QObject(parent) {}
-Q_SIGNALS:
- void changed();
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathAttribute : public QDeclarativePathElement
-{
- Q_OBJECT
-
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
-public:
- QDeclarativePathAttribute(QObject *parent=0) : QDeclarativePathElement(parent), _value(0) {}
-
-
- QString name() const;
- void setName(const QString &name);
-
- qreal value() const;
- void setValue(qreal value);
-
-Q_SIGNALS:
- void nameChanged();
- void valueChanged();
-
-private:
- QString _name;
- qreal _value;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeCurve : public QDeclarativePathElement
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
- Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
- Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
-public:
- QDeclarativeCurve(QObject *parent=0) : QDeclarativePathElement(parent) {}
-
- qreal x() const;
- void setX(qreal x);
- bool hasX();
-
- qreal y() const;
- void setY(qreal y);
- bool hasY();
-
- qreal relativeX() const;
- void setRelativeX(qreal x);
- bool hasRelativeX();
-
- qreal relativeY() const;
- void setRelativeY(qreal y);
- bool hasRelativeY();
-
- virtual void addToPath(QPainterPath &, const QDeclarativePathData &) {}
-
-Q_SIGNALS:
- void xChanged();
- void yChanged();
- void relativeXChanged();
- void relativeYChanged();
-
-private:
- QDeclarativeNullableValue<qreal> _x;
- QDeclarativeNullableValue<qreal> _y;
- QDeclarativeNullableValue<qreal> _relativeX;
- QDeclarativeNullableValue<qreal> _relativeY;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathLine : public QDeclarativeCurve
-{
- Q_OBJECT
-public:
- QDeclarativePathLine(QObject *parent=0) : QDeclarativeCurve(parent) {}
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathQuad : public QDeclarativeCurve
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
- Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
- Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
- Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
-public:
- QDeclarativePathQuad(QObject *parent=0) : QDeclarativeCurve(parent), _controlX(0), _controlY(0) {}
-
- qreal controlX() const;
- void setControlX(qreal x);
-
- qreal controlY() const;
- void setControlY(qreal y);
-
- qreal relativeControlX() const;
- void setRelativeControlX(qreal x);
- bool hasRelativeControlX();
-
- qreal relativeControlY() const;
- void setRelativeControlY(qreal y);
- bool hasRelativeControlY();
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-
-Q_SIGNALS:
- void controlXChanged();
- void controlYChanged();
- void relativeControlXChanged();
- void relativeControlYChanged();
-
-private:
- qreal _controlX;
- qreal _controlY;
- QDeclarativeNullableValue<qreal> _relativeControlX;
- QDeclarativeNullableValue<qreal> _relativeControlY;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathCubic : public QDeclarativeCurve
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)
- Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
- Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
- Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
- Q_PROPERTY(qreal relativeControl1X READ relativeControl1X WRITE setRelativeControl1X NOTIFY relativeControl1XChanged)
- Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
- Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
- Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
-public:
- QDeclarativePathCubic(QObject *parent=0) : QDeclarativeCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
-
- qreal control1X() const;
- void setControl1X(qreal x);
-
- qreal control1Y() const;
- void setControl1Y(qreal y);
-
- qreal control2X() const;
- void setControl2X(qreal x);
-
- qreal control2Y() const;
- void setControl2Y(qreal y);
-
- qreal relativeControl1X() const;
- void setRelativeControl1X(qreal x);
- bool hasRelativeControl1X();
-
- qreal relativeControl1Y() const;
- void setRelativeControl1Y(qreal y);
- bool hasRelativeControl1Y();
-
- qreal relativeControl2X() const;
- void setRelativeControl2X(qreal x);
- bool hasRelativeControl2X();
-
- qreal relativeControl2Y() const;
- void setRelativeControl2Y(qreal y);
- bool hasRelativeControl2Y();
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-
-Q_SIGNALS:
- void control1XChanged();
- void control1YChanged();
- void control2XChanged();
- void control2YChanged();
- void relativeControl1XChanged();
- void relativeControl1YChanged();
- void relativeControl2XChanged();
- void relativeControl2YChanged();
-
-private:
- qreal _control1X;
- qreal _control1Y;
- qreal _control2X;
- qreal _control2Y;
- QDeclarativeNullableValue<qreal> _relativeControl1X;
- QDeclarativeNullableValue<qreal> _relativeControl1Y;
- QDeclarativeNullableValue<qreal> _relativeControl2X;
- QDeclarativeNullableValue<qreal> _relativeControl2Y;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathCatmullRomCurve : public QDeclarativeCurve
-{
- Q_OBJECT
-public:
- QDeclarativePathCatmullRomCurve(QObject *parent=0) : QDeclarativeCurve(parent) {}
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathArc : public QDeclarativeCurve
-{
- Q_OBJECT
- Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
- Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
- Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
- Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
-
-public:
- QDeclarativePathArc(QObject *parent=0)
- : QDeclarativeCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
-
- enum ArcDirection { Clockwise, Counterclockwise };
- Q_ENUMS(ArcDirection)
-
- qreal radiusX() const;
- void setRadiusX(qreal);
-
- qreal radiusY() const;
- void setRadiusY(qreal);
-
- bool useLargeArc() const;
- void setUseLargeArc(bool);
-
- ArcDirection direction() const;
- void setDirection(ArcDirection direction);
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-
-Q_SIGNALS:
- void radiusXChanged();
- void radiusYChanged();
- void useLargeArcChanged();
- void directionChanged();
-
-private:
- qreal _radiusX;
- qreal _radiusY;
- bool _useLargeArc;
- ArcDirection _direction;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathSvg : public QDeclarativeCurve
-{
- Q_OBJECT
- Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
-public:
- QDeclarativePathSvg(QObject *parent=0) : QDeclarativeCurve(parent) {}
-
- QString path() const;
- void setPath(const QString &path);
-
- void addToPath(QPainterPath &path, const QDeclarativePathData &);
-
-Q_SIGNALS:
- void pathChanged();
-
-private:
- QString _path;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativePathPercent : public QDeclarativePathElement
-{
- Q_OBJECT
- Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
-public:
- QDeclarativePathPercent(QObject *parent=0) : QDeclarativePathElement(parent) {}
-
- qreal value() const;
- void setValue(qreal value);
-
-signals:
- void valueChanged();
-
-private:
- qreal _value;
-};
-
-struct QDeclarativeCachedBezier
-{
- QDeclarativeCachedBezier() : isValid(false) {}
- QBezier bezier;
- int element;
- qreal bezLength;
- qreal currLength;
- qreal p;
- bool isValid;
-};
-
-class QDeclarativePathPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativePath : public QObject, public QDeclarativeParserStatus
-{
- Q_OBJECT
-
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativePathElement> pathElements READ pathElements)
- Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
- Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
- Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
- Q_CLASSINFO("DefaultProperty", "pathElements")
- Q_INTERFACES(QDeclarativeParserStatus)
-public:
- QDeclarativePath(QObject *parent=0);
- ~QDeclarativePath();
-
- QDeclarativeListProperty<QDeclarativePathElement> pathElements();
-
- qreal startX() const;
- void setStartX(qreal x);
- bool hasStartX() const;
-
- qreal startY() const;
- void setStartY(qreal y);
- bool hasStartY() const;
-
- bool isClosed() const;
- bool hasEnd() const;
-
- QPainterPath path() const;
- QStringList attributes() const;
- qreal attributeAt(const QString &, qreal) const;
- QPointF pointAt(qreal) const;
- QPointF sequentialPointAt(qreal p, qreal *angle = 0) const;
-
-Q_SIGNALS:
- void changed();
- void startXChanged();
- void startYChanged();
-
-protected:
- virtual void componentComplete();
- virtual void classBegin();
-
-private Q_SLOTS:
- void processPath();
-
-private:
- struct AttributePoint {
- AttributePoint() : percent(0), scale(1), origpercent(0) {}
- AttributePoint(const AttributePoint &other)
- : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
- AttributePoint &operator=(const AttributePoint &other) {
- percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
- }
- qreal percent; //massaged percent along the painter path
- qreal scale;
- qreal origpercent; //'real' percent along the painter path
- QHash<QString, qreal> values;
- };
-
- void interpolate(int idx, const QString &name, qreal value);
- void endpoint(const QString &name);
- void createPointCache() const;
-
- static void interpolate(QList<AttributePoint> &points, int idx, const QString &name, qreal value);
- static void endpoint(QList<AttributePoint> &attributePoints, const QString &name);
- static QPointF forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
- static QPointF backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
-
-private:
- Q_DISABLE_COPY(QDeclarativePath)
- Q_DECLARE_PRIVATE(QDeclarativePath)
- friend class QQuickPathAnimationUpdater;
-
-public:
- QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = 0);
- static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativePathElement)
-QML_DECLARE_TYPE(QDeclarativePathAttribute)
-QML_DECLARE_TYPE(QDeclarativeCurve)
-QML_DECLARE_TYPE(QDeclarativePathLine)
-QML_DECLARE_TYPE(QDeclarativePathQuad)
-QML_DECLARE_TYPE(QDeclarativePathCubic)
-QML_DECLARE_TYPE(QDeclarativePathCatmullRomCurve)
-QML_DECLARE_TYPE(QDeclarativePathArc)
-QML_DECLARE_TYPE(QDeclarativePathSvg)
-QML_DECLARE_TYPE(QDeclarativePathPercent)
-QML_DECLARE_TYPE(QDeclarativePath)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEPATH_H
diff --git a/src/declarative/util/qdeclarativepathinterpolator_p.h b/src/declarative/util/qdeclarativepathinterpolator_p.h
deleted file mode 100644
index cb8ccfa8fb..0000000000
--- a/src/declarative/util/qdeclarativepathinterpolator_p.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEPATHINTERPOLATOR_P_H
-#define QDECLARATIVEPATHINTERPOLATOR_P_H
-
-#include <qdeclarative.h>
-#include <QObject>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativePath;
-class Q_AUTOTEST_EXPORT QDeclarativePathInterpolator : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
- Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
- Q_PROPERTY(qreal x READ x NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y NOTIFY yChanged)
- Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged)
-public:
- explicit QDeclarativePathInterpolator(QObject *parent = 0);
-
- QDeclarativePath *path() const;
- void setPath(QDeclarativePath *path);
-
- qreal progress() const;
- void setProgress(qreal progress);
-
- qreal x() const;
- qreal y() const;
- qreal angle() const;
-
-Q_SIGNALS:
- void pathChanged();
- void progressChanged();
- void xChanged();
- void yChanged();
- void angleChanged();
-
-private Q_SLOTS:
- void _q_pathUpdated();
-
-private:
- QDeclarativePath *_path;
- qreal _x;
- qreal _y;
- qreal _angle;
- qreal _progress;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativePathInterpolator)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEPATHINTERPOLATOR_P_H
diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp
deleted file mode 100644
index b57bfac585..0000000000
--- a/src/declarative/util/qdeclarativepixmapcache.cpp
+++ /dev/null
@@ -1,1241 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "qdeclarativepixmapcache_p.h"
-#include <qdeclarativenetworkaccessmanagerfactory.h>
-#include <qdeclarativeimageprovider.h>
-
-#include <qdeclarativeengine.h>
-#include <private/qdeclarativeglobal_p.h>
-#include <private/qdeclarativeengine_p.h>
-
-#include <private/qsgtexture_p.h>
-
-#include <QCoreApplication>
-#include <QImageReader>
-#include <QHash>
-#include <QNetworkReply>
-#include <QPixmapCache>
-#include <QFile>
-#include <QThread>
-#include <QMutex>
-#include <QMutexLocker>
-#include <QWaitCondition>
-#include <QBuffer>
-#include <QWaitCondition>
-#include <QtCore/qdebug.h>
-#include <private/qobject_p.h>
-#include <QSslError>
-#include <QOpenGLContext>
-
-#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
-#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
-#define CACHE_EXPIRE_TIME 30
-#define CACHE_REMOVAL_FRACTION 4
-
-QT_BEGIN_NAMESPACE
-
-// The cache limit describes the maximum "junk" in the cache.
-static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded in qpixmapcache.cpp
-
-QSGTexture *QDeclarativeDefaultTextureFactory::createTexture() const
-{
- QSGPlainTexture *t = new QSGPlainTexture();
- t->setImage(im);
- return t;
-}
-
-class QDeclarativePixmapReader;
-class QDeclarativePixmapData;
-class QDeclarativePixmapReply : public QObject
-{
- Q_OBJECT
-public:
- enum ReadError { NoError, Loading, Decoding };
-
- QDeclarativePixmapReply(QDeclarativePixmapData *);
- ~QDeclarativePixmapReply();
-
- QDeclarativePixmapData *data;
- QDeclarativeEngine *engineForReader; // always access reader inside readerMutex
- QSize requestSize;
- QUrl url;
-
- bool loading;
- int redirectCount;
-
- class Event : public QEvent {
- public:
- Event(ReadError, const QString &, const QSize &, QDeclarativeTextureFactory *factory, const QImage &image);
-
- ReadError error;
- QString errorString;
- QSize implicitSize;
- QImage image;
- QDeclarativeTextureFactory *textureFactory;
- };
- void postReply(ReadError, const QString &, const QSize &, const QImage &image);
- void postReply(ReadError, const QString &, const QSize &, QDeclarativeTextureFactory *factory, const QImage &image);
-
-
-Q_SIGNALS:
- void finished();
- void downloadProgress(qint64, qint64);
-
-protected:
- bool event(QEvent *event);
-
-private:
- Q_DISABLE_COPY(QDeclarativePixmapReply)
-
-public:
- static int finishedIndex;
- static int downloadProgressIndex;
-};
-
-class QDeclarativePixmapReaderThreadObject : public QObject {
- Q_OBJECT
-public:
- QDeclarativePixmapReaderThreadObject(QDeclarativePixmapReader *);
- void processJobs();
- virtual bool event(QEvent *e);
-private slots:
- void networkRequestDone();
-private:
- QDeclarativePixmapReader *reader;
-};
-
-class QDeclarativePixmapData;
-class QDeclarativePixmapReader : public QThread
-{
- Q_OBJECT
-public:
- QDeclarativePixmapReader(QDeclarativeEngine *eng);
- ~QDeclarativePixmapReader();
-
- QDeclarativePixmapReply *getImage(QDeclarativePixmapData *);
- void cancel(QDeclarativePixmapReply *rep);
-
- static QDeclarativePixmapReader *instance(QDeclarativeEngine *engine);
- static QDeclarativePixmapReader *existingInstance(QDeclarativeEngine *engine);
-
-protected:
- void run();
-
-private:
- friend class QDeclarativePixmapReaderThreadObject;
- void processJobs();
- void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &);
- void networkRequestDone(QNetworkReply *);
-
- QList<QDeclarativePixmapReply*> jobs;
- QList<QDeclarativePixmapReply*> cancelled;
- QDeclarativeEngine *engine;
- QObject *eventLoopQuitHack;
-
- QMutex mutex;
- QDeclarativePixmapReaderThreadObject *threadObject;
- QWaitCondition waitCondition;
-
- QNetworkAccessManager *networkAccessManager();
- QNetworkAccessManager *accessManager;
-
- QHash<QNetworkReply*,QDeclarativePixmapReply*> replies;
-
- static int replyDownloadProgress;
- static int replyFinished;
- static int downloadProgress;
- static int threadNetworkRequestDone;
- static QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> readers;
-public:
- static QMutex readerMutex;
-};
-
-class QDeclarativePixmapData
-{
-public:
- QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QSize &s, const QString &e)
- : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Error),
- url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0),
- prevUnreferencedPtr(0), nextUnreferenced(0)
- {
- declarativePixmaps.insert(pixmap);
- }
-
- QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QSize &r)
- : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Loading),
- url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
- nextUnreferenced(0)
- {
- declarativePixmaps.insert(pixmap);
- }
-
- QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QImage &p, const QSize &s, const QSize &r)
- : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
- url(u), image(p), implicitSize(s), requestSize(r), textureFactory(new QDeclarativeDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
- prevUnreferencedPtr(0), nextUnreferenced(0)
- {
- declarativePixmaps.insert(pixmap);
- }
-
- QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, QDeclarativeTextureFactory *factory, const QImage &p, const QSize &s, const QSize &r)
- : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
- url(u), image(p), implicitSize(s), requestSize(r), textureFactory(factory), reply(0), prevUnreferenced(0),
- prevUnreferencedPtr(0), nextUnreferenced(0)
- {
- declarativePixmaps.insert(pixmap);
- }
-
- QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QImage &p)
- : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarativePixmap::Ready),
- image(p), implicitSize(p.size()), requestSize(p.size()), textureFactory(new QDeclarativeDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
- prevUnreferencedPtr(0), nextUnreferenced(0)
- {
- declarativePixmaps.insert(pixmap);
- }
-
- ~QDeclarativePixmapData()
- {
- while (!declarativePixmaps.isEmpty()) {
- QDeclarativePixmap *referencer = declarativePixmaps.first();
- declarativePixmaps.remove(referencer);
- referencer->d = 0;
- }
- delete textureFactory;
- }
-
- int cost() const;
- void addref();
- void release();
- void addToCache();
- void removeFromCache();
-
- uint refCount;
-
- bool inCache:1;
- bool privatePixmap:1;
-
- QDeclarativePixmap::Status pixmapStatus;
- QUrl url;
- QString errorString;
- QImage image;
- QSize implicitSize;
- QSize requestSize;
-
- QDeclarativeTextureFactory *textureFactory;
-
- QIntrusiveList<QDeclarativePixmap, &QDeclarativePixmap::dataListNode> declarativePixmaps;
- QDeclarativePixmapReply *reply;
-
- QDeclarativePixmapData *prevUnreferenced;
- QDeclarativePixmapData**prevUnreferencedPtr;
- QDeclarativePixmapData *nextUnreferenced;
-};
-
-int QDeclarativePixmapReply::finishedIndex = -1;
-int QDeclarativePixmapReply::downloadProgressIndex = -1;
-
-// XXX
-QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> QDeclarativePixmapReader::readers;
-QMutex QDeclarativePixmapReader::readerMutex;
-
-int QDeclarativePixmapReader::replyDownloadProgress = -1;
-int QDeclarativePixmapReader::replyFinished = -1;
-int QDeclarativePixmapReader::downloadProgress = -1;
-int QDeclarativePixmapReader::threadNetworkRequestDone = -1;
-
-
-void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString,
- const QSize &implicitSize, const QImage &image)
-{
- loading = false;
- QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, new QDeclarativeDefaultTextureFactory(image), image));
-}
-
-void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString,
- const QSize &implicitSize, QDeclarativeTextureFactory *factory,
- const QImage &image)
-{
- loading = false;
- QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory, image));
-}
-
-QDeclarativePixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QDeclarativeTextureFactory *factory, const QImage &i)
- : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i), textureFactory(factory)
-{
-}
-
-QNetworkAccessManager *QDeclarativePixmapReader::networkAccessManager()
-{
- if (!accessManager) {
- Q_ASSERT(threadObject);
- accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
- }
- return accessManager;
-}
-
-static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
- const QSize &requestSize)
-{
- QImageReader imgio(dev);
-
- bool force_scale = false;
- if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
- imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
- force_scale = true;
- }
-
- bool scaled = false;
- if (requestSize.width() > 0 || requestSize.height() > 0) {
- QSize s = imgio.size();
- if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
- if (requestSize.height() <= 0)
- s.setHeight(s.height()*requestSize.width()/s.width());
- s.setWidth(requestSize.width()); scaled = true;
- }
- if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
- if (requestSize.width() <= 0)
- s.setWidth(s.width()*requestSize.height()/s.height());
- s.setHeight(requestSize.height()); scaled = true;
- }
- if (scaled) { imgio.setScaledSize(s); }
- }
-
- if (impsize)
- *impsize = imgio.size();
-
- if (imgio.read(image)) {
- if (impsize && impsize->width() < 0)
- *impsize = image->size();
- return true;
- } else {
- if (errorString)
- *errorString = QDeclarativePixmap::tr("Error decoding: %1: %2").arg(url.toString())
- .arg(imgio.errorString());
- return false;
- }
-}
-
-QDeclarativePixmapReader::QDeclarativePixmapReader(QDeclarativeEngine *eng)
-: QThread(eng), engine(eng), threadObject(0), accessManager(0)
-{
- eventLoopQuitHack = new QObject;
- eventLoopQuitHack->moveToThread(this);
- connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
- start(QThread::LowestPriority);
-}
-
-QDeclarativePixmapReader::~QDeclarativePixmapReader()
-{
- readerMutex.lock();
- readers.remove(engine);
- readerMutex.unlock();
-
- mutex.lock();
- // manually cancel all outstanding jobs.
- foreach (QDeclarativePixmapReply *reply, jobs) {
- delete reply;
- }
- jobs.clear();
- QList<QDeclarativePixmapReply*> activeJobs = replies.values();
- foreach (QDeclarativePixmapReply *reply, activeJobs) {
- if (reply->loading) {
- cancelled.append(reply);
- reply->data = 0;
- }
- }
- if (threadObject) threadObject->processJobs();
- mutex.unlock();
-
- eventLoopQuitHack->deleteLater();
- wait();
-}
-
-void QDeclarativePixmapReader::networkRequestDone(QNetworkReply *reply)
-{
- QDeclarativePixmapReply *job = replies.take(reply);
-
- if (job) {
- job->redirectCount++;
- if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) {
- QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- if (redirect.isValid()) {
- QUrl url = reply->url().resolved(redirect.toUrl());
- QNetworkRequest req(url);
- req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
-
- reply->deleteLater();
- reply = networkAccessManager()->get(req);
-
- QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
- QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
-
- replies.insert(reply, job);
- return;
- }
- }
-
- QImage image;
- QDeclarativePixmapReply::ReadError error = QDeclarativePixmapReply::NoError;
- QString errorString;
- QSize readSize;
- if (reply->error()) {
- error = QDeclarativePixmapReply::Loading;
- errorString = reply->errorString();
- } else {
- QByteArray all = reply->readAll();
- QBuffer buff(&all);
- buff.open(QIODevice::ReadOnly);
- if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize))
- error = QDeclarativePixmapReply::Decoding;
- }
- // send completion event to the QDeclarativePixmapReply
- mutex.lock();
- if (!cancelled.contains(job)) {
- job->postReply(error, errorString, readSize, image);
- }
- mutex.unlock();
- }
- reply->deleteLater();
-
- // kick off event loop again incase we have dropped below max request count
- threadObject->processJobs();
-}
-
-QDeclarativePixmapReaderThreadObject::QDeclarativePixmapReaderThreadObject(QDeclarativePixmapReader *i)
-: reader(i)
-{
-}
-
-void QDeclarativePixmapReaderThreadObject::processJobs()
-{
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
-}
-
-bool QDeclarativePixmapReaderThreadObject::event(QEvent *e)
-{
- if (e->type() == QEvent::User) {
- reader->processJobs();
- return true;
- } else {
- return QObject::event(e);
- }
-}
-
-void QDeclarativePixmapReaderThreadObject::networkRequestDone()
-{
- QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
- reader->networkRequestDone(reply);
-}
-
-void QDeclarativePixmapReader::processJobs()
-{
- QMutexLocker locker(&mutex);
-
- while (true) {
- if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
- return; // Nothing else to do
-
- // Clean cancelled jobs
- if (cancelled.count()) {
- for (int i = 0; i < cancelled.count(); ++i) {
- QDeclarativePixmapReply *job = cancelled.at(i);
- QNetworkReply *reply = replies.key(job, 0);
- if (reply && reply->isRunning()) {
- // cancel any jobs already started
- replies.remove(reply);
- reply->close();
- }
- // deleteLater, since not owned by this thread
- job->deleteLater();
- }
- cancelled.clear();
- }
-
- if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
- QDeclarativePixmapReply *runningJob = jobs.takeLast();
- runningJob->loading = true;
-
- QUrl url = runningJob->url;
- QSize requestSize = runningJob->requestSize;
- locker.unlock();
- processJob(runningJob, url, requestSize);
- locker.relock();
- }
- }
-}
-
-void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url,
- const QSize &requestSize)
-{
- // fetch
- if (url.scheme() == QLatin1String("image")) {
- // Use QmlImageProvider
- QSize readSize;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url);
- if (imageType == QDeclarativeImageProvider::Invalid) {
- QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::Loading;
- QString errorStr = QDeclarativePixmap::tr("Invalid image provider: %1").arg(url.toString());
- QImage image;
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, image);
- mutex.unlock();
- } else if (imageType == QDeclarativeImageProvider::Image) {
- QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
- QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
- QString errorStr;
- if (image.isNull()) {
- errorCode = QDeclarativePixmapReply::Loading;
- errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString());
- }
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, image);
- mutex.unlock();
- } else {
- QDeclarativeTextureFactory *t = ep->getTextureFromProvider(url, &readSize, requestSize);
- QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
- QString errorStr;
- if (!t) {
- errorCode = QDeclarativePixmapReply::Loading;
- errorStr = QDeclarativePixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
- }
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, t, QImage());
- mutex.unlock();
-
- }
-
- } else {
- QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
- // Image is local - load/decode immediately
- QImage image;
- QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
- QString errorStr;
- QFile f(lf);
- QSize readSize;
- if (f.open(QIODevice::ReadOnly)) {
- if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
- errorCode = QDeclarativePixmapReply::Loading;
- } else {
- errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
- errorCode = QDeclarativePixmapReply::Loading;
- }
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, image);
- mutex.unlock();
- } else {
- // Network resource
- QNetworkRequest req(url);
- req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
- QNetworkReply *reply = networkAccessManager()->get(req);
-
- QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
- QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
-
- replies.insert(reply, runningJob);
- }
- }
-}
-
-QDeclarativePixmapReader *QDeclarativePixmapReader::instance(QDeclarativeEngine *engine)
-{
- // XXX NOTE: must be called within readerMutex locking.
- QDeclarativePixmapReader *reader = readers.value(engine);
- if (!reader) {
- reader = new QDeclarativePixmapReader(engine);
- readers.insert(engine, reader);
- }
-
- return reader;
-}
-
-QDeclarativePixmapReader *QDeclarativePixmapReader::existingInstance(QDeclarativeEngine *engine)
-{
- // XXX NOTE: must be called within readerMutex locking.
- return readers.value(engine, 0);
-}
-
-QDeclarativePixmapReply *QDeclarativePixmapReader::getImage(QDeclarativePixmapData *data)
-{
- mutex.lock();
- QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(data);
- reply->engineForReader = engine;
- jobs.append(reply);
- // XXX
- if (threadObject) threadObject->processJobs();
- mutex.unlock();
- return reply;
-}
-
-void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply)
-{
- mutex.lock();
- if (reply->loading) {
- cancelled.append(reply);
- reply->data = 0;
- // XXX
- if (threadObject) threadObject->processJobs();
- } else {
- jobs.removeAll(reply);
- delete reply;
- }
- mutex.unlock();
-}
-
-void QDeclarativePixmapReader::run()
-{
- if (replyDownloadProgress == -1) {
- const QMetaObject *nr = &QNetworkReply::staticMetaObject;
- const QMetaObject *pr = &QDeclarativePixmapReply::staticMetaObject;
- const QMetaObject *ir = &QDeclarativePixmapReaderThreadObject::staticMetaObject;
- replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
- replyFinished = nr->indexOfSignal("finished()");
- downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
- threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
- }
-
- mutex.lock();
- threadObject = new QDeclarativePixmapReaderThreadObject(this);
- mutex.unlock();
-
- processJobs();
- exec();
-
- delete threadObject;
- threadObject = 0;
-}
-
-class QDeclarativePixmapKey
-{
-public:
- const QUrl *url;
- const QSize *size;
-};
-
-inline bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs)
-{
- return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
-}
-
-inline uint qHash(const QDeclarativePixmapKey &key)
-{
- return qHash(*key.url) ^ key.size->width() ^ key.size->height();
-}
-
-class QSGContext;
-
-class QDeclarativePixmapStore : public QObject
-{
- Q_OBJECT
-public:
- QDeclarativePixmapStore();
- ~QDeclarativePixmapStore();
-
- void unreferencePixmap(QDeclarativePixmapData *);
- void referencePixmap(QDeclarativePixmapData *);
-
-protected:
- virtual void timerEvent(QTimerEvent *);
-
-public:
- QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
-
-private:
- void shrinkCache(int remove);
-
- QDeclarativePixmapData *m_unreferencedPixmaps;
- QDeclarativePixmapData *m_lastUnreferencedPixmap;
-
- int m_unreferencedCost;
- int m_timerId;
-};
-Q_GLOBAL_STATIC(QDeclarativePixmapStore, pixmapStore);
-
-
-QDeclarativePixmapStore::QDeclarativePixmapStore()
-: m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1)
-{
-}
-
-QDeclarativePixmapStore::~QDeclarativePixmapStore()
-{
- int leakedPixmaps = 0;
- QList<QDeclarativePixmapData*> cachedData = m_cache.values();
-
- // unreference all (leaked) pixmaps
- foreach (QDeclarativePixmapData* pixmap, cachedData) {
- int currRefCount = pixmap->refCount;
- if (currRefCount) {
- leakedPixmaps++;
- while (currRefCount > 0) {
- pixmap->release();
- currRefCount--;
- }
- }
- }
-
- // free all unreferenced pixmaps
- while (m_lastUnreferencedPixmap) {
- shrinkCache(20);
- }
-
- if (leakedPixmaps)
- qDebug("Number of leaked pixmaps: %i", leakedPixmaps);
-}
-
-void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
-{
- Q_ASSERT(data->prevUnreferenced == 0);
- Q_ASSERT(data->prevUnreferencedPtr == 0);
- Q_ASSERT(data->nextUnreferenced == 0);
-
- data->nextUnreferenced = m_unreferencedPixmaps;
- data->prevUnreferencedPtr = &m_unreferencedPixmaps;
-
- m_unreferencedPixmaps = data;
- if (m_unreferencedPixmaps->nextUnreferenced) {
- m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps;
- m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced;
- }
-
- if (!m_lastUnreferencedPixmap)
- m_lastUnreferencedPixmap = data;
-
- m_unreferencedCost += data->cost();
-
- shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
-
- if (m_timerId == -1 && m_unreferencedPixmaps)
- m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
-}
-
-void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
-{
- Q_ASSERT(data->prevUnreferencedPtr);
-
- *data->prevUnreferencedPtr = data->nextUnreferenced;
- if (data->nextUnreferenced) {
- data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
- data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
- }
- if (m_lastUnreferencedPixmap == data)
- m_lastUnreferencedPixmap = data->prevUnreferenced;
-
- data->nextUnreferenced = 0;
- data->prevUnreferencedPtr = 0;
- data->prevUnreferenced = 0;
-
- m_unreferencedCost -= data->cost();
-}
-
-void QDeclarativePixmapStore::shrinkCache(int remove)
-{
- while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
- QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
- Q_ASSERT(data->nextUnreferenced == 0);
-
- *data->prevUnreferencedPtr = 0;
- m_lastUnreferencedPixmap = data->prevUnreferenced;
- data->prevUnreferencedPtr = 0;
- data->prevUnreferenced = 0;
-
- remove -= data->cost();
- m_unreferencedCost -= data->cost();
- data->removeFromCache();
- delete data;
- }
-}
-
-void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
-{
- int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
-
- shrinkCache(removalCost);
-
- if (m_unreferencedPixmaps == 0) {
- killTimer(m_timerId);
- m_timerId = -1;
- }
-}
-
-QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativePixmapData *d)
-: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0)
-{
- if (finishedIndex == -1) {
- finishedIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
- downloadProgressIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- }
-}
-
-QDeclarativePixmapReply::~QDeclarativePixmapReply()
-{
-}
-
-bool QDeclarativePixmapReply::event(QEvent *event)
-{
- if (event->type() == QEvent::User) {
-
- if (data) {
- Event *de = static_cast<Event *>(event);
- data->pixmapStatus = (de->error == NoError) ? QDeclarativePixmap::Ready : QDeclarativePixmap::Error;
-
- if (data->pixmapStatus == QDeclarativePixmap::Ready) {
- if (de->textureFactory) {
- data->textureFactory = de->textureFactory;
- }
- data->image = de->image;
- data->implicitSize = de->implicitSize;
- } else {
- data->errorString = de->errorString;
- data->removeFromCache(); // We don't continue to cache error'd pixmaps
- }
-
- data->reply = 0;
- emit finished();
- }
-
- delete this;
- return true;
- } else {
- return QObject::event(event);
- }
-}
-
-int QDeclarativePixmapData::cost() const
-{
- if (textureFactory)
- return textureFactory->textureByteCount();
- return image.byteCount();
-}
-
-void QDeclarativePixmapData::addref()
-{
- ++refCount;
- if (prevUnreferencedPtr)
- pixmapStore()->referencePixmap(this);
-}
-
-void QDeclarativePixmapData::release()
-{
- Q_ASSERT(refCount > 0);
- --refCount;
- if (refCount == 0) {
- if (reply) {
- QDeclarativePixmapReply *cancelReply = reply;
- reply->data = 0;
- reply = 0;
- QDeclarativePixmapReader::readerMutex.lock();
- QDeclarativePixmapReader *reader = QDeclarativePixmapReader::existingInstance(cancelReply->engineForReader);
- if (reader)
- reader->cancel(cancelReply);
- QDeclarativePixmapReader::readerMutex.unlock();
- }
-
- if (pixmapStatus == QDeclarativePixmap::Ready) {
- pixmapStore()->unreferencePixmap(this);
- } else {
- removeFromCache();
- delete this;
- }
- }
-}
-
-void QDeclarativePixmapData::addToCache()
-{
- if (!inCache) {
- QDeclarativePixmapKey key = { &url, &requestSize };
- pixmapStore()->m_cache.insert(key, this);
- inCache = true;
- }
-}
-
-void QDeclarativePixmapData::removeFromCache()
-{
- if (inCache) {
- QDeclarativePixmapKey key = { &url, &requestSize };
- pixmapStore()->m_cache.remove(key);
- inCache = false;
- }
-}
-
-static QDeclarativePixmapData* createPixmapDataSync(QDeclarativePixmap *declarativePixmap, QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok)
-{
- if (url.scheme() == QLatin1String("image")) {
- QSize readSize;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url);
-
- switch (imageType) {
- case QDeclarativeImageProvider::Invalid:
- return new QDeclarativePixmapData(declarativePixmap, url, requestSize,
- QDeclarativePixmap::tr("Invalid image provider: %1").arg(url.toString()));
- case QDeclarativeImageProvider::Texture:
- {
- QDeclarativeTextureFactory *texture = ep->getTextureFromProvider(url, &readSize, requestSize);
- if (texture) {
- *ok = true;
- return new QDeclarativePixmapData(declarativePixmap, url, texture, QImage(), readSize, requestSize);
- }
- }
-
- case QDeclarativeImageProvider::Image:
- {
- QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
- if (!image.isNull()) {
- *ok = true;
- return new QDeclarativePixmapData(declarativePixmap, url, image, readSize, requestSize);
- }
- }
- case QDeclarativeImageProvider::Pixmap:
- {
- QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize);
- if (!pixmap.isNull()) {
- *ok = true;
- return new QDeclarativePixmapData(declarativePixmap, url, pixmap.toImage(), readSize, requestSize);
- }
- }
- }
-
- // provider has bad image type, or provider returned null image
- return new QDeclarativePixmapData(declarativePixmap, url, requestSize,
- QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString()));
- }
-
- QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
- if (localFile.isEmpty())
- return 0;
-
- QFile f(localFile);
- QSize readSize;
- QString errorString;
-
- if (f.open(QIODevice::ReadOnly)) {
- QImage image;
-
- if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
- *ok = true;
- return new QDeclarativePixmapData(declarativePixmap, url, image, readSize, requestSize);
- }
- errorString = QDeclarativePixmap::tr("Invalid image data: %1").arg(url.toString());
-
- } else {
- errorString = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
- }
- return new QDeclarativePixmapData(declarativePixmap, url, requestSize, errorString);
-}
-
-
-struct QDeclarativePixmapNull {
- QUrl url;
- QImage image;
- QSize size;
-};
-Q_GLOBAL_STATIC(QDeclarativePixmapNull, nullPixmap);
-
-QDeclarativePixmap::QDeclarativePixmap()
-: d(0)
-{
-}
-
-QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url)
-: d(0)
-{
- load(engine, url);
-}
-
-QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
-: d(0)
-{
- load(engine, url, size);
-}
-
-QDeclarativePixmap::~QDeclarativePixmap()
-{
- if (d) {
- d->declarativePixmaps.remove(this);
- d->release();
- d = 0;
- }
-}
-
-bool QDeclarativePixmap::isNull() const
-{
- return d == 0;
-}
-
-bool QDeclarativePixmap::isReady() const
-{
- return status() == Ready;
-}
-
-bool QDeclarativePixmap::isError() const
-{
- return status() == Error;
-}
-
-bool QDeclarativePixmap::isLoading() const
-{
- return status() == Loading;
-}
-
-QString QDeclarativePixmap::error() const
-{
- if (d)
- return d->errorString;
- else
- return QString();
-}
-
-QDeclarativePixmap::Status QDeclarativePixmap::status() const
-{
- if (d)
- return d->pixmapStatus;
- else
- return Null;
-}
-
-const QUrl &QDeclarativePixmap::url() const
-{
- if (d)
- return d->url;
- else
- return nullPixmap()->url;
-}
-
-const QSize &QDeclarativePixmap::implicitSize() const
-{
- if (d)
- return d->implicitSize;
- else
- return nullPixmap()->size;
-}
-
-const QSize &QDeclarativePixmap::requestSize() const
-{
- if (d)
- return d->requestSize;
- else
- return nullPixmap()->size;
-}
-
-QDeclarativeTextureFactory *QDeclarativePixmap::textureFactory() const
-{
- if (d)
- return d->textureFactory;
-
- return 0;
-}
-
-const QImage &QDeclarativePixmap::image() const
-{
- if (d)
- return d->image;
- else
- return nullPixmap()->image;
-}
-
-void QDeclarativePixmap::setImage(const QImage &p)
-{
- clear();
-
- if (!p.isNull())
- d = new QDeclarativePixmapData(this, p);
-}
-
-int QDeclarativePixmap::width() const
-{
- if (d)
- return d->textureFactory ? d->textureFactory->textureSize().width() : d->image.width();
- else
- return 0;
-}
-
-int QDeclarativePixmap::height() const
-{
- if (d)
- return d->textureFactory ? d->textureFactory->textureSize().height() : d->image.height();
- else
- return 0;
-}
-
-QRect QDeclarativePixmap::rect() const
-{
- if (d)
- return d->textureFactory ? QRect(QPoint(), d->textureFactory->textureSize()) : d->image.rect();
- else
- return QRect();
-}
-
-void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url)
-{
- load(engine, url, QSize(), QDeclarativePixmap::Cache);
-}
-
-void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options)
-{
- load(engine, url, QSize(), options);
-}
-
-void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
-{
- load(engine, url, size, QDeclarativePixmap::Cache);
-}
-
-void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options)
-{
- if (d) {
- d->declarativePixmaps.remove(this);
- d->release();
- d = 0;
- }
-
- QDeclarativePixmapKey key = { &url, &requestSize };
- QDeclarativePixmapStore *store = pixmapStore();
-
- QHash<QDeclarativePixmapKey, QDeclarativePixmapData *>::Iterator iter = store->m_cache.find(key);
-
- if (iter == store->m_cache.end()) {
- if (options & QDeclarativePixmap::Asynchronous) {
- // pixmaps can only be loaded synchronously
- if (url.scheme() == QLatin1String("image")
- && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) {
- options &= ~QDeclarativePixmap::Asynchronous;
- }
- }
-
- if (!(options & QDeclarativePixmap::Asynchronous)) {
- bool ok = false;
- d = createPixmapDataSync(this, engine, url, requestSize, &ok);
- if (ok) {
- if (options & QDeclarativePixmap::Cache)
- d->addToCache();
- return;
- }
- if (d) // loadable, but encountered error while loading
- return;
- }
-
- if (!engine)
- return;
-
- d = new QDeclarativePixmapData(this, url, requestSize);
- if (options & QDeclarativePixmap::Cache)
- d->addToCache();
-
- QDeclarativePixmapReader::readerMutex.lock();
- d->reply = QDeclarativePixmapReader::instance(engine)->getImage(d);
- QDeclarativePixmapReader::readerMutex.unlock();
- } else {
- d = *iter;
- d->addref();
- d->declarativePixmaps.insert(this);
- }
-}
-
-void QDeclarativePixmap::clear()
-{
- if (d) {
- d->declarativePixmaps.remove(this);
- d->release();
- d = 0;
- }
-}
-
-void QDeclarativePixmap::clear(QObject *obj)
-{
- if (d) {
- if (d->reply)
- QObject::disconnect(d->reply, 0, obj, 0);
- d->declarativePixmaps.remove(this);
- d->release();
- d = 0;
- }
-}
-
-bool QDeclarativePixmap::connectFinished(QObject *object, const char *method)
-{
- if (!d || !d->reply) {
- qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
- return false;
- }
-
- return QObject::connect(d->reply, SIGNAL(finished()), object, method);
-}
-
-bool QDeclarativePixmap::connectFinished(QObject *object, int method)
-{
- if (!d || !d->reply) {
- qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
- return false;
- }
-
- return QMetaObject::connect(d->reply, QDeclarativePixmapReply::finishedIndex, object, method);
-}
-
-bool QDeclarativePixmap::connectDownloadProgress(QObject *object, const char *method)
-{
- if (!d || !d->reply) {
- qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
- return false;
- }
-
- return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
-}
-
-bool QDeclarativePixmap::connectDownloadProgress(QObject *object, int method)
-{
- if (!d || !d->reply) {
- qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
- return false;
- }
-
- return QMetaObject::connect(d->reply, QDeclarativePixmapReply::downloadProgressIndex, object, method);
-}
-
-QT_END_NAMESPACE
-
-#include <qdeclarativepixmapcache.moc>
diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h
deleted file mode 100644
index a0e35aba5d..0000000000
--- a/src/declarative/util/qdeclarativepixmapcache_p.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEPIXMAPCACHE_H
-#define QDECLARATIVEPIXMAPCACHE_H
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qstring.h>
-#include <QtGui/qpixmap.h>
-#include <QtCore/qurl.h>
-
-#include <private/qintrusivelist_p.h>
-#include <qdeclarativeimageprovider.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeEngine;
-class QDeclarativePixmapData;
-class QDeclarativeTextureFactory;
-
-class QDeclarativeDefaultTextureFactory : public QDeclarativeTextureFactory
-{
- Q_OBJECT
-public:
- QDeclarativeDefaultTextureFactory(const QImage &i)
- : im(i)
- {
- }
-
- QSGTexture *createTexture() const;
- QSize textureSize() const { return im.size(); }
- int textureByteCount() const { return im.byteCount(); }
- QImage image() const { return im; }
-
-private:
- QImage im;
-};
-
-class Q_DECLARATIVE_EXPORT QDeclarativePixmap
-{
- Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmap)
-public:
- QDeclarativePixmap();
- QDeclarativePixmap(QDeclarativeEngine *, const QUrl &);
- QDeclarativePixmap(QDeclarativeEngine *, const QUrl &, const QSize &);
- ~QDeclarativePixmap();
-
- enum Status { Null, Ready, Error, Loading };
-
- enum Option {
- Asynchronous = 0x00000001,
- Cache = 0x00000002
- };
- Q_DECLARE_FLAGS(Options, Option)
-
- bool isNull() const;
- bool isReady() const;
- bool isError() const;
- bool isLoading() const;
-
- Status status() const;
- QString error() const;
- const QUrl &url() const;
- const QSize &implicitSize() const;
- const QSize &requestSize() const;
- const QImage &image() const;
- void setImage(const QImage &);
-
- QDeclarativeTextureFactory *textureFactory() const;
-
- QRect rect() const;
- int width() const;
- int height() const;
-
- void load(QDeclarativeEngine *, const QUrl &);
- void load(QDeclarativeEngine *, const QUrl &, QDeclarativePixmap::Options options);
- void load(QDeclarativeEngine *, const QUrl &, const QSize &);
- void load(QDeclarativeEngine *, const QUrl &, const QSize &, QDeclarativePixmap::Options options);
-
- void clear();
- void clear(QObject *);
-
- bool connectFinished(QObject *, const char *);
- bool connectFinished(QObject *, int);
- bool connectDownloadProgress(QObject *, const char *);
- bool connectDownloadProgress(QObject *, int);
-
-private:
- Q_DISABLE_COPY(QDeclarativePixmap)
- QDeclarativePixmapData *d;
- QIntrusiveListNode dataListNode;
- friend class QDeclarativePixmapData;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePixmap::Options)
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEPIXMAPCACHE_H
diff --git a/src/declarative/util/qdeclarativepropertychanges_p.h b/src/declarative/util/qdeclarativepropertychanges_p.h
deleted file mode 100644
index 6d3e032b57..0000000000
--- a/src/declarative/util/qdeclarativepropertychanges_p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEPROPERTYCHANGES_H
-#define QDECLARATIVEPROPERTYCHANGES_H
-
-#include "qdeclarativestateoperations_p.h"
-#include <private/qdeclarativecustomparser_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativePropertyChangesPrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativePropertyChanges)
-
- Q_PROPERTY(QObject *target READ object WRITE setObject)
- Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
- Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
-public:
- QDeclarativePropertyChanges();
- ~QDeclarativePropertyChanges();
-
- QObject *object() const;
- void setObject(QObject *);
-
- bool restoreEntryValues() const;
- void setRestoreEntryValues(bool);
-
- bool isExplicit() const;
- void setIsExplicit(bool);
-
- virtual ActionList actions();
-
- bool containsProperty(const QString &name) const;
- bool containsValue(const QString &name) const;
- bool containsExpression(const QString &name) const;
- void changeValue(const QString &name, const QVariant &value);
- void changeExpression(const QString &name, const QString &expression);
- void removeProperty(const QString &name);
- QVariant value(const QString &name) const;
- QString expression(const QString &name) const;
-
- void detachFromState();
- void attachToState();
-
- QVariant property(const QString &name) const;
-};
-
-class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser
-{
-public:
- QDeclarativePropertyChangesParser()
- : QDeclarativeCustomParser(AcceptsAttachedProperties) {}
-
- void compileList(QList<QPair<QString, QVariant> > &list, const QString &pre, const QDeclarativeCustomParserProperty &prop);
-
- virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
- virtual void setCustomData(QObject *, const QByteArray &);
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativePropertyChanges)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEPROPERTYCHANGES_H
diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h
deleted file mode 100644
index 9417383c1e..0000000000
--- a/src/declarative/util/qdeclarativesmoothedanimation_p.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESMOOTHEDANIMATION_H
-#define QDECLARATIVESMOOTHEDANIMATION_H
-
-#include <qdeclarative.h>
-#include "qdeclarativeanimation_p.h"
-
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeProperty;
-class QDeclarativeSmoothedAnimationPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation)
- Q_ENUMS(ReversingMode)
-
- Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
- Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
- Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
-
-public:
- enum ReversingMode { Eased, Immediate, Sync };
-
- QDeclarativeSmoothedAnimation(QObject *parent = 0);
- ~QDeclarativeSmoothedAnimation();
-
- ReversingMode reversingMode() const;
- void setReversingMode(ReversingMode);
-
- virtual int duration() const;
- virtual void setDuration(int);
-
- qreal velocity() const;
- void setVelocity(qreal);
-
- int maximumEasingTime() const;
- void setMaximumEasingTime(int);
-
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
- QAbstractAnimation* qtAnimation();
-
-Q_SIGNALS:
- void velocityChanged();
- void reversingModeChanged();
- void maximumEasingTimeChanged();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESMOOTHEDANIMATION_H
diff --git a/src/declarative/util/qdeclarativespringanimation_p.h b/src/declarative/util/qdeclarativespringanimation_p.h
deleted file mode 100644
index 14a34b47c5..0000000000
--- a/src/declarative/util/qdeclarativespringanimation_p.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESPRINGANIMATION_H
-#define QDECLARATIVESPRINGANIMATION_H
-
-#include <qdeclarative.h>
-#include "qdeclarativeanimation_p.h"
-
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeSpringAnimationPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeSpringAnimation : public QDeclarativeNumberAnimation
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeSpringAnimation)
- Q_INTERFACES(QDeclarativePropertyValueSource)
-
- Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
- Q_PROPERTY(qreal spring READ spring WRITE setSpring)
- Q_PROPERTY(qreal damping READ damping WRITE setDamping)
- Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
- Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
- Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged)
-
-public:
- QDeclarativeSpringAnimation(QObject *parent=0);
- ~QDeclarativeSpringAnimation();
-
- qreal velocity() const;
- void setVelocity(qreal velocity);
-
- qreal spring() const;
- void setSpring(qreal spring);
-
- qreal damping() const;
- void setDamping(qreal damping);
-
- qreal epsilon() const;
- void setEpsilon(qreal epsilon);
-
- qreal mass() const;
- void setMass(qreal modulus);
-
- qreal modulus() const;
- void setModulus(qreal modulus);
-
- virtual void transition(QDeclarativeStateActions &actions,
- QDeclarativeProperties &modified,
- TransitionDirection direction);
-
-protected:
- virtual QAbstractAnimation *qtAnimation();
-
-Q_SIGNALS:
- void modulusChanged();
- void massChanged();
- void syncChanged();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeSpringAnimation)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESPRINGANIMATION_H
diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h
deleted file mode 100644
index a7aafe32fe..0000000000
--- a/src/declarative/util/qdeclarativestate_p.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESTATE_H
-#define QDECLARATIVESTATE_H
-
-#include <qdeclarative.h>
-#include <qdeclarativeproperty.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qsharedpointer.h>
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeActionEvent;
-class QDeclarativeAbstractBinding;
-class QDeclarativeBinding;
-class QDeclarativeExpression;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeAction
-{
-public:
- QDeclarativeAction();
- QDeclarativeAction(QObject *, const QString &, const QVariant &);
- QDeclarativeAction(QObject *, const QString &,
- QDeclarativeContext *, const QVariant &);
-
- bool restore:1;
- bool actionDone:1;
- bool reverseEvent:1;
- bool deletableToBinding:1;
-
- QDeclarativeProperty property;
- QVariant fromValue;
- QVariant toValue;
-
- QDeclarativeAbstractBinding *fromBinding;
- QWeakPointer<QDeclarativeAbstractBinding> toBinding;
- QDeclarativeActionEvent *event;
-
- //strictly for matching
- QObject *specifiedObject;
- QString specifiedProperty;
-
- void deleteFromBinding();
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeActionEvent
-{
-public:
- virtual ~QDeclarativeActionEvent();
- virtual QString typeName() const;
-
- enum Reason { ActualChange, FastForward };
-
- virtual void execute(Reason reason = ActualChange);
- virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
- virtual void saveOriginals() {}
- virtual bool needsCopy() { return false; }
- virtual void copyOriginals(QDeclarativeActionEvent *) {}
-
- virtual bool isRewindable() { return isReversable(); }
- virtual void rewind() {}
- virtual void saveCurrentValues() {}
- virtual void saveTargetValues() {}
-
- virtual bool changesBindings();
- virtual void clearBindings();
- virtual bool override(QDeclarativeActionEvent*other);
-};
-
-//### rename to QDeclarativeStateChange?
-class QDeclarativeStateGroup;
-class QDeclarativeState;
-class QDeclarativeStateOperationPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeStateOperation : public QObject
-{
- Q_OBJECT
-public:
- QDeclarativeStateOperation(QObject *parent = 0)
- : QObject(parent) {}
- typedef QList<QDeclarativeAction> ActionList;
-
- virtual ActionList actions();
-
- QDeclarativeState *state() const;
- void setState(QDeclarativeState *state);
-
-protected:
- QDeclarativeStateOperation(QObjectPrivate &dd, QObject *parent = 0);
-
-private:
- Q_DECLARE_PRIVATE(QDeclarativeStateOperation)
- Q_DISABLE_COPY(QDeclarativeStateOperation)
-};
-
-typedef QDeclarativeStateOperation::ActionList QDeclarativeStateActions;
-
-class QDeclarativeTransition;
-class QDeclarativeStatePrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeState : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QString name READ name WRITE setName)
- Q_PROPERTY(QDeclarativeBinding *when READ when WRITE setWhen)
- Q_PROPERTY(QString extend READ extends WRITE setExtends)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeStateOperation> changes READ changes)
- Q_CLASSINFO("DefaultProperty", "changes")
- Q_CLASSINFO("DeferredPropertyNames", "changes")
-
-public:
- QDeclarativeState(QObject *parent=0);
- virtual ~QDeclarativeState();
-
- QString name() const;
- void setName(const QString &);
- bool isNamed() const;
-
- /*'when' is a QDeclarativeBinding to limit state changes oscillation
- due to the unpredictable order of evaluation of bound expressions*/
- bool isWhenKnown() const;
- QDeclarativeBinding *when() const;
- void setWhen(QDeclarativeBinding *);
-
- QString extends() const;
- void setExtends(const QString &);
-
- QDeclarativeListProperty<QDeclarativeStateOperation> changes();
- int operationCount() const;
- QDeclarativeStateOperation *operationAt(int) const;
-
- QDeclarativeState &operator<<(QDeclarativeStateOperation *);
-
- void apply(QDeclarativeTransition *, QDeclarativeState *revert);
- void cancel();
-
- QDeclarativeStateGroup *stateGroup() const;
- void setStateGroup(QDeclarativeStateGroup *);
-
- bool containsPropertyInRevertList(QObject *target, const QString &name) const;
- bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue);
- bool changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding);
- bool removeEntryFromRevertList(QObject *target, const QString &name);
- void addEntryToRevertList(const QDeclarativeAction &action);
- void removeAllEntriesFromRevertList(QObject *target);
- void addEntriesToRevertList(const QList<QDeclarativeAction> &actions);
- QVariant valueInRevertList(QObject *target, const QString &name) const;
- QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QString &name) const;
-
- bool isStateActive() const;
-
-Q_SIGNALS:
- void completed();
-
-private:
- Q_DECLARE_PRIVATE(QDeclarativeState)
- Q_DISABLE_COPY(QDeclarativeState)
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeStateOperation)
-QML_DECLARE_TYPE(QDeclarativeState)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESTATE_H
diff --git a/src/declarative/util/qdeclarativestategroup_p.h b/src/declarative/util/qdeclarativestategroup_p.h
deleted file mode 100644
index c59325580b..0000000000
--- a/src/declarative/util/qdeclarativestategroup_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESTATEGROUP_H
-#define QDECLARATIVESTATEGROUP_H
-
-#include "qdeclarativestate_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeStateGroupPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeStateGroup : public QObject, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_DECLARE_PRIVATE(QDeclarativeStateGroup)
-
- Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeState> states READ statesProperty DESIGNABLE false)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitionsProperty DESIGNABLE false)
-
-public:
- QDeclarativeStateGroup(QObject * = 0);
- virtual ~QDeclarativeStateGroup();
-
- QString state() const;
- void setState(const QString &);
-
- QDeclarativeListProperty<QDeclarativeState> statesProperty();
- QList<QDeclarativeState *> states() const;
-
- QDeclarativeListProperty<QDeclarativeTransition> transitionsProperty();
-
- QDeclarativeState *findState(const QString &name) const;
- void removeState(QDeclarativeState *state);
-
- virtual void classBegin();
- virtual void componentComplete();
-Q_SIGNALS:
- void stateChanged(const QString &);
-
-private:
- friend class QDeclarativeState;
- friend class QDeclarativeStatePrivate;
- bool updateAutoState();
- void stateAboutToComplete();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeStateGroup)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESTATEGROUP_H
diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h
deleted file mode 100644
index 4975a5226f..0000000000
--- a/src/declarative/util/qdeclarativestateoperations_p.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESTATEOPERATIONS_H
-#define QDECLARATIVESTATEOPERATIONS_H
-
-#include "qdeclarativestate_p.h"
-#include <qdeclarativescriptstring.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QDeclarativeStateChangeScriptPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeStateChangeScript : public QDeclarativeStateOperation, public QDeclarativeActionEvent
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeStateChangeScript)
-
- Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
- Q_PROPERTY(QString name READ name WRITE setName)
-
-public:
- QDeclarativeStateChangeScript(QObject *parent=0);
- ~QDeclarativeStateChangeScript();
-
- virtual ActionList actions();
-
- virtual QString typeName() const;
-
- QDeclarativeScriptString script() const;
- void setScript(const QDeclarativeScriptString &);
-
- QString name() const;
- void setName(const QString &);
-
- virtual void execute(Reason reason = ActualChange);
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeStateChangeScript)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESTATEOPERATIONS_H
diff --git a/src/declarative/util/qdeclarativesystempalette_p.h b/src/declarative/util/qdeclarativesystempalette_p.h
deleted file mode 100644
index e92dc514d5..0000000000
--- a/src/declarative/util/qdeclarativesystempalette_p.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVESYSTEMPALETTE_H
-#define QDECLARATIVESYSTEMPALETTE_H
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-#include <QPalette>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeSystemPalettePrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeSystemPalette : public QObject
-{
- Q_OBJECT
- Q_ENUMS(ColorGroup)
- Q_DECLARE_PRIVATE(QDeclarativeSystemPalette)
-
- Q_PROPERTY(QDeclarativeSystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
- Q_PROPERTY(QColor window READ window NOTIFY paletteChanged)
- Q_PROPERTY(QColor windowText READ windowText NOTIFY paletteChanged)
- Q_PROPERTY(QColor base READ base NOTIFY paletteChanged)
- Q_PROPERTY(QColor text READ text NOTIFY paletteChanged)
- Q_PROPERTY(QColor alternateBase READ alternateBase NOTIFY paletteChanged)
- Q_PROPERTY(QColor button READ button NOTIFY paletteChanged)
- Q_PROPERTY(QColor buttonText READ buttonText NOTIFY paletteChanged)
- Q_PROPERTY(QColor light READ light NOTIFY paletteChanged)
- Q_PROPERTY(QColor midlight READ midlight NOTIFY paletteChanged)
- Q_PROPERTY(QColor dark READ dark NOTIFY paletteChanged)
- Q_PROPERTY(QColor mid READ mid NOTIFY paletteChanged)
- Q_PROPERTY(QColor shadow READ shadow NOTIFY paletteChanged)
- Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
- Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged)
-
-public:
- QDeclarativeSystemPalette(QObject *parent=0);
- ~QDeclarativeSystemPalette();
-
- enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
-
- QColor window() const;
- QColor windowText() const;
-
- QColor base() const;
- QColor text() const;
- QColor alternateBase() const;
-
- QColor button() const;
- QColor buttonText() const;
-
- QColor light() const;
- QColor midlight() const;
- QColor dark() const;
- QColor mid() const;
- QColor shadow() const;
-
- QColor highlight() const;
- QColor highlightedText() const;
-
- QDeclarativeSystemPalette::ColorGroup colorGroup() const;
- void setColorGroup(QDeclarativeSystemPalette::ColorGroup);
-
-Q_SIGNALS:
- void paletteChanged();
-
-private:
- bool eventFilter(QObject *watched, QEvent *event);
- bool event(QEvent *event);
-
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeSystemPalette)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVESYSTEMPALETTE_H
diff --git a/src/declarative/util/qdeclarativetimer_p.h b/src/declarative/util/qdeclarativetimer_p.h
deleted file mode 100644
index 7de56068dd..0000000000
--- a/src/declarative/util/qdeclarativetimer_p.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVETIMER_H
-#define QDECLARATIVETIMER_H
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-#include <QtCore/qabstractanimation.h>
-
-#include <private/qdeclarativeglobal_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeTimerPrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeTimer : public QObject, public QDeclarativeParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeTimer)
- Q_INTERFACES(QDeclarativeParserStatus)
- Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged)
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged)
- Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
- Q_PROPERTY(QObject *parent READ parent CONSTANT)
-
-public:
- QDeclarativeTimer(QObject *parent=0);
-
- void setInterval(int interval);
- int interval() const;
-
- bool isRunning() const;
- void setRunning(bool running);
-
- bool isRepeating() const;
- void setRepeating(bool repeating);
-
- bool triggeredOnStart() const;
- void setTriggeredOnStart(bool triggeredOnStart);
-
-protected:
- void classBegin();
- void componentComplete();
-
-public Q_SLOTS:
- void start();
- void stop();
- void restart();
-
-Q_SIGNALS:
- void triggered();
- void runningChanged();
- void intervalChanged();
- void repeatChanged();
- void triggeredOnStartChanged();
-
-private:
- void update();
-
-private Q_SLOTS:
- void ticked();
- void finished();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeTimer)
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/util/qdeclarativetransition_p.h b/src/declarative/util/qdeclarativetransition_p.h
deleted file mode 100644
index a53346e148..0000000000
--- a/src/declarative/util/qdeclarativetransition_p.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVETRANSITION_H
-#define QDECLARATIVETRANSITION_H
-
-#include "qdeclarativestate_p.h"
-
-#include <qdeclarative.h>
-
-#include <QtCore/qobject.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeAbstractAnimation;
-class QDeclarativeTransitionPrivate;
-class QDeclarativeTransitionManager;
-class Q_DECLARATIVE_EXPORT QDeclarativeTransition : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeTransition)
-
- Q_PROPERTY(QString from READ fromState WRITE setFromState NOTIFY fromChanged)
- Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged)
- Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- Q_CLASSINFO("DefaultProperty", "animations")
- Q_CLASSINFO("DeferredPropertyNames", "animations")
-
-public:
- QDeclarativeTransition(QObject *parent=0);
- ~QDeclarativeTransition();
-
- QString fromState() const;
- void setFromState(const QString &);
-
- QString toState() const;
- void setToState(const QString &);
-
- bool reversible() const;
- void setReversible(bool);
-
- bool enabled() const;
- void setEnabled(bool enabled);
-
- QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations();
-
- void prepare(QDeclarativeStateOperation::ActionList &actions,
- QList<QDeclarativeProperty> &after,
- QDeclarativeTransitionManager *end);
-
- void setReversed(bool r);
- void stop();
-
-Q_SIGNALS:
- void fromChanged();
- void toChanged();
- void reversibleChanged();
- void enabledChanged();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QDeclarativeTransition)
-
-QT_END_HEADER
-
-#endif // QDECLARATIVETRANSITION_H
diff --git a/src/declarative/util/qdeclarativeutilmodule_p.h b/src/declarative/util/qdeclarativeutilmodule_p.h
deleted file mode 100644
index 7304f6fd77..0000000000
--- a/src/declarative/util/qdeclarativeutilmodule_p.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 QDECLARATIVEUTILMODULE_H
-#define QDECLARATIVEUTILMODULE_H
-
-#include <qdeclarative.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QDeclarativeUtilModule
-{
-public:
- static void defineModule();
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEUTILMODULE_H
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index 3122cd24bb..01d4247ff8 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -1,61 +1,5 @@
SOURCES += \
- $$PWD/qdeclarativeutilmodule.cpp\
- $$PWD/qdeclarativeconnections.cpp \
- $$PWD/qdeclarativepackage.cpp \
- $$PWD/qdeclarativeanimation.cpp \
- $$PWD/qdeclarativesystempalette.cpp \
- $$PWD/qdeclarativespringanimation.cpp \
- $$PWD/qdeclarativesmoothedanimation.cpp \
- $$PWD/qdeclarativestate.cpp\
- $$PWD/qdeclarativetransitionmanager.cpp \
- $$PWD/qdeclarativestateoperations.cpp \
- $$PWD/qdeclarativepropertychanges.cpp \
- $$PWD/qdeclarativestategroup.cpp \
- $$PWD/qdeclarativetransition.cpp \
- $$PWD/qdeclarativelistaccessor.cpp \
- $$PWD/qdeclarativetimeline.cpp \
- $$PWD/qdeclarativetimer.cpp \
- $$PWD/qdeclarativebind.cpp \
- $$PWD/qdeclarativepropertymap.cpp \
- $$PWD/qdeclarativepixmapcache.cpp \
- $$PWD/qdeclarativebehavior.cpp \
- $$PWD/qdeclarativefontloader.cpp \
- $$PWD/qdeclarativestyledtext.cpp \
- $$PWD/qdeclarativepath.cpp \
- $$PWD/qdeclarativechangeset.cpp \
- $$PWD/qdeclarativelistcompositor.cpp \
- $$PWD/qdeclarativepathinterpolator.cpp \
- $$PWD/qdeclarativesvgparser.cpp
+ $$PWD/qdeclarativepropertymap.cpp
HEADERS += \
- $$PWD/qdeclarativeutilmodule_p.h\
- $$PWD/qdeclarativeconnections_p.h \
- $$PWD/qdeclarativepackage_p.h \
- $$PWD/qdeclarativeanimation_p.h \
- $$PWD/qdeclarativeanimation_p_p.h \
- $$PWD/qdeclarativesystempalette_p.h \
- $$PWD/qdeclarativespringanimation_p.h \
- $$PWD/qdeclarativesmoothedanimation_p.h \
- $$PWD/qdeclarativesmoothedanimation_p_p.h \
- $$PWD/qdeclarativestate_p.h\
- $$PWD/qdeclarativestateoperations_p.h \
- $$PWD/qdeclarativepropertychanges_p.h \
- $$PWD/qdeclarativestate_p_p.h\
- $$PWD/qdeclarativetransitionmanager_p_p.h \
- $$PWD/qdeclarativestategroup_p.h \
- $$PWD/qdeclarativetransition_p.h \
- $$PWD/qdeclarativelistaccessor_p.h \
- $$PWD/qdeclarativetimeline_p_p.h \
- $$PWD/qdeclarativetimer_p.h \
- $$PWD/qdeclarativebind_p.h \
- $$PWD/qdeclarativepropertymap.h \
- $$PWD/qdeclarativepixmapcache_p.h \
- $$PWD/qdeclarativebehavior_p.h \
- $$PWD/qdeclarativefontloader_p.h \
- $$PWD/qdeclarativestyledtext_p.h \
- $$PWD/qdeclarativepath_p.h \
- $$PWD/qdeclarativepath_p_p.h \
- $$PWD/qdeclarativechangeset_p.h \
- $$PWD/qdeclarativelistcompositor_p.h \
- $$PWD/qdeclarativepathinterpolator_p.h \
- $$PWD/qdeclarativesvgparser_p.h \ No newline at end of file
+ $$PWD/qdeclarativepropertymap.h
diff --git a/src/imports/etcprovider/etcprovider.pro b/src/imports/etcprovider/etcprovider.pro
index b48235eed8..3ec3ab5d09 100644
--- a/src/imports/etcprovider/etcprovider.pro
+++ b/src/imports/etcprovider/etcprovider.pro
@@ -3,7 +3,7 @@ TARGETPATH = Qt/labs/etcprovider
include(../qimportbase.pri)
!contains(QT_CONFIG, egl):DEFINES += QT_NO_EGL
-QT += declarative opengl
+QT += declarative quick opengl
SOURCES += qetcprovider.cpp plugin.cpp
HEADERS += qetcprovider.h plugin.h
diff --git a/src/imports/etcprovider/qetcprovider.h b/src/imports/etcprovider/qetcprovider.h
index cac37584d4..42c8e410db 100644
--- a/src/imports/etcprovider/qetcprovider.h
+++ b/src/imports/etcprovider/qetcprovider.h
@@ -44,7 +44,7 @@
#include <qopengl.h>
#include <QDeclarativeImageProvider>
-#include <QSGTexture>
+#include <QtQuick/QSGTexture>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>
#include <QFileInfo>
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 35590b221d..18400f86f2 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
-SUBDIRS += qtquick1 qt47 folderlistmodel particles gestures etcprovider
+SUBDIRS += qtquick2 qtquick1 qt47 folderlistmodel particles gestures etcprovider
contains(QT_CONFIG, qmltest): SUBDIRS += testlib
-contains(QT_CONFIG, xmlpatterns) : SUBDIRS += xmllistmodel \ No newline at end of file
+contains(QT_CONFIG, xmlpatterns) : SUBDIRS += xmllistmodel
diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp
new file mode 100644
index 0000000000..a0def068d9
--- /dev/null
+++ b/src/imports/qtquick2/plugin.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 <QtDeclarative/qdeclarativeextensionplugin.h>
+
+#include <private/qtquick2_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//![class decl]
+class QtQuick2Plugin : public QDeclarativeExtensionPlugin
+{
+ Q_OBJECT
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick"));
+ QDeclarativeQtQuick2Module::defineModule();
+ }
+};
+//![class decl]
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
+
+//![plugin export decl]
+Q_EXPORT_PLUGIN2(qtquick2plugin, QT_PREPEND_NAMESPACE(QtQuick2Plugin));
+//![plugin export decl]
+
diff --git a/src/imports/qtquick2/qmldir b/src/imports/qtquick2/qmldir
new file mode 100644
index 0000000000..bb4d33a5be
--- /dev/null
+++ b/src/imports/qtquick2/qmldir
@@ -0,0 +1 @@
+plugin qtquick2plugin
diff --git a/src/imports/qtquick2/qtquick2.pro b/src/imports/qtquick2/qtquick2.pro
new file mode 100644
index 0000000000..3f76abd87f
--- /dev/null
+++ b/src/imports/qtquick2/qtquick2.pro
@@ -0,0 +1,19 @@
+TARGET = qtquick2plugin
+TARGETPATH = QtQuick.2
+include(../qimportbase.pri)
+
+SOURCES += \
+ plugin.cpp
+
+QT += quick-private declarative-private
+
+OTHER_FILES += \
+ qmldir
+
+DESTDIR = $$QT.declarative.imports/$$TARGETPATH
+target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+qmldir.files += $$PWD/qmldir
+qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+INSTALLS += target qmldir
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index c7d7d9191e..0d3669970f 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -46,7 +46,7 @@
#include "QtQuickTest/private/quicktestresult_p.h"
#include "QtQuickTest/private/quicktestevent_p.h"
#include "private/qtestoptions_p.h"
-#include "QtDeclarative/qquickitem.h"
+#include "QtQuick/qquickitem.h"
#include <QtDeclarative/private/qdeclarativeengine_p.h>
QML_DECLARE_TYPE(QuickTestResult)
diff --git a/src/imports/testlib/testlib.pro b/src/imports/testlib/testlib.pro
index dbe45fb6fa..3b8a5bf75e 100644
--- a/src/imports/testlib/testlib.pro
+++ b/src/imports/testlib/testlib.pro
@@ -4,7 +4,7 @@ include(../qimportbase.pri)
CONFIG += qt plugin
-QT += declarative qmltest qmltest-private v8-private declarative-private core-private testlib
+QT += declarative quick qmltest qmltest-private v8-private declarative-private core-private testlib
SOURCES += main.cpp
HEADERS +=
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
index a06c1bdc10..ed6ba4cf29 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
@@ -1,7 +1,7 @@
load(qt_module)
TARGET = qmldbg_qtquick2
-QT += declarative-private core-private gui-private opengl-private v8-private
+QT += declarative-private quick-private core-private gui-private opengl-private v8-private
load(qt_plugin)
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
index 5ed919c87c..33b8cc1b4e 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
@@ -44,7 +44,7 @@
#include <QtCore/qplugin.h>
#include <QtDeclarative/private/qdeclarativeinspectorservice_p.h>
-#include <QtDeclarative/QQuickView>
+#include <QtQuick/QQuickView>
namespace QmlJSDebugger {
namespace QtQuick2 {
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/sghighlight.h b/src/plugins/qmltooling/qmldbg_qtquick2/sghighlight.h
index 8ba1af6576..d6c380e0d2 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/sghighlight.h
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/sghighlight.h
@@ -43,7 +43,7 @@
#define SGHIGHLIGHT_H
#include <QtCore/QWeakPointer>
-#include <QtDeclarative/QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
namespace QmlJSDebugger {
namespace QtQuick2 {
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/sgselectiontool.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/sgselectiontool.cpp
index 4d5fc3738d..f96f7d2422 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/sgselectiontool.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/sgselectiontool.cpp
@@ -45,8 +45,8 @@
#include "sgviewinspector.h"
#include <QtGui/QMouseEvent>
-#include <QtDeclarative/QQuickView>
-#include <QtDeclarative/QQuickItem>
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
namespace QmlJSDebugger {
namespace QtQuick2 {
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/sgviewinspector.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/sgviewinspector.cpp
index 06eb6eac97..a1c2c1a1b2 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/sgviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/sgviewinspector.cpp
@@ -45,10 +45,10 @@
#include "sghighlight.h"
#include "sgselectiontool.h"
-#include <QtDeclarative/private/qquickitem_p.h>
+#include <QtQuick/private/qquickitem_p.h>
-#include <QtDeclarative/QQuickView>
-#include <QtDeclarative/QQuickItem>
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
#include <cfloat>
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index ff04487b18..cc2466639c 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -7,7 +7,7 @@ CONFIG += module
CONFIG += dll warn_on declarative_debug
MODULE_PRI += ../../modules/qt_qmltest.pri
-QT += testlib-private declarative testlib qtquick1 widgets widgets-private gui
+QT += testlib-private declarative testlib quick qtquick1 widgets widgets-private gui
DEFINES += QT_BUILD_QUICK_TEST_LIB QT_NO_URL_CAST_FROM_STRING
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 976b4d6de0..65107ee717 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -49,7 +49,7 @@
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecontext.h>
#if defined(QML_VERSION) && QML_VERSION >= 0x020000
-#include <QtDeclarative/qquickview.h>
+#include <QtQuick/qquickview.h>
#define QUICK_TEST_SCENEGRAPH 1
#endif
#include <QtDeclarative/qjsvalue.h>
diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp
index 780d502f52..e865954460 100644
--- a/src/qmltest/quicktestevent.cpp
+++ b/src/qmltest/quicktestevent.cpp
@@ -45,8 +45,8 @@
#include <QtQuick1/qdeclarativeitem.h>
#include <QtQuick1/qdeclarativeview.h>
#if defined(QML_VERSION) && QML_VERSION >= 0x020000
-#include <QtDeclarative/qquickitem.h>
-#include <QtDeclarative/qquickcanvas.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickcanvas.h>
#define QUICK_TEST_SCENEGRAPH 1
#endif
#include <QtWidgets/qgraphicsscene.h>
diff --git a/src/declarative/designer/designer.pri b/src/quick/designer/designer.pri
index c523525977..c523525977 100644
--- a/src/declarative/designer/designer.pri
+++ b/src/quick/designer/designer.pri
diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/designersupport.cpp
new file mode 100644
index 0000000000..04a176f511
--- /dev/null
+++ b/src/quick/designer/designersupport.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "designersupport.h"
+#include <private/qquickitem_p.h>
+
+#include <QtQuick/private/qquickshadereffectsource_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <private/qquickview_p.h>
+#include <QtQuick/private/qdeclarativestategroup_p.h>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+DesignerSupport::DesignerSupport()
+{
+}
+
+DesignerSupport::~DesignerSupport()
+{
+ QHash<QQuickItem*, QQuickShaderEffectTexture*>::iterator iterator;
+
+ for (iterator = m_itemTextureHash.begin(); iterator != m_itemTextureHash.end(); ++iterator) {
+ QQuickShaderEffectTexture *texture = iterator.value();
+ QQuickItem *item = iterator.key();
+ QQuickItemPrivate::get(item)->derefFromEffectItem(true);
+ delete texture;
+ }
+}
+
+void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
+{
+ if (referencedItem == 0)
+ return;
+
+ QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
+ QQuickCanvasPrivate::get(referencedItem->canvas())->updateDirtyNode(referencedItem);
+
+ Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode);
+
+ if (!m_itemTextureHash.contains(referencedItem)) {
+ QQuickShaderEffectTexture *texture = new QQuickShaderEffectTexture(referencedItem);
+
+ texture->setLive(true);
+ texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode);
+ texture->setRect(referencedItem->boundingRect());
+ texture->setSize(referencedItem->boundingRect().size().toSize());
+ texture->setRecursive(true);
+#ifndef QT_OPENGL_ES
+ texture->setFormat(GL_RGBA8);
+#else
+ texture->setFormat(GL_RGBA);
+#endif
+ texture->setHasMipmaps(false);
+
+ m_itemTextureHash.insert(referencedItem, texture);
+ }
+}
+
+void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
+{
+ if (referencedItem == 0)
+ return;
+
+ delete m_itemTextureHash.take(referencedItem);
+ QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
+}
+
+QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
+{
+ if (referencedItem == 0 || referencedItem->parentItem() == 0) {
+ qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
+ return QImage();
+ }
+
+ QQuickShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
+
+ Q_ASSERT(renderTexture);
+ if (renderTexture == 0)
+ return QImage();
+ renderTexture->setRect(boundingRect);
+ renderTexture->setSize(imageSize);
+ renderTexture->updateTexture();
+
+ QImage renderImage = renderTexture->toImage();
+ renderImage = renderImage.mirrored(false, true);
+
+ if (renderImage.size().isEmpty())
+ qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
+
+ return renderImage;
+}
+
+bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
+{
+ if (referencedItem == 0)
+ return false;
+
+ return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
+}
+
+void DesignerSupport::resetDirty(QQuickItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return;
+
+ QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
+ QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
+}
+
+QTransform DesignerSupport::canvasTransform(QQuickItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return QTransform();
+
+ return QQuickItemPrivate::get(referencedItem)->itemToCanvasTransform();
+}
+
+QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return QTransform();
+
+ QTransform parentTransform;
+
+ QQuickItemPrivate::get(referencedItem)->itemToParentTransform(parentTransform);
+
+ return parentTransform;
+}
+
+QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
+{
+ switch (anchorLine) {
+ case QQuickAnchorLine::Left: return QLatin1String("left");
+ case QQuickAnchorLine::Right: return QLatin1String("right");
+ case QQuickAnchorLine::Top: return QLatin1String("top");
+ case QQuickAnchorLine::Bottom: return QLatin1String("bottom");
+ case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter");
+ case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter");
+ case QQuickAnchorLine::Baseline: return QLatin1String("baseline");
+ case QQuickAnchorLine::Invalid:
+ default: return QString();
+ }
+}
+
+bool isValidAnchorName(const QString &name)
+{
+ static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
+ << QLatin1String("anchors.left")
+ << QLatin1String("anchors.right")
+ << QLatin1String("anchors.bottom")
+ << QLatin1String("anchors.verticalCenter")
+ << QLatin1String("anchors.horizontalCenter")
+ << QLatin1String("anchors.fill")
+ << QLatin1String("anchors.centerIn")
+ << QLatin1String("anchors.baseline"));
+
+ return anchorNameList.contains(name);
+}
+
+bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+{
+ Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
+ QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
+ QQuickAnchors *anchors = fromItemPrivate->anchors();
+ return anchors->fill() == toItem
+ || anchors->centerIn() == toItem
+ || anchors->bottom().item == toItem
+ || anchors->top().item == toItem
+ || anchors->left().item == toItem
+ || anchors->right().item == toItem
+ || anchors->verticalCenter().item == toItem
+ || anchors->horizontalCenter().item == toItem
+ || anchors->baseline().item == toItem;
+}
+
+bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+{
+ foreach (QQuickItem *childItem, fromItem->childItems()) {
+ if (childItem) {
+ if (isAnchoredTo(childItem, toItem))
+ return true;
+
+ if (areChildrenAnchoredTo(childItem, toItem))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QQuickAnchors *anchors(QQuickItem *item)
+{
+ QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
+ return itemPrivate->anchors();
+}
+
+QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
+{
+ if (name == QLatin1String("anchors.top"))
+ return QQuickAnchors::TopAnchor;
+
+ if (name == QLatin1String("anchors.left"))
+ return QQuickAnchors::LeftAnchor;
+
+ if (name == QLatin1String("anchors.bottom"))
+ return QQuickAnchors::BottomAnchor;
+
+ if (name == QLatin1String("anchors.right"))
+ return QQuickAnchors::RightAnchor;
+
+ if (name == QLatin1String("anchors.horizontalCenter"))
+ return QQuickAnchors::HCenterAnchor;
+
+ if (name == QLatin1String("anchors.verticalCenter"))
+ return QQuickAnchors::VCenterAnchor;
+
+ if (name == QLatin1String("anchors.baseline"))
+ return QQuickAnchors::BaselineAnchor;
+
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
+ return QQuickAnchors::LeftAnchor;
+}
+
+bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
+{
+ if (!isValidAnchorName(name))
+ return false;
+
+ if (name == QLatin1String("anchors.fill"))
+ return anchors(item)->fill() != 0;
+
+ if (name == QLatin1String("anchors.centerIn"))
+ return anchors(item)->centerIn() != 0;
+
+ if (name == QLatin1String("anchors.right"))
+ return anchors(item)->right().item != 0;
+
+ if (name == QLatin1String("anchors.top"))
+ return anchors(item)->top().item != 0;
+
+ if (name == QLatin1String("anchors.left"))
+ return anchors(item)->left().item != 0;
+
+ if (name == QLatin1String("anchors.bottom"))
+ return anchors(item)->bottom().item != 0;
+
+ if (name == QLatin1String("anchors.horizontalCenter"))
+ return anchors(item)->horizontalCenter().item != 0;
+
+ if (name == QLatin1String("anchors.verticalCenter"))
+ return anchors(item)->verticalCenter().item != 0;
+
+ if (name == QLatin1String("anchors.baseline"))
+ return anchors(item)->baseline().item != 0;
+
+ return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
+}
+
+QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
+{
+ return anchors(item)->fill();
+}
+
+QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
+{
+ return anchors(item)->centerIn();
+}
+
+
+
+QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context)
+{
+ QObject *targetObject = 0;
+ QString targetName;
+
+ if (name == QLatin1String("anchors.fill")) {
+ targetObject = anchors(item)->fill();
+ } else if (name == QLatin1String("anchors.centerIn")) {
+ targetObject = anchors(item)->centerIn();
+ } else {
+ QDeclarativeProperty metaProperty(item, name, context);
+ if (!metaProperty.isValid())
+ return QPair<QString, QObject*>();
+
+ QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
+ if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
+ targetObject = anchorLine.item;
+ targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
+ }
+
+ }
+
+ return QPair<QString, QObject*>(targetName, targetObject);
+}
+
+void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
+{
+ if (name == QLatin1String("anchors.fill")) {
+ anchors(item)->resetFill();
+ } else if (name == QLatin1String("anchors.centerIn")) {
+ anchors(item)->resetCenterIn();
+ } else if (name == QLatin1String("anchors.top")) {
+ anchors(item)->resetTop();
+ } else if (name == QLatin1String("anchors.left")) {
+ anchors(item)->resetLeft();
+ } else if (name == QLatin1String("anchors.right")) {
+ anchors(item)->resetRight();
+ } else if (name == QLatin1String("anchors.bottom")) {
+ anchors(item)->resetBottom();
+ } else if (name == QLatin1String("anchors.horizontalCenter")) {
+ anchors(item)->resetHorizontalCenter();
+ } else if (name == QLatin1String("anchors.verticalCenter")) {
+ anchors(item)->resetVerticalCenter();
+ } else if (name == QLatin1String("anchors.baseline")) {
+ anchors(item)->resetBaseline();
+ }
+}
+
+QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
+{
+ QList<QObject*> objectList;
+ QList<QDeclarativeState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
+ qCopy(stateList.begin(), stateList.end(), objectList.begin());
+
+ return objectList;
+}
+
+bool DesignerSupport::isComponentComplete(QQuickItem *item)
+{
+ return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
+}
+
+int DesignerSupport::borderWidth(QQuickItem *item)
+{
+ QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
+ if (rectangle)
+ return rectangle->border()->width();
+
+ return 0;
+}
+
+void DesignerSupport::refreshExpressions(QDeclarativeContext *context)
+{
+ QDeclarativeContextPrivate::get(context)->data->refreshExpressions();
+}
+
+void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
+{
+ QQuickViewPrivate::get(view)->setRootObject(item);
+}
+
+bool DesignerSupport::isValidWidth(QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->heightValid;
+}
+
+bool DesignerSupport::isValidHeight(QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->widthValid;
+}
+
+void DesignerSupport::updateDirtyNode(QQuickItem *item)
+{
+ QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/designer/designersupport.h b/src/quick/designer/designersupport.h
new file mode 100644
index 0000000000..18546eca66
--- /dev/null
+++ b/src/quick/designer/designersupport.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DESIGNERSUPPORT_H
+#define DESIGNERSUPPORT_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 <QtQuick/qtquickglobal.h>
+#include <QtCore/QtGlobal>
+#include <QtCore/QHash>
+#include <QtCore/QRectF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickShaderEffectTexture;
+class QImage;
+class QTransform;
+class QDeclarativeContext;
+class QQuickView;
+
+
+class Q_QUICK_EXPORT DesignerSupport
+{
+public:
+ enum DirtyType {
+ TransformOrigin = 0x00000001,
+ Transform = 0x00000002,
+ BasicTransform = 0x00000004,
+ Position = 0x00000008,
+ Size = 0x00000010,
+
+ ZValue = 0x00000020,
+ Content = 0x00000040,
+ Smooth = 0x00000080,
+ OpacityValue = 0x00000100,
+ ChildrenChanged = 0x00000200,
+ ChildrenStackingChanged = 0x00000400,
+ ParentChanged = 0x00000800,
+
+ Clip = 0x00001000,
+ Canvas = 0x00002000,
+
+ EffectReference = 0x00008000,
+ Visible = 0x00010000,
+ HideReference = 0x00020000,
+
+ TransformUpdateMask = TransformOrigin | Transform | BasicTransform | Position | Size | Canvas,
+ ComplexTransformUpdateMask = Transform | Canvas,
+ ContentUpdateMask = Size | Content | Smooth | Canvas,
+ ChildrenUpdateMask = ChildrenChanged | ChildrenStackingChanged | EffectReference | Canvas
+ };
+
+
+ DesignerSupport();
+ ~DesignerSupport();
+
+ void refFromEffectItem(QQuickItem *referencedItem, bool hide = true);
+ void derefFromEffectItem(QQuickItem *referencedItem, bool unhide = true);
+
+ QImage renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize);
+
+ static bool isDirty(QQuickItem *referencedItem, DirtyType dirtyType);
+ static void resetDirty(QQuickItem *referencedItem);
+
+ static QTransform canvasTransform(QQuickItem *referencedItem);
+ static QTransform parentTransform(QQuickItem *referencedItem);
+
+ static bool isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem);
+ static bool areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem);
+ static bool hasAnchor(QQuickItem *item, const QString &name);
+ static QQuickItem *anchorFillTargetItem(QQuickItem *item);
+ static QQuickItem *anchorCenterInTargetItem(QQuickItem *item);
+ static QPair<QString, QObject*> anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context);
+ static void resetAnchor(QQuickItem *item, const QString &name);
+
+
+ static QList<QObject*> statesForItem(QQuickItem *item);
+
+ static bool isComponentComplete(QQuickItem *item);
+
+ static int borderWidth(QQuickItem *item);
+
+ static void refreshExpressions(QDeclarativeContext *context);
+
+ static void setRootItem(QQuickView *view, QQuickItem *item);
+
+ static bool isValidWidth(QQuickItem *item);
+ static bool isValidHeight(QQuickItem *item);
+
+ static void updateDirtyNode(QQuickItem *item);
+
+private:
+ QHash<QQuickItem*, QQuickShaderEffectTexture*> m_itemTextureHash;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DESIGNERSUPPORT_H
diff --git a/src/declarative/items/checksync.pl b/src/quick/items/checksync.pl
index 7dffa72e88..7dffa72e88 100755
--- a/src/declarative/items/checksync.pl
+++ b/src/quick/items/checksync.pl
diff --git a/src/declarative/items/context2d/context2d.pri b/src/quick/items/context2d/context2d.pri
index 60b3e4b0c1..60b3e4b0c1 100644
--- a/src/declarative/items/context2d/context2d.pri
+++ b/src/quick/items/context2d/context2d.pri
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
new file mode 100644
index 0000000000..32809babed
--- /dev/null
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -0,0 +1,714 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <private/qsgadaptationlayer_p.h>
+#include "qquickcanvasitem_p.h"
+#include <private/qquickitem_p.h>
+#include "qquickcontext2d_p.h"
+#include "qquickcontext2dnode_p.h"
+#include "qquickcontext2dtexture_p.h"
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+
+#include <qdeclarativeinfo.h>
+#include <private/qdeclarativeengine_p.h>
+#include <QtCore/QBuffer>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCanvasItemPrivate : public QQuickItemPrivate
+{
+public:
+ QQuickCanvasItemPrivate();
+ ~QQuickCanvasItemPrivate();
+ QQuickContext2D* context;
+ QQuickContext2DTexture* texture;
+ QSizeF canvasSize;
+ QSize tileSize;
+ QRectF canvasWindow;
+ QRectF dirtyRect;
+ uint renderInThread : 1;
+ uint hasCanvasSize :1;
+ uint hasTileSize :1;
+ uint hasCanvasWindow :1;
+ uint componentCompleted :1;
+ QQuickCanvasItem::RenderTarget renderTarget;
+ QHash<QUrl, QDeclarativePixmap*> images;
+ QUrl baseUrl;
+};
+
+QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
+ : QQuickItemPrivate()
+ , context(0)
+ , texture(0)
+ , canvasSize(1, 1)
+ , tileSize(1, 1)
+ , renderInThread(false)
+ , hasCanvasSize(false)
+ , hasTileSize(false)
+ , hasCanvasWindow(false)
+ , componentCompleted(false)
+ , renderTarget(QQuickCanvasItem::FramebufferObject)
+{
+}
+
+QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
+{
+ qDeleteAll(images);
+}
+
+/*!
+ \qmlclass Canvas QQuickCanvasItem
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.0
+ \brief The Canvas item provides a 2D canvas element which enables drawing via Javascript.
+ \inherits Item
+ \ingroup qml-basic-visual-elements
+
+ The Canvas item allows drawing of straight and curved lines, simple and
+ complex shapes, graphs, and referenced graphic images. It can also add text, colors,
+ shadows, gradients, and patterns, and do low level pixel operations. The Canvas
+ output may be saved as an image file or serialized to a url.
+
+ To define a drawing area in the Canvas item set the \c width and \c height properties.
+ For example, the following code creates a Canvas item which has a drawing area with a height of 100
+ pixels and width of 200 pixels:
+ \qml
+ import QtQuick 2.0
+ Canvas {
+ id:mycanvas
+ width:100
+ height:200
+ }
+ \endqml
+
+ Currently the Canvas item only supports the two-dimensional rendering context.
+
+ \section1 Threaded Rendering and Render Target
+
+ The Canvas item supports two render targets: \c Canvas.Image and \c Canvas.FramebufferObject.
+
+ The \c Canvas.Image render target is a \a QImage object. This render target supports background
+ thread rendering, allowing complex or long running painting to be executed without blocking the UI.
+
+ The Canvas.FramebufferObject render target utilizes OpenGL hardware accelaration rather than rendering into
+ system memory, which in many cases results in faster rendering.
+
+ The default render target is Canvas.Image and the default renderInThread property is
+ false.
+
+ \section1 Tiled Canvas
+ The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize
+ and \l canvasWindow properties.
+
+ Tiling allows efficient display of a very large virtual via a smaller canvas
+ window. The actual memory consumption is in relatation to the canvas window size. The painting
+ code can draw within the virtual canvas without handling coordinate system transformations.
+
+ The tiles overlapping with the canvas window may be cached eliminating the need to redraw,
+ which can lead to significantly improved performance in some situations.
+
+ \section1 Pixel Operations
+ All HTML5 2D context pixel operations are supported. In order to ensure improved
+ pixel reading/writing performance the \a Canvas.Image render target should be chosen. The
+ \a Canvas.FramebufferObject render target requires the pixel data to be exchanged between
+ the system memory and the graphic card, which is significantly more expensive. Rendering
+ may also be synchronized with the V-sync signal (to avoid {en.wikipedia.org/wiki/Screen_tearing}{screen tearing})
+ which will futher impact pixel operations with \c Canvas.FrambufferObject render target.
+
+ \section1 Tips for Porting Existing HTML5 Canvas applications
+
+ Although the Canvas item is provides a HTML5 like API, HTML5 canvas applications
+ need to be modified to run in the Canvas item:
+ \list
+ \o Replace all DOM API calls with QML property bindings or Canvas item methods.
+ \o Replace all HTML event handlers with the \a MouseArea item.
+ \o Change setInterval/setTimeout function calls with the \a Timer item.
+ \o Place painting code into the \a QtQuick2::Canvas::onPaint handler and trigger
+ painting by calling the \c markDirty or \c requestPaint methods.
+ \o To draw images, load them by calling the Canvas's loadImage method and then request to paint
+ them in the onImageLoaded handler.
+ \endlist
+
+ \sa QtQuick2::Context2D
+*/
+
+QQuickCanvasItem::QQuickCanvasItem(QQuickItem *parent)
+ : QQuickItem(*(new QQuickCanvasItemPrivate), parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QQuickCanvasItem::~QQuickCanvasItem()
+{
+ Q_D(QQuickCanvasItem);
+ delete d->context;
+}
+
+/*!
+ \qmlproperty size QtQuick2::Canvas::canvasSize
+ Holds the logical canvas size that the context paints on.
+
+ By default, the canvas size is the same size as the current canvas item size.
+ By setting the canvasSize, tileSize and canvasWindow, the Canvas
+ item can act as a large virtual canvas with many seperately rendered tile rectangles
+ Only those tiles within the current canvas window are painted by
+ the Canvas render engine.
+
+ \sa QtQuick2::Canvas::tileSize QtQuick2::Canvas::canvasWindow
+*/
+QSizeF QQuickCanvasItem::canvasSize() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->canvasSize;
+}
+
+void QQuickCanvasItem::setCanvasSize(const QSizeF & size)
+{
+ Q_D(QQuickCanvasItem);
+ if (d->canvasSize != size) {
+ d->hasCanvasSize = true;
+ d->canvasSize = size;
+ emit canvasSizeChanged();
+ polish();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty size QtQuick2::Canvas::tileSize
+ Holds the canvas rendering tile size.
+
+ The Canvas item enters tiled mode by setting canvasSize, tileSize and
+ the canvasWindow. This can improve rendering performance
+ by rendering and caching tiles instead of rendering the whole canvas every time.
+
+ Memory will be consumed only by those tiles within the current visible region.
+
+ By default the tileSize is the same as the canvasSize.
+
+ \sa QtQuick2::Canvas::canvaasSize QtQuick2::Canvas::canvasWindow
+*/
+QSize QQuickCanvasItem::tileSize() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->tileSize;
+}
+
+void QQuickCanvasItem::setTileSize(const QSize & size)
+{
+ Q_D(QQuickCanvasItem);
+ if (d->tileSize != size) {
+ d->hasTileSize = true;
+ d->tileSize = size;
+
+ emit tileSizeChanged();
+ polish();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty rect QtQuick2::Canvas::canvasWindow
+ Holds the current canvas visible window.
+
+ By default the canvasWindow size is the same as the Canvas item
+ size with the topleft point as (0, 0).
+
+ If the canvasSize is different to the Canvas item size, the Canvas
+ item can display different visible areas by changing the canvas windowSize
+ and/or position.
+
+ \sa QtQuick2::Canvas::canvasSize QtQuick2::Canvas::tileSize
+*/
+QRectF QQuickCanvasItem::canvasWindow() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->canvasWindow;
+}
+
+void QQuickCanvasItem::setCanvasWindow(const QRectF& rect)
+{
+ Q_D(QQuickCanvasItem);
+ if (d->canvasWindow != rect) {
+ d->canvasWindow = rect;
+
+ d->hasCanvasWindow = true;
+ emit canvasWindowChanged();
+ polish();
+ update();
+ }
+}
+
+
+QQuickContext2D* QQuickCanvasItem::context() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->context;
+}
+/*!
+ \qmlproperty bool QtQuick2::Canvas::renderInThread
+ Holds the current canvas rendering mode.
+
+ Set renderInThread to true to render complex and long
+ running painting in a dedicated background
+ thread, avoiding blocking the main UI.
+
+ \note: Not all renderTargets support background rendering. If background rendering
+ is not supported by the current renderTarget, the renderInThread
+ property is ignored.
+
+ The default value is false.
+ \sa QtQuick2::Canvas::renderTarget
+*/
+bool QQuickCanvasItem::renderInThread() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->renderInThread;
+}
+/*!
+ \qmlproperty bool QtQuick2::Canvas::renderTarget
+ Holds the current canvas render target.
+
+ \list
+ \o Canvas.Image - render to an in memory image buffer, the render
+ target supports background rendering.
+ \o Canvas.FramebufferObject - render to an OpenGL frame buffer,
+ this render target will ignore the
+ renderInThread property. The actual
+ rendering happens in the main QML rendering
+ process, which may be in a seperate render thread
+ or in the main GUI thread depending upon the platform.
+ \endlist
+
+ The default render target is \c Canvas.Image.
+ \sa QtQuick2::Canvas::renderInThread
+*/
+QQuickCanvasItem::RenderTarget QQuickCanvasItem::renderTarget() const
+{
+ Q_D(const QQuickCanvasItem);
+ return d->renderTarget;
+}
+
+void QQuickCanvasItem::setRenderTarget(RenderTarget target)
+{
+ Q_D(QQuickCanvasItem);
+ if (d->renderTarget != target) {
+ d->renderTarget = target;
+
+ if (d->componentCompleted)
+ createTexture();
+ emit renderTargetChanged();
+ }
+}
+
+void QQuickCanvasItem::_doPainting(const QRectF& region)
+{
+ Q_D(QQuickCanvasItem);
+ emit paint(QDeclarativeV8Handle::fromHandle(d->context->v8value())
+ , QQuickContext2DTexture::tiledRect(region, d->tileSize));
+ if (d->texture)
+ d->texture->wake();
+}
+
+void QQuickCanvasItem::setRenderInThread(bool renderInThread)
+{
+ Q_D(QQuickCanvasItem);
+ if (d->renderInThread != renderInThread) {
+ d->renderInThread = renderInThread;
+
+ if (d->componentCompleted)
+ createTexture();
+
+ if (d->renderInThread)
+ connect(this, SIGNAL(painted()), SLOT(update()));
+ else
+ disconnect(this, SIGNAL(painted()), this, SLOT(update()));
+ emit renderInThreadChanged();
+ polish();
+ update();
+ }
+}
+
+void QQuickCanvasItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QQuickCanvasItem);
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+
+ const qreal w = newGeometry.width();
+ const qreal h = newGeometry.height();
+
+ if (!d->hasCanvasSize) {
+ d->canvasSize = QSizeF(w, h);
+ emit canvasSizeChanged();
+ }
+
+ if (!d->hasTileSize) {
+ d->tileSize = d->canvasSize.toSize();
+ emit tileSizeChanged();
+ }
+
+ if (!d->hasCanvasWindow) {
+ d->canvasWindow = newGeometry;
+ emit canvasWindowChanged();
+ }
+
+ polish();
+ update();
+}
+
+void QQuickCanvasItem::componentComplete()
+{
+ Q_D(QQuickCanvasItem);
+ QQuickItem::componentComplete();
+
+ if (!d->context)
+ createContext();
+ createTexture();
+
+ d->baseUrl = qmlEngine(this)->contextForObject(this)->baseUrl();
+ requestPaint();
+ updatePolish(); //force update the canvas sizes to texture for the first time
+ update();
+ d->componentCompleted = true;
+}
+
+void QQuickCanvasItem::updatePolish()
+{
+ Q_D(QQuickCanvasItem);
+ QQuickItem::updatePolish();
+ if (d->texture) {
+ if (!d->renderInThread && d->dirtyRect.isValid())
+ _doPainting(d->dirtyRect);
+
+ d->texture->canvasChanged(d->canvasSize.toSize()
+ , d->tileSize
+ , d->canvasWindow.toAlignedRect()
+ , d->dirtyRect.toAlignedRect()
+ , d->smooth);
+ d->dirtyRect = QRectF();
+ }
+}
+
+QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ Q_D(QQuickCanvasItem);
+ QQuickContext2DNode *node = static_cast<QQuickContext2DNode *>(oldNode);
+ if (!node)
+ node = new QQuickContext2DNode(this);
+
+ node->setTexture(d->texture);
+ node->setSize(d->canvasWindow.size());
+ node->update();
+ return node;
+}
+
+void QQuickCanvasItem::createTexture()
+{
+ Q_D(QQuickCanvasItem);
+
+ if (!d->texture
+ || d->texture->threadRendering() != d->renderInThread
+ || d->texture->renderTarget() != d->renderTarget) {
+ if (d->texture) {
+ d->texture->deleteLater();
+ d->texture = 0;
+ }
+
+ if (d->renderTarget == QQuickCanvasItem::Image) {
+ d->texture = new QQuickContext2DImageTexture(d->renderInThread);
+ } else if (d->renderTarget == QQuickCanvasItem::FramebufferObject) {
+ d->texture = new QQuickContext2DFBOTexture();
+ }
+
+ if (d->renderInThread && !d->texture->supportThreadRendering()) {
+ qWarning("Canvas: render target does not support thread rendering, force to non-thread rendering mode.");
+ d->renderInThread = false;
+ emit renderInThreadChanged();
+ }
+
+ if (d->renderInThread)
+ connect(d->texture, SIGNAL(textureChanged()), this, SLOT(update()));
+
+ d->texture->setItem(this);
+ }
+}
+
+void QQuickCanvasItem::createContext()
+{
+ Q_D(QQuickCanvasItem);
+
+ delete d->context;
+
+ d->context = new QQuickContext2D(this);
+
+ QV8Engine *e = QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this));
+ d->context->setV8Engine(e);
+}
+
+/*!
+ \qmlmethod object QtQuick2::Canvas::getContext(string contextId)
+
+ Currently, the canvas item only supports the 2D context. If the \a contextId
+ parameter isn't provided or is "2d", then the QtQuick2::Context2D object is
+ returned, otherwise returns an invalid value.
+ */
+QDeclarativeV8Handle QQuickCanvasItem::getContext(const QString &contextId)
+{
+ Q_D(QQuickCanvasItem);
+
+ if (contextId.toLower() != QLatin1String("2d"))
+ return QDeclarativeV8Handle::fromHandle(v8::Undefined());
+
+ if (!d->context)
+ createContext();
+ return QDeclarativeV8Handle::fromHandle(d->context->v8value());
+}
+
+/*!
+ \qmlmethod void QtQuick2::Canvas::markDirty(rect region)
+
+ Mark the given \a region as dirty, so that when this region is visible
+ the canvas renderer will redraw it. This will trigger the "onPaint" signal
+ handler function.
+
+ \sa QtQuick2::Canvas::paint QtQuick2::Canvas::requestPaint
+ */
+void QQuickCanvasItem::markDirty(const QRectF& region)
+{
+ Q_D(QQuickCanvasItem);
+ d->dirtyRect |= region;
+ if (d->componentCompleted)
+ polish();
+ update();
+}
+
+
+/*!
+ \qmlmethod bool QtQuick2::Canvas::save(string filename)
+
+ Save the current canvas content into an image file \a filename.
+ The saved image format is automatically decided by the \a filename's
+ suffix.
+
+ Note: calling this method will force painting the whole canvas, not just the
+ current canvas visible window.
+
+ \sa canvasWindow canvasSize toDataURL
+ */
+bool QQuickCanvasItem::save(const QString &filename) const
+{
+ Q_D(const QQuickCanvasItem);
+ QUrl url = d->baseUrl.resolved(QUrl::fromLocalFile(filename));
+ return toImage().save(url.toLocalFile());
+}
+
+QImage QQuickCanvasItem::loadedImage(const QUrl& url)
+{
+ Q_D(QQuickCanvasItem);
+ QUrl fullPathUrl = d->baseUrl.resolved(url);
+ if (!d->images.contains(fullPathUrl)) {
+ loadImage(url);
+ }
+ QDeclarativePixmap* pix = d->images.value(fullPathUrl);
+ if (pix->isLoading() || pix->isError()) {
+ return QImage();
+ }
+ return pix->image();
+}
+
+/*!
+ \qmlmethod void QtQuick2::Canvas::loadImage(url image)
+ Loads the given \c image asynchronously.
+
+ When the image is ready, onImageLoaded will be emitted.
+ The loaded image can be unloaded by the \a QtQuick2::Canvas::unloadImage method.
+
+ Note: Only loaded images can be painted on the Canvas item.
+ \sa QtQuick2::Canvas::unloadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded
+ \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage
+ */
+void QQuickCanvasItem::loadImage(const QUrl& url)
+{
+ Q_D(QQuickCanvasItem);
+ QUrl fullPathUrl = d->baseUrl.resolved(url);
+ if (!d->images.contains(fullPathUrl)) {
+ QDeclarativePixmap* pix = new QDeclarativePixmap();
+ d->images.insert(fullPathUrl, pix);
+
+ pix->load(qmlEngine(this)
+ , fullPathUrl
+ , QDeclarativePixmap::Cache | QDeclarativePixmap::Asynchronous);
+ pix->connectFinished(this, SIGNAL(imageLoaded()));
+ }
+}
+/*!
+ \qmlmethod void QtQuick2::Canvas::unloadImage(url image)
+ Unloads the \c image.
+
+ Once an image is unloaded it cannot be painted by the canvas context
+ unless it is loaded again.
+
+ \sa QtQuick2::Canvas::loadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded
+ \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage
+ */
+void QQuickCanvasItem::unloadImage(const QUrl& url)
+{
+ Q_D(QQuickCanvasItem);
+ QUrl removeThis = d->baseUrl.resolved(url);
+ if (d->images.contains(removeThis)) {
+ delete d->images.value(removeThis);
+ d->images.remove(removeThis);
+ }
+}
+
+/*!
+ \qmlmethod void QtQuick2::Canvas::isImageError(url image)
+ Returns true if the \a image failed to load.
+
+ \sa QtQuick2::Canvas::loadImage
+ */
+bool QQuickCanvasItem::isImageError(const QUrl& url) const
+{
+ Q_D(const QQuickCanvasItem);
+ QUrl fullPathUrl = d->baseUrl.resolved(url);
+ return d->images.contains(fullPathUrl)
+ && d->images.value(fullPathUrl)->isError();
+}
+
+/*!
+ \qmlmethod void QtQuick2::Canvas::isImageLoading(url image)
+ Returns true if the \a image is currently loading.
+
+ \sa QtQuick2::Canvas::loadImage
+ */
+bool QQuickCanvasItem::isImageLoading(const QUrl& url) const
+{
+ Q_D(const QQuickCanvasItem);
+ QUrl fullPathUrl = d->baseUrl.resolved(url);
+ return d->images.contains(fullPathUrl)
+ && d->images.value(fullPathUrl)->isLoading();
+}
+/*!
+ \qmlmethod void QtQuick2::Canvas::isImageLoaded(url image)
+ Returns true if the \a image is sucessfully loaded and ready to use.
+
+ \sa QtQuick2::Canvas::loadImage
+ */
+bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const
+{
+ Q_D(const QQuickCanvasItem);
+ QUrl fullPathUrl = d->baseUrl.resolved(url);
+ return d->images.contains(fullPathUrl)
+ && d->images.value(fullPathUrl)->isReady();
+}
+
+QImage QQuickCanvasItem::toImage(const QRectF& region) const
+{
+ Q_D(const QQuickCanvasItem);
+ if (d->texture) {
+ if (region.isEmpty())
+ return d->texture->toImage(canvasWindow());
+ else
+ return d->texture->toImage(region);
+ }
+ return QImage();
+}
+
+/*!
+ \qmlmethod string QtQuick2::Canvas::toDataURL(string mimeType)
+
+ Returns a data URL for the image in the canvas.
+
+ The default \a mimeType is "image/png".
+
+ \sa QtQuick2::Canvas::save
+ */
+QString QQuickCanvasItem::toDataURL(const QString& mimeType) const
+{
+ QImage image = toImage();
+
+ if (!image.isNull()) {
+ QByteArray ba;
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ QString mime = mimeType.toLower();
+ QString type;
+ if (mime == QLatin1Literal("image/png")) {
+ type = QLatin1Literal("PNG");
+ } else if (mime == QLatin1Literal("image/bmp"))
+ type = QLatin1Literal("BMP");
+ else if (mime == QLatin1Literal("image/jpeg"))
+ type = QLatin1Literal("JPEG");
+ else if (mime == QLatin1Literal("image/x-portable-pixmap"))
+ type = QLatin1Literal("PPM");
+ else if (mime == QLatin1Literal("image/tiff"))
+ type = QLatin1Literal("TIFF");
+ else if (mime == QLatin1Literal("image/xpm"))
+ type = QLatin1Literal("XPM");
+ else
+ return QLatin1Literal("data:,");
+
+ image.save(&buffer, type.toAscii());
+ buffer.close();
+ QString dataUrl = QLatin1Literal("data:%1;base64,%2");
+ return dataUrl.arg(mime).arg(QLatin1String(ba.toBase64().constData()));
+ }
+ return QLatin1Literal("data:,");
+}
+
+/*!
+ \qmlsignal QtQuick2::Canvas::onPaint(QtQuick2::Context2D context, rect region)
+
+ This handler is called to render the \a region.
+
+ This signal can be triggered by QtQuick2::Canvas::markdirty, QtQuick2::Canvas::requestPaint
+ or by changing the current canvas window.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Canvas::onPainted()
+
+ This handler is called after all context painting commands are executed and
+ the Canvas has been rendered.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
new file mode 100644
index 0000000000..70ca475c96
--- /dev/null
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCANVASITEM_P_H
+#define QQUICKCANVASITEM_P_H
+
+#include <QtQuick/qquickitem.h>
+#include <private/qv8engine_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickContext2D;
+class QQuickCanvasItemPrivate;
+class Q_QUICK_EXPORT QQuickCanvasItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_ENUMS(RenderTarget)
+ Q_ENUMS(ImageFilterMode)
+
+ Q_PROPERTY(QSizeF canvasSize READ canvasSize WRITE setCanvasSize NOTIFY canvasSizeChanged)
+ Q_PROPERTY(QSize tileSize READ tileSize WRITE setTileSize NOTIFY tileSizeChanged)
+ Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
+ Q_PROPERTY(bool renderInThread READ renderInThread WRITE setRenderInThread NOTIFY renderInThreadChanged)
+ Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
+public:
+ enum RenderTarget {
+ Image,
+ FramebufferObject
+ };
+
+ enum ImageFilterMode {
+ Threshold,
+ Mono,
+ GrayScale,
+ Brightness,
+ Invert,
+ Blur,
+ Opaque,
+ Convolute
+ };
+
+ QQuickCanvasItem(QQuickItem *parent = 0);
+ ~QQuickCanvasItem();
+
+ QSizeF canvasSize() const;
+ void setCanvasSize(const QSizeF &);
+
+ QSize tileSize() const;
+ void setTileSize(const QSize &);
+
+ QRectF canvasWindow() const;
+ void setCanvasWindow(const QRectF& rect);
+
+ bool renderInThread() const;
+ void setRenderInThread(bool renderInThread);
+
+ RenderTarget renderTarget() const;
+ void setRenderTarget(RenderTarget target);
+
+ QQuickContext2D* context() const;
+ QImage toImage(const QRectF& region = QRectF()) const;
+
+ QImage loadedImage(const QUrl& url);
+
+Q_SIGNALS:
+ void paint(QDeclarativeV8Handle context, const QRect &region);
+ void painted();
+ void canvasSizeChanged();
+ void tileSizeChanged();
+ void renderInThreadChanged();
+ void textureChanged();
+ void canvasWindowChanged();
+ void renderTargetChanged();
+ void imageLoaded();
+public Q_SLOTS:
+ QString toDataURL(const QString& type = QLatin1String("image/png")) const;
+ QDeclarativeV8Handle getContext(const QString & = QLatin1String("2d"));
+ void markDirty(const QRectF& region);
+ void requestPaint() {markDirty(canvasWindow());}
+ // Save current canvas to disk
+ bool save(const QString& filename) const;
+ void loadImage(const QUrl& url);
+ void unloadImage(const QUrl& url);
+ bool isImageLoaded(const QUrl& url) const;
+ bool isImageLoading(const QUrl& url) const;
+ bool isImageError(const QUrl& url) const;
+private Q_SLOTS:
+ void _doPainting(const QRectF& region);
+protected:
+ virtual void componentComplete();
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void updatePolish();
+private:
+ void createContext();
+ void createTexture();
+ Q_DECLARE_PRIVATE(QQuickCanvasItem)
+ friend class QQuickContext2D;
+ friend class QQuickContext2DTexture;
+};
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickCanvasItem)
+
+QT_END_HEADER
+
+#endif //QQUICKCANVASITEM_P_H
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
new file mode 100644
index 0000000000..d5d57132bf
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -0,0 +1,3540 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickcontext2d_p.h"
+#include "qquickcontext2dcommandbuffer_p.h"
+#include "qquickcanvasitem_p.h"
+#include <private/qquickitem_p.h>
+#include <QtQuick/private/qquickshadereffectsource_p.h>
+#include <QtGui/qopenglframebufferobject.h>
+
+#include <QtCore/qdebug.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qdeclarativesvgparser_p.h>
+#include <private/qdeclarativepath_p.h>
+
+#include <private/qquickimage_p_p.h>
+
+#include <QtGui/qguiapplication.h>
+#include <qdeclarativeinfo.h>
+#include <QtCore/qmath.h>
+#include <private/qv8engine_p.h>
+
+#include <qdeclarativeengine.h>
+#include <private/qv8domerrors_p.h>
+#include <QtCore/qnumeric.h>
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass Context2D QQuickContext2D
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.0
+ \brief The Context2D API allows you to draw 2d graphic shapes on the \c Canvas item.
+
+ The Context2D object can be created by \c Canvas item's \c getContext() method:
+ \code
+ Canvas {
+ id:canvas
+ onPaint:{
+ var ctx = canvas.getContext('2d');
+ //...
+ }
+ }
+ \endcode
+ The Context2D API implements the same \l {http://www.w3.org/TR/2dcontext}{W3C Canvas 2D Context API standard}
+ with some enhanced features.
+
+ The Context2D API provides the rendering \bold{context} which defines the methods and attributes needed to draw
+ on the \c Canvas item. The following assigns the canvas rendering context to a \c{context}
+ variable:
+ \code
+ var context = mycanvas.getContext("2d")
+ \endcode
+
+ The Context2D API renders the canvas as a coordinate system whose origin (0,0) is
+ at the top left corner, as shown in the figure below. Coordinates increase along
+ the \c{x} axis from left to right and along the \c{y} axis from top to bottom of
+ the canvas.
+ \image qml-item-canvas-context.gif
+*/
+
+Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
+
+static const double Q_PI = 3.14159265358979323846; // pi
+
+#define DEGREES(t) ((t) * 180.0 / Q_PI)
+
+#define CHECK_CONTEXT(r) if (!r || !r->context || !r->context->buffer()) \
+ V8THROW_ERROR("Not a Context2D object");
+
+#define CHECK_CONTEXT_SETTER(r) if (!r || !r->context || !r->context->buffer()) \
+ V8THROW_ERROR_SETTER("Not a Context2D object");
+#define qClamp(val, min, max) qMin(qMax(val, min), max)
+#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
+QColor qt_color_from_string(v8::Local<v8::Value> name)
+{
+ v8::String::AsciiValue str(name);
+
+ char *p = *str;
+ int len = str.length();
+ //rgb/hsl color string has at least 7 characters
+ if (!p || len > 255 || len <= 7)
+ return QColor(p);
+ else {
+ bool isRgb(false), isHsl(false), hasAlpha(false);
+ Q_UNUSED(isHsl)
+
+ while (isspace(*p)) p++;
+ if (strncmp(p, "rgb", 3) == 0)
+ isRgb = true;
+ else if (strncmp(p, "hsl", 3) == 0)
+ isHsl = true;
+ else
+ return QColor(p);
+
+ p+=3; //skip "rgb" or "hsl"
+ hasAlpha = (*p == 'a') ? true : false;
+
+ ++p; //skip "("
+
+ if (hasAlpha) ++p; //skip "a"
+
+ int rh, gs, bl, alpha = 255;
+
+ //red
+ while (isspace(*p)) p++;
+ rh = strtol(p, &p, 10);
+ if (*p == '%') {
+ rh = qRound(rh/100.0 * 255);
+ ++p;
+ }
+ if (*p++ != ',') return QColor();
+
+ //green
+ while (isspace(*p)) p++;
+ gs = strtol(p, &p, 10);
+ if (*p == '%') {
+ gs = qRound(gs/100.0 * 255);
+ ++p;
+ }
+ if (*p++ != ',') return QColor();
+
+ //blue
+ while (isspace(*p)) p++;
+ bl = strtol(p, &p, 10);
+ if (*p == '%') {
+ bl = qRound(bl/100.0 * 255);
+ ++p;
+ }
+
+ if (hasAlpha) {
+ if (*p++!= ',') return QColor();
+ while (isspace(*p)) p++;
+ bool ok = false;
+ alpha = qRound(qstrtod(p, const_cast<const char **>(&p), &ok) * 255);
+ }
+
+ if (*p != ')') return QColor();
+ if (isRgb)
+ return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
+ else
+ return QColor::fromHsl(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
+ }
+ return QColor();
+}
+
+QFont qt_font_from_string(const QString& fontString) {
+ QFont font;
+ // ### this is simplified and incomplete
+ // ### TODO:get code from Qt webkit
+ QStringList tokens = fontString.split(QLatin1String(" "));
+ foreach (const QString &token, tokens) {
+ if (token == QLatin1String("italic"))
+ font.setItalic(true);
+ else if (token == QLatin1String("bold"))
+ font.setBold(true);
+ else if (token.endsWith(QLatin1String("px"))) {
+ QString number = token;
+ number.remove(QLatin1String("px"));
+ //font.setPointSizeF(number.trimmed().toFloat());
+ font.setPixelSize(number.trimmed().toInt());
+ } else
+ font.setFamily(token);
+ }
+
+ return font;
+}
+
+
+
+class QQuickContext2DEngineData : public QV8Engine::Deletable
+{
+public:
+ QQuickContext2DEngineData(QV8Engine *engine);
+ ~QQuickContext2DEngineData();
+
+ v8::Persistent<v8::Function> constructorContext;
+ v8::Persistent<v8::Function> constructorGradient;
+ v8::Persistent<v8::Function> constructorPattern;
+ v8::Persistent<v8::Function> constructorPixelArray;
+ v8::Persistent<v8::Function> constructorImageData;
+};
+
+V8_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
+
+class QV8Context2DResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(Context2DType)
+public:
+ QV8Context2DResource(QV8Engine *e) : QV8ObjectResource(e) {}
+ QQuickContext2D* context;
+};
+
+class QV8Context2DStyleResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(Context2DStyleType)
+public:
+ QV8Context2DStyleResource(QV8Engine *e)
+ : QV8ObjectResource(e)
+ , patternRepeatX(false)
+ , patternRepeatY(false)
+ {}
+ QBrush brush;
+ bool patternRepeatX:1;
+ bool patternRepeatY:1;
+};
+
+class QV8Context2DPixelArrayResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(Context2DPixelArrayType)
+public:
+ QV8Context2DPixelArrayResource(QV8Engine *e) : QV8ObjectResource(e) {}
+
+ QImage image;
+};
+
+QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
+{
+ int sides = radius ? radius : qRound(qSqrt(weights.size()));
+ int half = qFloor(sides/2);
+
+ QImage dst = QImage(src.size(), src.format());
+ int w = src.width();
+ int h = src.height();
+ for (int y = 0; y < dst.height(); ++y) {
+ QRgb *dr = (QRgb*)dst.scanLine(y);
+ for (int x = 0; x < dst.width(); ++x) {
+ unsigned char* dRgb = ((unsigned char*)&dr[x]);
+ unsigned char red=0, green=0, blue=0, alpha=0;
+ int sy = y;
+ int sx = x;
+
+ for (int cy=0; cy<sides; cy++) {
+ for (int cx=0; cx<sides; cx++) {
+ int scy = sy + cy - half;
+ int scx = sx + cx - half;
+ if (scy >= 0 && scy < w && scx >= 0 && scx < h) {
+ const QRgb *sr = (const QRgb*)(src.constScanLine(scy));
+ const unsigned char* sRgb = ((const unsigned char*)&sr[scx]);
+ qreal wt = radius ? weights[0] : weights[cy*sides+cx];
+ red += sRgb[0] * wt;
+ green += sRgb[1] * wt;
+ blue += sRgb[2] * wt;
+ alpha += sRgb[3] * wt;
+ }
+ }
+ }
+ dRgb[0] = red;
+ dRgb[1] = green;
+ dRgb[2] = blue;
+ dRgb[3] = alpha;
+ }
+ }
+ return dst;
+}
+
+void qt_image_boxblur(QImage& image, int radius, bool quality)
+{
+ int passes = quality? 3: 1;
+ for (int i=0; i < passes; i++) {
+ image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0/(radius * radius * 1.0), radius);
+ }
+}
+
+static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
+{
+ if (compositeOperator == QLatin1String("source-over")) {
+ return QPainter::CompositionMode_SourceOver;
+ } else if (compositeOperator == QLatin1String("source-out")) {
+ return QPainter::CompositionMode_SourceOut;
+ } else if (compositeOperator == QLatin1String("source-in")) {
+ return QPainter::CompositionMode_SourceIn;
+ } else if (compositeOperator == QLatin1String("source-atop")) {
+ return QPainter::CompositionMode_SourceAtop;
+ } else if (compositeOperator == QLatin1String("destination-atop")) {
+ return QPainter::CompositionMode_DestinationAtop;
+ } else if (compositeOperator == QLatin1String("destination-in")) {
+ return QPainter::CompositionMode_DestinationIn;
+ } else if (compositeOperator == QLatin1String("destination-out")) {
+ return QPainter::CompositionMode_DestinationOut;
+ } else if (compositeOperator == QLatin1String("destination-over")) {
+ return QPainter::CompositionMode_DestinationOver;
+ } else if (compositeOperator == QLatin1String("lighter")) {
+ return QPainter::CompositionMode_Lighten;
+ } else if (compositeOperator == QLatin1String("copy")) {
+ return QPainter::CompositionMode_Source;
+ } else if (compositeOperator == QLatin1String("xor")) {
+ return QPainter::CompositionMode_Xor;
+ } else if (compositeOperator == QLatin1String("qt-clear")) {
+ return QPainter::CompositionMode_Clear;
+ } else if (compositeOperator == QLatin1String("qt-destination")) {
+ return QPainter::CompositionMode_Destination;
+ } else if (compositeOperator == QLatin1String("qt-multiply")) {
+ return QPainter::CompositionMode_Multiply;
+ } else if (compositeOperator == QLatin1String("qt-screen")) {
+ return QPainter::CompositionMode_Screen;
+ } else if (compositeOperator == QLatin1String("qt-overlay")) {
+ return QPainter::CompositionMode_Overlay;
+ } else if (compositeOperator == QLatin1String("qt-darken")) {
+ return QPainter::CompositionMode_Darken;
+ } else if (compositeOperator == QLatin1String("qt-lighten")) {
+ return QPainter::CompositionMode_Lighten;
+ } else if (compositeOperator == QLatin1String("qt-color-dodge")) {
+ return QPainter::CompositionMode_ColorDodge;
+ } else if (compositeOperator == QLatin1String("qt-color-burn")) {
+ return QPainter::CompositionMode_ColorBurn;
+ } else if (compositeOperator == QLatin1String("qt-hard-light")) {
+ return QPainter::CompositionMode_HardLight;
+ } else if (compositeOperator == QLatin1String("qt-soft-light")) {
+ return QPainter::CompositionMode_SoftLight;
+ } else if (compositeOperator == QLatin1String("qt-difference")) {
+ return QPainter::CompositionMode_Difference;
+ } else if (compositeOperator == QLatin1String("qt-exclusion")) {
+ return QPainter::CompositionMode_Exclusion;
+ }
+ return QPainter::CompositionMode_SourceOver;
+}
+
+static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
+{
+ switch (op) {
+ case QPainter::CompositionMode_SourceOver:
+ return QLatin1String("source-over");
+ case QPainter::CompositionMode_DestinationOver:
+ return QLatin1String("destination-over");
+ case QPainter::CompositionMode_Clear:
+ return QLatin1String("qt-clear");
+ case QPainter::CompositionMode_Source:
+ return QLatin1String("copy");
+ case QPainter::CompositionMode_Destination:
+ return QLatin1String("qt-destination");
+ case QPainter::CompositionMode_SourceIn:
+ return QLatin1String("source-in");
+ case QPainter::CompositionMode_DestinationIn:
+ return QLatin1String("destination-in");
+ case QPainter::CompositionMode_SourceOut:
+ return QLatin1String("source-out");
+ case QPainter::CompositionMode_DestinationOut:
+ return QLatin1String("destination-out");
+ case QPainter::CompositionMode_SourceAtop:
+ return QLatin1String("source-atop");
+ case QPainter::CompositionMode_DestinationAtop:
+ return QLatin1String("destination-atop");
+ case QPainter::CompositionMode_Xor:
+ return QLatin1String("xor");
+ case QPainter::CompositionMode_Plus:
+ return QLatin1String("plus");
+ case QPainter::CompositionMode_Multiply:
+ return QLatin1String("qt-multiply");
+ case QPainter::CompositionMode_Screen:
+ return QLatin1String("qt-screen");
+ case QPainter::CompositionMode_Overlay:
+ return QLatin1String("qt-overlay");
+ case QPainter::CompositionMode_Darken:
+ return QLatin1String("qt-darken");
+ case QPainter::CompositionMode_Lighten:
+ return QLatin1String("lighter");
+ case QPainter::CompositionMode_ColorDodge:
+ return QLatin1String("qt-color-dodge");
+ case QPainter::CompositionMode_ColorBurn:
+ return QLatin1String("qt-color-burn");
+ case QPainter::CompositionMode_HardLight:
+ return QLatin1String("qt-hard-light");
+ case QPainter::CompositionMode_SoftLight:
+ return QLatin1String("qt-soft-light");
+ case QPainter::CompositionMode_Difference:
+ return QLatin1String("qt-difference");
+ case QPainter::CompositionMode_Exclusion:
+ return QLatin1String("qt-exclusion");
+ default:
+ break;
+ }
+ return QString();
+}
+
+
+static v8::Local<v8::Object> qt_create_image_data(qreal w, qreal h, QV8Engine* engine, const QImage& image)
+{
+ QQuickContext2DEngineData *ed = engineData(engine);
+ v8::Local<v8::Object> imageData = ed->constructorImageData->NewInstance();
+ QV8Context2DPixelArrayResource *r = new QV8Context2DPixelArrayResource(engine);
+ if (image.isNull()) {
+ r->image = QImage(w, h, QImage::Format_ARGB32);
+ r->image.fill(0x00000000);
+ } else {
+ Q_ASSERT(image.width() == w && image.height() == h);
+ r->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
+ }
+ v8::Local<v8::Object> pixelData = ed->constructorPixelArray->NewInstance();
+ pixelData->SetExternalResource(r);
+
+ imageData->SetInternalField(0, pixelData);
+ return imageData;
+}
+
+//static script functions
+
+/*!
+ \qmlproperty QtQuick2::Canvas QtQuick2::Context2D::canvas
+ Holds the canvas item that the context paints on.
+
+ This property is read only.
+*/
+static v8::Handle<v8::Value> ctx2d_canvas(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ return engine->newQObject(r->context->canvas());
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::restore()
+ Pops the top state on the stack, restoring the context to that state.
+
+ \sa QtQuick2::Context2D::save()
+*/
+static v8::Handle<v8::Value> ctx2d_restore(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ r->context->popState();
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::reset()
+ Resets the context state and properties to the default values.
+*/
+static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ r->context->reset();
+ r->context->m_path = QPainterPath();
+ r->context->m_path.setFillRule(Qt::WindingFill);
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::save()
+ Pushes the current state onto the state stack.
+
+ Before changing any state attributes, you should save the current state
+ for future reference. The context maintains a stack of drawing states.
+ Each state consists of the current transformation matrix, clipping region,
+ and values of the following attributes:
+ \list
+ \o\a QtQuick2::Context2D::strokeStyle
+ \o\a QtQuick2::Context2D::fillStyle
+ \o\a QtQuick2::Context2D::fillRule
+ \o\a QtQuick2::Context2D::globalAlpha
+ \o\a QtQuick2::Context2D::lineWidth
+ \o\a QtQuick2::Context2D::lineCap
+ \o\a QtQuick2::Context2D::lineJoin
+ \o\a QtQuick2::Context2D::miterLimit
+ \o\a QtQuick2::Context2D::shadowOffsetX
+ \o\a QtQuick2::Context2D::shadowOffsetY
+ \o\a QtQuick2::Context2D::shadowBlur
+ \o\a QtQuick2::Context2D::shadowColor
+ \o\a QtQuick2::Context2D::globalCompositeOperation
+ \o\a QtQuick2::Context2D::font
+ \o\a QtQuick2::Context2D::textAlign
+ \o\a QtQuick2::Context2D::textBaseline
+ \endlist
+
+ The current path is NOT part of the drawing state. The path can be reset by
+ invoking the \a QtQuick2::Context2D::beginPath() method.
+*/
+static v8::Handle<v8::Value> ctx2d_save(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ r->context->pushState();
+
+ return args.This();
+}
+
+// transformations
+/*!
+ \qmlmethod object QtQuick2::Context2D::rotate(real angle)
+ Rotate the canvas around the current origin by \c angle in radians and clockwise direction.
+ \code
+ ctx.rotate(Math.PI/2);
+ \endcode
+ \image qml-item-canvas-rotate.png
+
+ The rotation transformation matrix is as follows:
+
+ \image qml-item-canvas-math-rotate.png
+
+ where the \c angle of rotation is in radians.
+
+*/
+static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 1) {
+ qreal angle = args[0]->NumberValue();
+ if (!qIsFinite(angle))
+ return args.This();
+
+ r->context->state.matrix.rotate(DEGREES(angle));
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::scale(real x, real y)
+ Increases or decreases the size of each unit in the canvas grid by multiplying the scale factors
+ to the current tranform matrix.
+ Where \c x is the scale factor in the horizontal direction and \c y is the scale factor in the
+ vertical direction.
+ The following code doubles the horizontal size of an object drawn on the canvas and half its
+ vertical size:
+ \code
+ ctx.scale(2.0, 0.5);
+ \endcode
+ \image qml-item-canvas-scale.png
+
+*/
+static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 2) {
+ qreal x, y;
+ x = args[0]->NumberValue();
+ y = args[1]->NumberValue();
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+
+ r->context->state.matrix.scale(x, y);
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::setTransform(real a, real b, real c, real d, real e, real f)
+ Changes the transformation matrix to the matrix given by the arguments as described below.
+
+ Modifying the transformation matrix directly enables you to perform scaling,
+ rotating, and translating transformations in a single step.
+
+ Each point on the canvas is multiplied by the matrix before anything is
+ drawn. The \l{HTML5 Canvas API} defines the transformation matrix as:
+
+ \image qml-item-canvas-math.png
+ where:
+ \list
+ \o \c{a} is the scale factor in the horizontal (x) direction
+ \image qml-item-canvas-scalex.png
+ \o \c{c} is the skew factor in the x direction
+ \image qml-item-canvas-canvas-skewx.png
+ \o \c{e} is the translation in the x direction
+ \image qml-item-canvas-canvas-translate.png
+ \o \c{b} is the skew factor in the y (vertical) direction
+ \image qml-item-canvas-canvas-skewy.png
+ \o \c{d} is the scale factor in the y direction
+ \image qml-item-canvas-canvas-scaley.png
+ \o \c{f} is the translation in the y direction
+ \image qml-item-canvas-canvas-translatey.png
+ \o the last row remains constant
+ \endlist
+ The scale factors and skew factors are multiples; \c{e} and \c{f} are
+ coordinate space units, just like the units in the \a QtQuick2::Context2D::translate(x,y)
+ method.
+
+ \sa QtQuick2::Context2D::transform()
+*/
+static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 6) {
+ qreal a = args[0]->NumberValue();
+ qreal b = args[1]->NumberValue();
+ qreal c = args[2]->NumberValue();
+ qreal d = args[3]->NumberValue();
+ qreal e = args[4]->NumberValue();
+ qreal f = args[5]->NumberValue();
+
+ if (!qIsFinite(a)
+ || !qIsFinite(b)
+ || !qIsFinite(c)
+ || !qIsFinite(d)
+ || !qIsFinite(e)
+ || !qIsFinite(f))
+ return args.This();
+
+ r->context->state.matrix = QTransform(a, b, c, d, e, f);
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::transform(real a, real b, real c, real d, real e, real f)
+ This method is very similar to \a QtQuick2::Context2D::setTransform(), but instead of replacing the old
+ tranform matrix, this method applies the given tranform matrix to the current matrix by mulitplying to it.
+
+ The \a setTransform(a, b, c, d, e, f) method actually resets the current transform to the identity matrix,
+ and then invokes the transform(a, b, c, d, e, f) method with the same arguments.
+
+ \sa QtQuick2::Context2D::setTransform()
+*/
+static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 6) {
+ qreal a = args[0]->NumberValue();
+ qreal b = args[1]->NumberValue();
+ qreal c = args[2]->NumberValue();
+ qreal d = args[3]->NumberValue();
+ qreal e = args[4]->NumberValue();
+ qreal f = args[5]->NumberValue();
+
+ if (!qIsFinite(a)
+ || !qIsFinite(b)
+ || !qIsFinite(c)
+ || !qIsFinite(d)
+ || !qIsFinite(e)
+ || !qIsFinite(f))
+ return args.This();
+
+ r->context->state.matrix *= QTransform(a, b, c, d, e, f);
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::translate(real x, real y)
+ Translates the origin of the canvas to point (\c x, \c y).
+
+ \c x is the horizontal distance that the origin is translated, in coordinate space units,
+ \c y is the vertical distance that the origin is translated, in coordinate space units.
+ Translating the origin enables you to draw patterns of different objects on the canvas
+ without having to measure the coordinates manually for each shape.
+*/
+static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 2) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+
+ r->context->state.matrix.translate(x, y);
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+
+ return args.This();
+}
+
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::resetTransform()
+ Reset the transformation matrix to default value.
+
+ \sa QtQuick2::Context2D::transform(), QtQuick2::Context2D::setTransform(), QtQuick2::Context2D::reset()
+*/
+static v8::Handle<v8::Value> ctx2d_resetTransform(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ r->context->state.matrix = QTransform();
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+
+ return args.This();
+}
+
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::shear(real sh, real sv )
+ Shear the transformation matrix with \a sh in horizontal direction and \a sv in vertical direction.
+*/
+static v8::Handle<v8::Value> ctx2d_shear(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 2) {
+ qreal sh = args[0]->NumberValue();
+ qreal sv = args[1]->NumberValue();
+
+ if (!qIsFinite(sh) || !qIsFinite(sv))
+ return args.This();
+
+ r->context->state.matrix.shear(sh, sv);
+ r->context->buffer()->updateMatrix(r->context->state.matrix);
+ }
+ return args.This();
+}
+// compositing
+
+/*!
+ \qmlproperty real QtQuick2::Context2D::globalAlpha
+ Holds the the current alpha value applied to rendering operations.
+ The value must be in the range from 0.0 (fully transparent) to 1.0 (fully opque).
+ The default value is 1.0.
+*/
+static v8::Handle<v8::Value> ctx2d_globalAlpha(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+ return v8::Number::New(r->context->state.globalAlpha);
+}
+
+static void ctx2d_globalAlpha_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ qreal globalAlpha = value->NumberValue();
+
+ if (!qIsFinite(globalAlpha))
+ return;
+
+ if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->context->state.globalAlpha != globalAlpha) {
+ r->context->state.globalAlpha = globalAlpha;
+ r->context->buffer()->setGlobalAlpha(r->context->state.globalAlpha);
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick2::Context2D::globalCompositeOperation
+ Holds the the current the current composition operation, from the list below:
+ \list
+ \o source-atop - A atop B. Display the source image wherever both images are opaque.
+ Display the destination image wherever the destination image is opaque but the source image is transparent.
+ Display transparency elsewhere.
+ \o source-in - A in B. Display the source image wherever both the source image and destination image are opaque.
+ Display transparency elsewhere.
+ \o source-out - A out B. Display the source image wherever the source image is opaque and the destination image is transparent.
+ Display transparency elsewhere.
+ \o source-over - (default) A over B. Display the source image wherever the source image is opaque.
+ Display the destination image elsewhere.
+ \o destination-atop - B atop A. Same as source-atop but using the destination image instead of the source image and vice versa.
+ \o destination-in - B in A. Same as source-in but using the destination image instead of the source image and vice versa.
+ \o destination-out - B out A. Same as source-out but using the destination image instead of the source image and vice versa.
+ \o destination-over - B over A. Same as source-over but using the destination image instead of the source image and vice versa.
+ \o lighter - A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit.
+ \o copy - A (B is ignored). Display the source image instead of the destination image.
+ \o xor - A xor B. Exclusive OR of the source image and destination image.
+ \endlist
+
+ Additionally, this property also accepts the compositon modes listed in \a {QPainter::CompositionMode}. According to the W3C standard, these
+ extension composition modes are provided as "vendorName-operationName" syntax, for example: \c {QPainter::CompositionMode_Exclusion} is porvided as
+ "qt-exclusion".
+*/
+static v8::Handle<v8::Value> ctx2d_globalCompositeOperation(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ return engine->toString(qt_composite_mode_to_string(r->context->state.globalCompositeOperation));
+}
+
+static void ctx2d_globalCompositeOperation_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+
+ QString mode = engine->toString(value);
+ QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
+ if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over"))
+ return;
+
+ if (cm != r->context->state.globalCompositeOperation) {
+ r->context->state.globalCompositeOperation = cm;
+ r->context->buffer()->setGlobalCompositeOperation(cm);
+ }
+}
+
+// colors and styles
+/*!
+ \qmlproperty variant QtQuick2::Context2D::fillStyle
+ Holds the current style used for filling shapes.
+ The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object. Invalid values are ignored.
+ This property accepts several color syntaxes:
+ \list
+ \o 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)'
+ \o 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)'
+ \o 'hsl(hue, saturation, lightness)'
+ \o 'hsla(hue, saturation, lightness, alpha)'
+ \o '#RRGGBB' - for example: '#00FFCC'
+ \o Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0)
+ \endlist
+ If the \a fillStyle or \a strokeStyle is assigned many times in a loop, the last Qt.rgba() syntax should be chosen, as it has the
+ best performance, because it's already a valid QColor value, does not need to be parsed everytime.
+
+ The default value is '#000000'.
+ \sa QtQuick2::Context2D::createLinearGradient
+ \sa QtQuick2::Context2D::createRadialGradient
+ \sa QtQuick2::Context2D::createPattern
+ \sa QtQuick2::Context2D::strokeStyle
+ */
+static v8::Handle<v8::Value> ctx2d_fillStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ QColor color = r->context->state.fillStyle.color();
+ if (color.isValid()) {
+ if (color.alpha() == 255)
+ return engine->toString(color.name());
+ QString alphaString = QString::number(color.alphaF(), 'f');
+ while (alphaString.endsWith(QLatin1Char('0')))
+ alphaString.chop(1);
+ if (alphaString.endsWith(QLatin1Char('.')))
+ alphaString += QLatin1Char('0');
+ return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
+ }
+ return r->context->m_fillStyle;
+}
+
+static void ctx2d_fillStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ if (value->IsObject()) {
+ QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
+ if (color.isValid()) {
+ r->context->state.fillStyle = color;
+ r->context->buffer()->setFillStyle(color);
+ r->context->m_fillStyle = value;
+ } else {
+ QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
+ if (style && style->brush != r->context->state.fillStyle) {
+ r->context->state.fillStyle = style->brush;
+ r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
+ r->context->m_fillStyle = value;
+ r->context->state.fillPatternRepeatX = style->patternRepeatX;
+ r->context->state.fillPatternRepeatY = style->patternRepeatY;
+ }
+ }
+ } else if (value->IsString()) {
+ QColor color = qt_color_from_string(value);
+ if (color.isValid() && r->context->state.fillStyle != QBrush(color)) {
+ r->context->state.fillStyle = QBrush(color);
+ r->context->buffer()->setFillStyle(r->context->state.fillStyle);
+ r->context->m_fillStyle = value;
+ }
+ }
+}
+/*!
+ \qmlproperty enumeration QtQuick2::Context2D::fillRule
+ Holds the current fill rule used for filling shapes. The following fill rules supported:
+ \list
+ \o Qt.OddEvenFill
+ \o Qt.WindingFill
+ \endlist
+ Note: Unlike the \a QPainterPath, the Canvas API uses the winding fill as the default fill rule.
+ The fillRule property is part of the context rendering state.
+
+ \sa QtQuick2::Context2D::fillStyle
+ */
+static v8::Handle<v8::Value> ctx2d_fillRule(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ return engine->fromVariant(r->context->state.fillRule);
+}
+
+static void ctx2d_fillRule_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ if ((value->IsString() && engine->toString(value) == QStringLiteral("WindingFill"))
+ ||(value->IsNumber() && value->NumberValue() == Qt::WindingFill)) {
+ r->context->state.fillRule = Qt::WindingFill;
+ } else if ((value->IsString() && engine->toString(value) == QStringLiteral("OddEvenFill"))
+ ||(value->IsNumber() && value->NumberValue() == Qt::OddEvenFill)) {
+ r->context->state.fillRule = Qt::OddEvenFill;
+ } else {
+ //error
+ }
+ r->context->m_path.setFillRule(r->context->state.fillRule);
+}
+/*!
+ \qmlproperty variant QtQuick2::Context2D::strokeStyle
+ Holds the current color or style to use for the lines around shapes,
+ The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object.
+ Invalid values are ignored.
+
+ The default value is '#000000'.
+
+ \sa QtQuick2::Context2D::createLinearGradient
+ \sa QtQuick2::Context2D::createRadialGradient
+ \sa QtQuick2::Context2D::createPattern
+ \sa QtQuick2::Context2D::fillStyle
+ */
+v8::Handle<v8::Value> ctx2d_strokeStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ QColor color = r->context->state.strokeStyle.color();
+ if (color.isValid()) {
+ if (color.alpha() == 255)
+ return engine->toString(color.name());
+ QString alphaString = QString::number(color.alphaF(), 'f');
+ while (alphaString.endsWith(QLatin1Char('0')))
+ alphaString.chop(1);
+ if (alphaString.endsWith(QLatin1Char('.')))
+ alphaString += QLatin1Char('0');
+ return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
+ }
+ return r->context->m_strokeStyle;
+}
+
+static void ctx2d_strokeStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ if (value->IsObject()) {
+ QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
+ if (color.isValid()) {
+ r->context->state.fillStyle = color;
+ r->context->buffer()->setStrokeStyle(color);
+ r->context->m_strokeStyle = value;
+ } else {
+ QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
+ if (style && style->brush != r->context->state.strokeStyle) {
+ r->context->state.strokeStyle = style->brush;
+ r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
+ r->context->m_strokeStyle = value;
+ r->context->state.strokePatternRepeatX = style->patternRepeatX;
+ r->context->state.strokePatternRepeatY = style->patternRepeatY;
+
+ }
+ }
+ } else if (value->IsString()) {
+ QColor color = qt_color_from_string(value);
+ if (color.isValid() && r->context->state.strokeStyle != QBrush(color)) {
+ r->context->state.strokeStyle = QBrush(color);
+ r->context->buffer()->setStrokeStyle(r->context->state.strokeStyle);
+ r->context->m_strokeStyle = value;
+ }
+ }
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::createLinearGradient(real x0, real y0, real x1, real y1)
+ Returns a CanvasGradient object that represents a linear gradient that transitions the color along a line between
+ the start point (\a x0, \a y0) and the end point (\a x1, \a y1).
+
+ A gradient is a smooth transition between colors. There are two types of gradients: linear and radial.
+ Gradients must have two or more color stops, representing color shifts positioned from 0 to 1 between
+ to the gradient's starting and end points or circles.
+
+ \sa QtQuick2::Context2D::CanvasGradient::addColorStop
+ \sa QtQuick2::Context2D::createRadialGradient
+ \sa QtQuick2::Context2D::ctx2d_createConicalGradient
+ \sa QtQuick2::Context2D::createPattern
+ \sa QtQuick2::Context2D::fillStyle
+ \sa QtQuick2::Context2D::strokeStyle
+ */
+
+static v8::Handle<v8::Value> ctx2d_createLinearGradient(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 4) {
+ QQuickContext2DEngineData *ed = engineData(engine);
+ v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
+ QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
+ qreal x0 = args[0]->NumberValue();
+ qreal y0 = args[1]->NumberValue();
+ qreal x1 = args[2]->NumberValue();
+ qreal y1 = args[3]->NumberValue();
+
+ if (!qIsFinite(x0)
+ || !qIsFinite(y0)
+ || !qIsFinite(x1)
+ || !qIsFinite(y1))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
+
+ r->brush = QLinearGradient(x0, y0, x1, y1);
+ gradient->SetExternalResource(r);
+ return gradient;
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::createRadialGradient(real x0, real y0, real r0, real x1, real y1, real r1)
+ Returns a CanvasGradient object that represents a radial gradient that paints along the cone given by the start circle with
+ origin (x0, y0) and radius r0, and the end circle with origin (x1, y1) and radius r1.
+
+ \sa QtQuick2::Context2D::CanvasGradient::addColorStop
+ \sa QtQuick2::Context2D::createLinearGradient
+ \sa QtQuick2::Context2D::ctx2d_createConicalGradient
+ \sa QtQuick2::Context2D::createPattern
+ \sa QtQuick2::Context2D::fillStyle
+ \sa QtQuick2::Context2D::strokeStyle
+ */
+
+static v8::Handle<v8::Value> ctx2d_createRadialGradient(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 6) {
+ QQuickContext2DEngineData *ed = engineData(engine);
+ v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
+ QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
+
+ qreal x0 = args[0]->NumberValue();
+ qreal y0 = args[1]->NumberValue();
+ qreal r0 = args[2]->NumberValue();
+ qreal x1 = args[3]->NumberValue();
+ qreal y1 = args[4]->NumberValue();
+ qreal r1 = args[5]->NumberValue();
+
+ if (!qIsFinite(x0)
+ || !qIsFinite(y0)
+ || !qIsFinite(x1)
+ || !qIsFinite(r0)
+ || !qIsFinite(r1)
+ || !qIsFinite(y1))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
+
+ if (r0 < 0 || r1 < 0)
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
+
+
+ r->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
+ gradient->SetExternalResource(r);
+ return gradient;
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::createConicalGradient(real x, real y, real angle)
+ Returns a CanvasGradient object that represents a conical gradient that interpolate colors counter-clockwise around a center point (\c x, \c y)
+ with start angle \c angle in units of radians.
+
+ \sa QtQuick2::Context2D::CanvasGradient::addColorStop
+ \sa QtQuick2::Context2D::createLinearGradient
+ \sa QtQuick2::Context2D::ctx2d_createRadialGradient
+ \sa QtQuick2::Context2D::createPattern
+ \sa QtQuick2::Context2D::fillStyle
+ \sa QtQuick2::Context2D::strokeStyle
+ */
+
+static v8::Handle<v8::Value> ctx2d_createConicalGradient(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 6) {
+ QQuickContext2DEngineData *ed = engineData(engine);
+ v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
+ QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
+
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal angle = DEGREES(args[2]->NumberValue());
+ if (!qIsFinite(x) || !qIsFinite(y))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
+
+ if (!qIsFinite(angle))
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
+
+ r->brush = QConicalGradient(x, y, angle);
+ gradient->SetExternalResource(r);
+ return gradient;
+ }
+
+ return args.This();
+}
+/*!
+ \qmlmethod variant createPattern(Color color, enumeration patternMode)
+ This is a overload function.
+ Returns a CanvasPattern object that uses the given \c color and \c patternMode.
+ The valid pattern modes are:
+ \list
+ \o Qt.SolidPattern
+ \o Qt.Dense1Pattern
+ \o Qt.Dense2Pattern
+ \o Qt.Dense3Pattern
+ \o Qt.Dense4Pattern
+ \o Qt.Dense5Pattern
+ \o Qt.Dense6Pattern
+ \o Qt.Dense7Pattern
+ \o Qt.HorPattern
+ \o Qt.VerPattern
+ \o Qt.CrossPattern
+ \o Qt.BDiagPattern
+ \o Qt.FDiagPattern
+ \o Qt.DiagCrossPattern
+\endlist
+ \sa Qt::BrushStyle
+ */
+/*!
+ \qmlmethod variant createPattern(Image image, string repetition)
+ Returns a CanvasPattern object that uses the given image and repeats in the direction(s) given by the repetition argument.
+
+ The \a image parameter must be a valid Image item, a valid \a QtQuick2::CanvasImageData object or loaded image url, if there is no image data, throws an INVALID_STATE_ERR exception.
+
+ The allowed values for \a repetition are:
+
+ \list
+ \o "repeat" - both directions
+ \o "repeat-x - horizontal only
+ \o "repeat-y" - vertical only
+ \o "no-repeat" - neither
+ \endlist
+
+ If the repetition argument is empty or null, the value "repeat" is used.
+
+ \sa QtQuick2::Context2D::strokeStyle
+ \sa QtQuick2::Context2D::fillStyle
+ */
+static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 2) {
+ QQuickContext2DEngineData *ed = engineData(engine);
+ QV8Context2DStyleResource *styleResouce = new QV8Context2DStyleResource(engine);
+
+ QColor color = engine->toVariant(args[0], qMetaTypeId<QColor>()).value<QColor>();
+ if (color.isValid()) {
+ int patternMode = args[1]->IntegerValue();
+ Qt::BrushStyle style = Qt::SolidPattern;
+ if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) {
+ style = static_cast<Qt::BrushStyle>(patternMode);
+ }
+ styleResouce->brush = QBrush(color, style);
+ } else {
+ QImage patternTexture;
+
+ if (args[0]->IsObject()) {
+ QV8Context2DPixelArrayResource *pixelData = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->Get(v8::String::New("data"))->ToObject());
+ if (pixelData) {
+ patternTexture = pixelData->image;
+ }
+ } else {
+ patternTexture = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+ }
+
+ if (!patternTexture.isNull()) {
+ styleResouce->brush.setTextureImage(patternTexture);
+
+ QString repetition = engine->toString(args[1]);
+ if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) {
+ styleResouce->patternRepeatX = true;
+ styleResouce->patternRepeatY = true;
+ } else if (repetition == QStringLiteral("repeat-x")) {
+ styleResouce->patternRepeatX = true;
+ } else if (repetition == QStringLiteral("repeat-y")) {
+ styleResouce->patternRepeatY = true;
+ } else if (repetition == QStringLiteral("no-repeat")) {
+ styleResouce->patternRepeatY = false;
+ styleResouce->patternRepeatY = false;
+ } else {
+ //TODO: exception: SYNTAX_ERR
+ }
+
+ }
+ }
+
+ v8::Local<v8::Object> pattern = ed->constructorPattern->NewInstance();
+ pattern->SetExternalResource(styleResouce);
+ return pattern;
+
+ }
+ return v8::Undefined();
+}
+
+// line styles
+/*!
+ \qmlproperty string QtQuick2::Context2D::lineCap
+ Holds the the current line cap style.
+ The possible line cap styles are:
+ \list
+ \o butt - the end of each line has a flat edge perpendicular to the direction of the line, this is the default line cap value.
+ \o round - a semi-circle with the diameter equal to the width of the line must then be added on to the end of the line.
+ \o square - a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line.
+ \endlist
+ Other values are ignored.
+*/
+v8::Handle<v8::Value> ctx2d_lineCap(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ switch (r->context->state.lineCap) {
+ case Qt::RoundCap:
+ return engine->toString(QLatin1String("round"));
+ case Qt::FlatCap:
+ return engine->toString(QLatin1String("butt"));
+ case Qt::SquareCap:
+ return engine->toString(QLatin1String("square"));
+ default:
+ break;
+ }
+ return engine->toString(QLatin1String("butt"));;
+}
+
+static void ctx2d_lineCap_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ QString lineCap = engine->toString(value);
+ Qt::PenCapStyle cap;
+ if (lineCap == QLatin1String("round"))
+ cap = Qt::RoundCap;
+ else if (lineCap == QLatin1String("butt"))
+ cap = Qt::FlatCap;
+ else if (lineCap == QLatin1String("square"))
+ cap = Qt::SquareCap;
+ else
+ return;
+
+ if (cap != r->context->state.lineCap) {
+ r->context->state.lineCap = cap;
+ r->context->buffer()->setLineCap(cap);
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick2::Context2D::lineJoin
+ Holds the the current line join style. A join exists at any point in a subpath
+ shared by two consecutive lines. When a subpath is closed, then a join also exists
+ at its first point (equivalent to its last point) connecting the first and last lines in the subpath.
+
+ The possible line join styles are:
+ \list
+ \o bevel - this is all that is rendered at joins.
+ \o round - a filled arc connecting the two aforementioned corners of the join, abutting (and not overlapping) the aforementioned triangle, with the diameter equal to the line width and the origin at the point of the join, must be rendered at joins.
+ \o miter - a second filled triangle must (if it can given the miter length) be rendered at the join, this is the default line join style.
+ \endlist
+ Other values are ignored.
+*/
+v8::Handle<v8::Value> ctx2d_lineJoin(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ switch (r->context->state.lineJoin) {
+ case Qt::RoundJoin:
+ return engine->toString(QLatin1String("round"));
+ case Qt::BevelJoin:
+ return engine->toString(QLatin1String("bevel"));
+ case Qt::MiterJoin:
+ return engine->toString(QLatin1String("miter"));
+ default:
+ break;
+ }
+ return engine->toString(QLatin1String("miter"));
+}
+
+static void ctx2d_lineJoin_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ QString lineJoin = engine->toString(value);
+ Qt::PenJoinStyle join;
+ if (lineJoin == QLatin1String("round"))
+ join = Qt::RoundJoin;
+ else if (lineJoin == QLatin1String("bevel"))
+ join = Qt::BevelJoin;
+ else if (lineJoin == QLatin1String("miter"))
+ join = Qt::MiterJoin;
+ else
+ return;
+
+ if (join != r->context->state.lineJoin) {
+ r->context->state.lineJoin = join;
+ r->context->buffer()->setLineJoin(join);
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick2::Context2D::lineWidth
+ Holds the the current line width. Values that are not finite values greater than zero are ignored.
+ */
+v8::Handle<v8::Value> ctx2d_lineWidth(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ return v8::Number::New(r->context->state.lineWidth);
+}
+
+static void ctx2d_lineWidth_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ qreal w = value->NumberValue();
+
+ if (w > 0 && qIsFinite(w) && w != r->context->state.lineWidth) {
+ r->context->state.lineWidth = w;
+ r->context->buffer()->setLineWidth(w);
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick2::Context2D::miterLimit
+ Holds the current miter limit ratio.
+ The default miter limit value is 10.0.
+ */
+v8::Handle<v8::Value> ctx2d_miterLimit(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ return v8::Number::New(r->context->state.miterLimit);
+}
+
+static void ctx2d_miterLimit_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ qreal ml = value->NumberValue();
+
+ if (ml > 0 && qIsFinite(ml) && ml != r->context->state.miterLimit) {
+ r->context->state.miterLimit = ml;
+ r->context->buffer()->setMiterLimit(ml);
+ }
+}
+
+// shadows
+/*!
+ \qmlproperty real QtQuick2::Context2D::shadowBlur
+ Holds the current level of blur applied to shadows
+ */
+v8::Handle<v8::Value> ctx2d_shadowBlur(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ return v8::Number::New(r->context->state.shadowBlur);
+}
+
+static void ctx2d_shadowBlur_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+ qreal blur = value->NumberValue();
+
+ if (blur > 0 && qIsFinite(blur) && blur != r->context->state.shadowBlur) {
+ r->context->state.shadowBlur = blur;
+ r->context->buffer()->setShadowBlur(blur);
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick2::Context2D::shadowColor
+ Holds the current shadow color.
+ */
+v8::Handle<v8::Value> ctx2d_shadowColor(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ return engine->toString(r->context->state.shadowColor.name());
+}
+
+static void ctx2d_shadowColor_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QColor color = qt_color_from_string(value);
+
+ if (color.isValid() && color != r->context->state.shadowColor) {
+ r->context->state.shadowColor = color;
+ r->context->buffer()->setShadowColor(color);
+ }
+}
+
+
+/*!
+ \qmlproperty qreal QtQuick2::Context2D::shadowOffsetX
+ Holds the current shadow offset in the positive horizontal distance.
+
+ \sa QtQuick2::Context2D::shadowOffsetY
+ */
+v8::Handle<v8::Value> ctx2d_shadowOffsetX(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ return v8::Number::New(r->context->state.shadowOffsetX);
+}
+
+static void ctx2d_shadowOffsetX_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ qreal offsetX = value->NumberValue();
+ if (qIsFinite(offsetX) && offsetX != r->context->state.shadowOffsetX) {
+ r->context->state.shadowOffsetX = offsetX;
+ r->context->buffer()->setShadowOffsetX(offsetX);
+ }
+}
+/*!
+ \qmlproperty qreal QtQuick2::Context2D::shadowOffsetY
+ Holds the current shadow offset in the positive vertical distance.
+
+ \sa QtQuick2::Context2D::shadowOffsetX
+ */
+v8::Handle<v8::Value> ctx2d_shadowOffsetY(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+
+ return v8::Number::New(r->context->state.shadowOffsetY);
+}
+
+static void ctx2d_shadowOffsetY_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ qreal offsetY = value->NumberValue();
+ if (qIsFinite(offsetY) && offsetY != r->context->state.shadowOffsetY) {
+ r->context->state.shadowOffsetY = offsetY;
+ r->context->buffer()->setShadowOffsetY(offsetY);
+ }
+}
+
+v8::Handle<v8::Value> ctx2d_path(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+ return r->context->m_v8path;
+}
+
+static void ctx2d_path_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ r->context->beginPath();
+ if (value->IsObject()) {
+ QDeclarativePath* path = qobject_cast<QDeclarativePath*>(engine->toQObject(value));
+ if (path)
+ r->context->m_path = path->path();
+ } else {
+ QString path = engine->toString(value->ToString());
+ QDeclarativeSvgParser::parsePathDataFast(path, r->context->m_path);
+ }
+ r->context->m_v8path = value;
+}
+
+//rects
+/*!
+ \qmlmethod object QtQuick2::Context2D::clearRect(real x, real y, real w, real h)
+ Clears all pixels on the canvas in the given rectangle to transparent black.
+ */
+static v8::Handle<v8::Value> ctx2d_clearRect(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+ r->context->buffer()->clearRect(x, y, w, h);
+ }
+
+ return args.This();
+}
+/*!
+ \qmlmethod object QtQuick2::Context2D::fillRect(real x, real y, real w, real h)
+ Paint the specified rectangular area using the fillStyle.
+
+ \sa QtQuick2::Context2D::fillStyle
+ */
+static v8::Handle<v8::Value> ctx2d_fillRect(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+ r->context->buffer()->fillRect(x, y, w, h);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::fillRect(real x, real y, real w, real h)
+ Stroke the specified rectangle's path using the strokeStyle, lineWidth, lineJoin,
+ and (if appropriate) miterLimit attributes.
+
+ \sa QtQuick2::Context2D::strokeStyle
+ \sa QtQuick2::Context2D::lineWidth
+ \sa QtQuick2::Context2D::lineJoin
+ \sa QtQuick2::Context2D::miterLimit
+ */
+static v8::Handle<v8::Value> ctx2d_strokeRect(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+ r->context->buffer()->strokeRect(x, y, w, h);
+ }
+
+ return args.This();
+}
+
+// Complex shapes (paths) API
+/*!
+ \qmlmethod object QtQuick2::Context2D::arc(real x, real y, real radius, real startAngle, real endAngle, bool anticlockwise)
+ Adds an arc to the current subpath that lies on the circumference of the circle whose center is at the point (\c x,\cy) and whose radius is \c radius.
+ \image qml-item-canvas-arcTo2.png
+ \sa QtQuick2::Context2D::arcTo
+ See {http://www.w3.org/TR/2dcontext/#dom-context-2d-arc}{W3C 2d context standard for arc}
+ */
+static v8::Handle<v8::Value> ctx2d_arc(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() >= 5) {
+ bool antiClockwise = false;
+
+ if (args.Length() == 6)
+ antiClockwise = args[5]->BooleanValue();
+
+ qreal radius = args[2]->NumberValue();
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal sa = args[3]->NumberValue();
+ qreal ea = args[4]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(sa) || !qIsFinite(ea))
+ return args.This();
+
+ if (radius < 0)
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
+
+ r->context->arc(args[0]->NumberValue(),
+ args[1]->NumberValue(),
+ radius,
+ args[3]->NumberValue(),
+ args[4]->NumberValue(),
+ antiClockwise);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::arcTo(real x1, real y1, real x2, real y2, real radius)
+
+ Adds an arc with the given control points and radius to the current subpath, connected to the previous point by a straight line.
+ To draw an arc, you begin with the same steps your followed to create a line:
+ \list
+ \o Call the context.beginPath() method to set a new path.
+ \o Call the context.moveTo(\c x, \c y) method to set your starting position on the canvas at the point (\c x,\c y).
+ \o To draw an arc or circle, call the context.arcTo(\c x1, \c y1, \c x2, \c y2,\c radius) method.
+ This adds an arc with starting point (\c x1,\c y1), ending point (\c x2, \c y2), and radius \c radius to the current subpath and connects
+ it to the previous subpath by a straight line.
+ \endlist
+ \image qml-item-canvas-arcTo.png
+ Both startAngle and endAngle are measured from the x axis in units of radians.
+
+ \image qml-item-canvas-startAngle.png
+ The anticlockwise has the value TRUE for each arc in the figure above because they are all drawn in the counterclockwise direction.
+ \sa QtQuick2::Context2D::arc
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto}{W3C 2d context standard for arcTo}
+ */
+static v8::Handle<v8::Value> ctx2d_arcTo(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+
+ if (args.Length() == 5) {
+ qreal x1 = args[0]->NumberValue();
+ qreal y1 = args[1]->NumberValue();
+ qreal x2 = args[2]->NumberValue();
+ qreal y2 = args[3]->NumberValue();
+
+ if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2))
+ return args.This();
+
+ qreal radius = args[4]->NumberValue();
+ if (radius < 0)
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
+ r->context->arcTo(args[0]->NumberValue(),
+ args[1]->NumberValue(),
+ args[2]->NumberValue(),
+ args[3]->NumberValue(),
+ args[4]->NumberValue());
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::beginPath()
+
+ Resets the current path to a new path.
+ */
+static v8::Handle<v8::Value> ctx2d_beginPath(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ r->context->beginPath();
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::bezierCurveTo(real cp1x, real cp1y, real cp2x, real cp2y, real x, real y)
+
+ Adds a cubic Bezier curve between the current position and the given endPoint using the control points specified by (\c cp1x, cp1y),
+ and (\c cp2x, \c cp2y).
+ After the curve is added, the current position is updated to be at the end point (\c x, \c y) of the curve.
+ The following code produces the path shown below:
+ \code
+ ctx.strokeStyle = Qt.rgba(0, 0, 0, 1);
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.moveTo(20, 0);//start point
+ ctx.bezierCurveTo(-10, 90, 210, 90, 180, 0);
+ ctx.stroke();
+ \endcode
+ \image qml-item-canvas-bezierCurveTo.png
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto}{W3C 2d context standard for bezierCurveTo}
+ \sa {http://www.openrise.com/lab/FlowerPower/}{The beautiful flower demo by using bezierCurveTo}
+ */
+static v8::Handle<v8::Value> ctx2d_bezierCurveTo(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 6) {
+ qreal cp1x = args[0]->NumberValue();
+ qreal cp1y = args[1]->NumberValue();
+ qreal cp2x = args[2]->NumberValue();
+ qreal cp2y = args[3]->NumberValue();
+ qreal x = args[4]->NumberValue();
+ qreal y = args[5]->NumberValue();
+
+ if (!qIsFinite(cp1x) || !qIsFinite(cp1y) || !qIsFinite(cp2x) || !qIsFinite(cp2y) || !qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+
+ r->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::clip()
+
+ Creates the clipping region from the current path.
+ Any parts of the shape outside the clipping path are not displayed.
+ To create a complex shape using the \a clip() method:
+
+ \list 1
+ \o Call the \c{context.beginPath()} method to set the clipping path.
+ \o Define the clipping path by calling any combination of the \c{lineTo},
+ \c{arcTo}, \c{arc}, \c{moveTo}, etc and \c{closePath} methods.
+ \o Call the \c{context.clip()} method.
+ \endlist
+
+ The new shape displays. The following shows how a clipping path can
+ modify how an image displays:
+
+ \image qml-canvas-clip-complex.png
+ \sa QtQuick2::Context2D::beginPath()
+ \sa QtQuick2::Context2D::closePath()
+ \sa QtQuick2::Context2D::stroke()
+ \sa QtQuick2::Context2D::fill()
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-clip}{W3C 2d context standard for clip}
+ */
+static v8::Handle<v8::Value> ctx2d_clip(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QPainterPath clipPath = r->context->m_path;
+ clipPath.closeSubpath();
+ if (!r->context->state.clipPath.isEmpty())
+ r->context->state.clipPath = clipPath.intersected(r->context->state.clipPath);
+ else
+ r->context->state.clipPath = clipPath;
+ r->context->buffer()->clip(r->context->state.clipPath);
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::closePath()
+ Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting a new path.
+ The current point of the new path is the previous subpath's first point.
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-closepath}{W3C 2d context standard for closePath}
+ */
+static v8::Handle<v8::Value> ctx2d_closePath(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ r->context->closePath();
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::fill()
+
+ Fills the subpaths with the current fill style.
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-fill}{W3C 2d context standard for fill}
+
+ \sa QtQuick2::Context2D::fillStyle
+ */
+static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r);
+
+ r->context->buffer()->fill(r->context->m_path);
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::lineTo(real x, real y)
+
+ Draws a line from the current position to the point (x, y).
+ */
+static v8::Handle<v8::Value> ctx2d_lineTo(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 2) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+
+ r->context->lineTo(x, y);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::moveTo(real x, real y)
+
+ Creates a new subpath with the given point.
+ */
+static v8::Handle<v8::Value> ctx2d_moveTo(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 2) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+ r->context->moveTo(x, y);
+ }
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::quadraticCurveTo(real cpx, real cpy, real x, real y)
+
+ Adds a quadratic Bezier curve between the current point and the endpoint (\c x, \c y) with the control point specified by (\c cpx, \c cpy).
+
+ See {http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for for quadraticCurveTo}
+ */
+static v8::Handle<v8::Value> ctx2d_quadraticCurveTo(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 4) {
+ qreal cpx = args[0]->NumberValue();
+ qreal cpy = args[1]->NumberValue();
+ qreal x = args[2]->NumberValue();
+ qreal y = args[3]->NumberValue();
+
+ if (!qIsFinite(cpx) || !qIsFinite(cpy) || !qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+
+ r->context->quadraticCurveTo(cpx, cpy, x, y);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::rect(real x, real y, real w, real h)
+
+ Adds a rectangle at position (\c x, \c y), with the given width \c w and height \c h, as a closed subpath.
+ */
+static v8::Handle<v8::Value> ctx2d_rect(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+ r->context->rect(x, y, w, h);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::roundedRect(real x, real y, real w, real h, real xRadius, real yRadius)
+
+ Adds the given rectangle rect with rounded corners to the path. The \c xRadius and \c yRadius arguments specify the radius of the
+ ellipses defining the corners of the rounded rectangle.
+ */
+static v8::Handle<v8::Value> ctx2d_roundedRect(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ if (args.Length() == 6) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+ qreal xr = args[4]->NumberValue();
+ qreal yr = args[5]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+ if (!qIsFinite(xr) || !qIsFinite(yr))
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "roundedRect(): Invalid arguments");
+
+ r->context->roundedRect(x, y, w, h, xr, yr);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::ellipse(real x, real y, real w, real h)
+
+ Creates an ellipse within the bounding rectangle defined by its top-left corner at (\a x, \ y), width \a w and height \a h,
+ and adds it to the path as a closed subpath.
+
+ The ellipse is composed of a clockwise curve, starting and finishing at zero degrees (the 3 o'clock position).
+ */
+static v8::Handle<v8::Value> ctx2d_ellipse(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return args.This();
+
+
+ r->context->ellipse(x, y, w, h);
+ }
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::text(string text, real x, real y)
+
+ Adds the given \c text to the path as a set of closed subpaths created from the current context font supplied.
+ The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\c x, \c y).
+ */
+static v8::Handle<v8::Value> ctx2d_text(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+ if (args.Length() == 3) {
+ qreal x = args[1]->NumberValue();
+ qreal y = args[2]->NumberValue();
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+ r->context->text(engine->toString(args[0]), x, y);
+ }
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::stroke()
+
+ Strokes the subpaths with the current stroke style.
+
+ See {http://www.w3.org/TR/2dcontext/#dom-context-2d-stroke}{W3C 2d context standard for stroke}
+
+ \sa QtQuick2::Context2D::strokeStyle
+ */
+static v8::Handle<v8::Value> ctx2d_stroke(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+
+ r->context->buffer()->stroke(r->context->m_path);
+
+ return args.This();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::isPointInPath(real x, real y)
+
+ Returns true if the given point is in the current path.
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath}{W3C 2d context standard for isPointInPath}
+ */
+static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ bool pointInPath = false;
+ if (args.Length() == 2) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return v8::Boolean::New(false);
+ pointInPath = r->context->isPointInPath(x, y);
+ }
+ return v8::Boolean::New(pointInPath);
+}
+
+static v8::Handle<v8::Value> ctx2d_drawFocusRing(const v8::Arguments &args)
+{
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
+ return args.This();
+}
+
+static v8::Handle<v8::Value> ctx2d_setCaretSelectionRect(const v8::Arguments &args)
+{
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
+ return args.This();
+}
+
+static v8::Handle<v8::Value> ctx2d_caretBlinkRate(const v8::Arguments &args)
+{
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
+ return args.This();
+}
+// text
+/*!
+ \qmlproperty string QtQuick2::Context2D::font
+ Holds the current font settings.
+
+ The default font value is "10px sans-serif".
+ See {http://www.w3.org/TR/2dcontext/#dom-context-2d-font}{w3C 2d context standard for font}
+ */
+v8::Handle<v8::Value> ctx2d_font(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ return engine->toString(r->context->state.font.toString());
+}
+
+static void ctx2d_font_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ QString fs = engine->toString(value);
+ QFont font = qt_font_from_string(fs);
+ if (font != r->context->state.font) {
+ r->context->state.font = font;
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick2::Context2D::textAlign
+
+ Holds the current text alignment settings.
+ The possible values are:
+ \list
+ \o start
+ \o end
+ \o left
+ \o right
+ \o center
+ \endlist
+ Other values are ignored. The default value is "start".
+ */
+v8::Handle<v8::Value> ctx2d_textAlign(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ switch (r->context->state.textAlign) {
+ case QQuickContext2D::Start:
+ return engine->toString(QLatin1String("start"));
+ case QQuickContext2D::End:
+ return engine->toString(QLatin1String("end"));
+ case QQuickContext2D::Left:
+ return engine->toString(QLatin1String("left"));
+ case QQuickContext2D::Right:
+ return engine->toString(QLatin1String("right"));
+ case QQuickContext2D::Center:
+ return engine->toString(QLatin1String("center"));
+ default:
+ break;
+ }
+ return engine->toString(QLatin1String("start"));
+}
+
+static void ctx2d_textAlign_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+
+ QString textAlign = engine->toString(value);
+
+ QQuickContext2D::TextAlignType ta;
+ if (textAlign == QLatin1String("start"))
+ ta = QQuickContext2D::Start;
+ else if (textAlign == QLatin1String("end"))
+ ta = QQuickContext2D::End;
+ else if (textAlign == QLatin1String("left"))
+ ta = QQuickContext2D::Left;
+ else if (textAlign == QLatin1String("right"))
+ ta = QQuickContext2D::Right;
+ else if (textAlign == QLatin1String("center"))
+ ta = QQuickContext2D::Center;
+ else
+ return;
+
+ if (ta != r->context->state.textAlign) {
+ r->context->state.textAlign = ta;
+ }
+}
+
+/*!
+ \qmlproperty string QtQuick2::Context2D::textBaseline
+
+ Holds the current baseline alignment settings.
+ The possible values are:
+ \list
+ \o top
+ \o hanging
+ \o middle
+ \o alphabetic
+ \o ideographic
+ \o bottom
+ \endlist
+ Other values are ignored. The default value is "alphabetic".
+ */
+v8::Handle<v8::Value> ctx2d_textBaseline(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ switch (r->context->state.textBaseline) {
+ case QQuickContext2D::Alphabetic:
+ return engine->toString(QLatin1String("alphabetic"));
+ case QQuickContext2D::Hanging:
+ return engine->toString(QLatin1String("hanging"));
+ case QQuickContext2D::Top:
+ return engine->toString(QLatin1String("top"));
+ case QQuickContext2D::Bottom:
+ return engine->toString(QLatin1String("bottom"));
+ case QQuickContext2D::Middle:
+ return engine->toString(QLatin1String("middle"));
+ default:
+ break;
+ }
+ return engine->toString(QLatin1String("alphabetic"));
+}
+
+static void ctx2d_textBaseline_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
+ CHECK_CONTEXT_SETTER(r)
+ QV8Engine *engine = V8ENGINE_ACCESSOR();
+ QString textBaseline = engine->toString(value);
+
+ QQuickContext2D::TextBaseLineType tb;
+ if (textBaseline == QLatin1String("alphabetic"))
+ tb = QQuickContext2D::Alphabetic;
+ else if (textBaseline == QLatin1String("hanging"))
+ tb = QQuickContext2D::Hanging;
+ else if (textBaseline == QLatin1String("top"))
+ tb = QQuickContext2D::Top;
+ else if (textBaseline == QLatin1String("bottom"))
+ tb = QQuickContext2D::Bottom;
+ else if (textBaseline == QLatin1String("middle"))
+ tb = QQuickContext2D::Middle;
+ else
+ return;
+
+ if (tb != r->context->state.textBaseline) {
+ r->context->state.textBaseline = tb;
+ }
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::fillText(text, x, y)
+ Fills the given text at the given position.
+ \sa QtQuick2::Context2D::font
+ \sa QtQuick2::Context2D::textAlign
+ \sa QtQuick2::Context2D::textBaseline
+ \sa QtQuick2::Context2D::strokeText
+ */
+static v8::Handle<v8::Value> ctx2d_fillText(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+ if (args.Length() == 3) {
+ qreal x = args[1]->NumberValue();
+ qreal y = args[2]->NumberValue();
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+ QPainterPath textPath = r->context->createTextGlyphs(x, y, engine->toString(args[0]));
+ r->context->buffer()->fill(textPath);
+ }
+ return args.This();
+}
+/*!
+ \qmlmethod object QtQuick2::Context2D::strokeText(text, x, y)
+ Strokes the given text at the given position.
+ \sa QtQuick2::Context2D::font
+ \sa QtQuick2::Context2D::textAlign
+ \sa QtQuick2::Context2D::textBaseline
+ \sa QtQuick2::Context2D::fillText
+ */
+static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+ if (args.Length() == 3) {
+ qreal x = args[1]->NumberValue();
+ qreal y = args[2]->NumberValue();
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return args.This();
+ QPainterPath textPath = r->context->createTextGlyphs(x, y, engine->toString(args[0]));
+ r->context->buffer()->stroke(textPath);
+ }
+ return args.This();
+}
+/*!
+ \qmlclass QtQuick2::TextMetrics
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.0
+ \brief The Context2D TextMetrics interface.
+ The TextMetrics object can be created by QtQuick2::Context2D::measureText method.
+ See {http://www.w3.org/TR/2dcontext/#textmetrics}{W3C 2d context TexMetrics} for more details.
+
+ \sa QtQuick2::Context2D::measureText
+ \sa QtQuick2::TextMetrics::width
+ */
+
+/*!
+ \qmlproperty int QtQuick2::TextMetrics::width
+ Holds the advance width of the text that was passed to the QtQuick2::Context2D::measureText() method.
+ This property is read only.
+ */
+
+/*!
+ \qmlmethod variant QtQuick2::Context2D::measureText(text)
+ Returns a TextMetrics object with the metrics of the given text in the current font.
+ */
+static v8::Handle<v8::Value> ctx2d_measureText(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 1) {
+ QFontMetrics fm(r->context->state.font);
+ uint width = fm.width(engine->toString(args[0]));
+ v8::Local<v8::Object> tm = v8::Object::New();
+ tm->Set(v8::String::New("width"), v8::Number::New(width));
+ return tm;
+ }
+ return v8::Undefined();
+}
+
+// drawing images
+/*!
+ \qmlmethod QtQuick2::Context2D::drawImage(variant image, real dx, real dy)
+ Draws the given \a image on the canvas at position (\a dx, \a dy).
+ Note:
+ The \a image type can be an Image item, an image url or a \a {QtQuick2::CanvasImageData} object.
+ When given as Image item, if the image isn't fully loaded, this method draws nothing.
+ When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
+ This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
+
+ \sa QtQuick2::CanvasImageData
+ \sa QtQuick2::Image
+ \sa QtQuick2::Canvas::loadImage
+ \sa QtQuick2::Canvas::isImageLoaded
+ \sa QtQuick2::Canvas::imageLoaded
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
+ */
+/*!
+ \qmlmethod QtQuick2::Context2D::drawImage(variant image, real dx, real dy, real dw, real dh)
+ This is an overloaded function.
+ Draws the given item as \a image onto the canvas at point (\a dx, \a dy) and with width \a dw,
+ height \a dh.
+
+ Note:
+ The \a image type can be an Image item, an image url or a \a {QtQuick2::CanvasImageData} object.
+ When given as Image item, if the image isn't fully loaded, this method draws nothing.
+ When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
+ This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
+
+ \sa QtQuick2::CanvasImageData
+ \sa QtQuick2::Image
+ \sa QtQuick2::Canvas::loadImage
+ \sa QtQuick2::Canvas::isImageLoaded
+ \sa QtQuick2::Canvas::imageLoaded
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
+ */
+/*!
+ \qmlmethod QtQuick2::Context2D::drawImage(variant image, real sx, real sy, real sw, sh, real dx, real dy, real dw, dh)
+ This is an overloaded function.
+ Draws the given item as \a image from source point (\a sx, \a sy) and source width \sw, source height \sh
+ onto the canvas at point (\a dx, \a dy) and with width \a dw, height \a dh.
+
+
+ Note:
+ The \a image type can be an Image or Canvas item, an image url or a \a {QtQuick2::CanvasImageData} object.
+ When given as Image item, if the image isn't fully loaded, this method draws nothing.
+ When given as url string, the image should be loaded by calling Canvas item's \a QtQuick2::Canvas::loadImage() method first.
+ This image been drawing is subject to the current context clip path, even the given \c image is a {QtQuick2::CanvasImageData} object.
+
+ \sa QtQuick2::CanvasImageData
+ \sa QtQuick2::Image
+ \sa QtQuick2::Canvas::loadImage
+ \sa QtQuick2::Canvas::isImageLoaded
+ \sa QtQuick2::Canvas::imageLoaded
+
+ \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
+*/
+static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+ qreal sx, sy, sw, sh, dx, dy, dw, dh;
+
+ if (!args.Length())
+ return args.This();
+
+ QImage image;
+ if (args[0]->IsString()) {
+ QUrl url(engine->toString(args[0]->ToString()));
+ if (!url.isValid())
+ V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
+
+ image = r->context->createImage(url);
+ } else if (args[0]->IsObject()) {
+ QQuickImage *imageItem = qobject_cast<QQuickImage*>(engine->toQObject(args[0]->ToObject()));
+ QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(engine->toQObject(args[0]->ToObject()));
+
+ QV8Context2DPixelArrayResource *pix = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->GetInternalField(0)->ToObject());
+ if (pix) {
+ image = pix->image;
+ } else if (imageItem) {
+ image = imageItem->image();
+ } else if (canvas) {
+ image = canvas->toImage();
+ } else {
+ V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
+ }
+ } else {
+ V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
+ }
+ if (args.Length() == 3) {
+ dx = args[1]->NumberValue();
+ dy = args[2]->NumberValue();
+ sx = 0;
+ sy = 0;
+ sw = image.width();
+ sh = image.height();
+ dw = sw;
+ dh = sh;
+ } else if (args.Length() == 5) {
+ sx = 0;
+ sy = 0;
+ sw = image.width();
+ sh = image.height();
+ dx = args[1]->NumberValue();
+ dy = args[2]->NumberValue();
+ dw = args[3]->NumberValue();
+ dh = args[4]->NumberValue();
+ } else if (args.Length() == 9) {
+ sx = args[1]->NumberValue();
+ sy = args[2]->NumberValue();
+ sw = args[3]->NumberValue();
+ sh = args[4]->NumberValue();
+ dx = args[5]->NumberValue();
+ dy = args[6]->NumberValue();
+ dw = args[7]->NumberValue();
+ dh = args[8]->NumberValue();
+ } else {
+ return args.This();
+ }
+
+ if (!qIsFinite(sx)
+ || !qIsFinite(sy)
+ || !qIsFinite(sw)
+ || !qIsFinite(sh)
+ || !qIsFinite(dx)
+ || !qIsFinite(dy)
+ || !qIsFinite(dw)
+ || !qIsFinite(dh))
+ return args.This();
+
+ if (!image.isNull()) {
+ if (sx < 0 || sy < 0 || sw == 0 || sh == 0
+ || sx + sw > image.width() || sy + sh > image.height()
+ || sx + sw < 0 || sy + sh < 0) {
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
+ }
+
+ r->context->buffer()->drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
+ }
+
+ return args.This();
+}
+
+// pixel manipulation
+/*!
+ \qmlclass QtQuick2::CanvasImageData
+ The \a QtQuick2::CanvasImageData object holds the image pixel data.
+
+ The \a QtQuick2::CanvasImageData object has the actual dimensions of the data stored in
+ this object and holds the one-dimensional array containing the data in RGBA order,
+ as integers in the range 0 to 255.
+
+ \sa QtQuick2::CanvasImageData::width
+ \sa QtQuick2::CanvasImageData::height
+ \sa QtQuick2::CanvasImageData::data
+ \sa QtQuick2::Context2D::createImageData
+ \sa QtQuick2::Context2D::getImageData
+ \sa QtQuick2::Context2D::putImageData
+ */
+/*!
+ \qmlproperty QtQuick2::CanvasImageData::width
+ Holds the actual width dimension of the data in the ImageData object, in device pixels.
+ */
+v8::Handle<v8::Value> ctx2d_imageData_width(v8::Local<v8::String>, const v8::AccessorInfo &args)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
+ if (!r)
+ return v8::Integer::New(0);
+ return v8::Integer::New(r->image.width());
+}
+
+/*!
+ \qmlproperty QtQuick2::CanvasImageData::height
+ Holds the actual height dimension of the data in the ImageData object, in device pixels.
+ */
+v8::Handle<v8::Value> ctx2d_imageData_height(v8::Local<v8::String>, const v8::AccessorInfo &args)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
+ if (!r)
+ return v8::Integer::New(0);
+
+ return v8::Integer::New(r->image.height());
+}
+
+/*!
+ \qmlproperty QtQuick2::CanvasImageData::data
+ Holds the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255.
+ */
+v8::Handle<v8::Value> ctx2d_imageData_data(v8::Local<v8::String>, const v8::AccessorInfo &args)
+{
+ return args.This()->GetInternalField(0);
+}
+
+/*!
+ \qmlmethod void QtQuick2::CanvasImageData::mirrr( bool horizontal = false, bool vertical = true)
+ Mirrors the image data in place in the \c horizontal and/or the \c vertical direction depending on
+ whether horizontal and vertical are set to true or false.
+ The default \c horizontal value is false, the default \c vertical value is true.
+*/
+static v8::Handle<v8::Value> ctx2d_imageData_mirror(const v8::Arguments &args)
+{
+ bool horizontal = false, vertical = true;
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
+
+ if (!r) {
+ //error
+ return v8::Undefined();
+ }
+
+ if (args.Length() > 2) {
+ //error
+ return v8::Undefined();
+ }
+
+ if (args.Length() == 1) {
+ horizontal = args[0]->BooleanValue();
+ } else if (args.Length() == 2) {
+ horizontal = args[0]->BooleanValue();
+ vertical = args[1]->BooleanValue();
+ }
+ r->image = r->image.mirrored(horizontal, vertical);
+ return args.This();
+}
+
+/*!
+ \qmlmethod void QtQuick2::CanvasImageData::filter(enumeration mode, args)
+ Filters the image data as defined by one of the following modes:
+ \list
+ \o Canvas.Threshold - converts the image to black and white pixels depending
+ if they are above or below the threshold defined by the level parameter.
+ The level must be between 0.0 (black) and 1.0(white).
+ If no level is specified, 0.5 is used.
+ \o Canvas.Mono - converts the image to the 1-bit per pixel format.
+ \o Canvas.GrayScale - converts any colors in the image to grayscale equivalents.
+ \o Canvas.Brightness -increase/decrease a fixed \c adjustment value to each pixel's RGB channel value.
+ \o Canvas.Invert - sets each pixel to its inverse value.
+ \o Canvas.Blur - executes a box blur with the pixel \c radius parameter specifying the range of the blurring for each pixel.
+ the default blur \c radius is 3. This filter also accepts another \c quality parameter, if true, the filter will
+ execute 3-passes box blur to simulate the Guassian blur. The default \c quality value is false.
+ \o Canvas.Opaque - sets the alpha channel to entirely opaque.
+ \o Canvas.Convolute - executes a generic {http://en.wikipedia.org/wiki/Convolution}{Convolution} filter, the second
+ parameter contains the convoluton matrix data as a number array.
+ \endlist
+
+*/
+static v8::Handle<v8::Value> ctx2d_imageData_filter(const v8::Arguments &args)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This()->GetInternalField(0)->ToObject());
+
+ if (!r) {
+ //error
+ return v8::Undefined();
+ }
+
+ if (args.Length() >= 1) {
+ int filterFlag = args[0]->IntegerValue();
+ switch (filterFlag) {
+ case QQuickCanvasItem::Mono :
+ {
+ r->image = r->image.convertToFormat(QImage::Format_Mono).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+ break;
+ case QQuickCanvasItem::GrayScale :
+ {
+ for (int y = 0; y < r->image.height(); ++y) {
+ QRgb *row = (QRgb*)r->image.scanLine(y);
+ for (int x = 0; x < r->image.width(); ++x) {
+ unsigned char* rgb = ((unsigned char*)&row[x]);
+ rgb[0] = rgb[1] = rgb[2] = qGray(rgb[0], rgb[1], rgb[2]);
+ }
+ }
+ }
+ break;
+ case QQuickCanvasItem::Threshold :
+ {
+ qreal threshold = 0.5;
+ if (args.Length() > 1)
+ threshold = args[1]->NumberValue();
+
+ for (int y = 0; y < r->image.height(); ++y) {
+ QRgb *row = (QRgb*)r->image.scanLine(y);
+ for (int x = 0; x < r->image.width(); ++x) {
+ unsigned char* rgb = ((unsigned char*)&row[x]);
+ unsigned char v = qGray(rgb[0], rgb[1], rgb[2]) >= threshold*255 ? 255 : 0;
+ rgb[0] = rgb[1] = rgb[2] = v;
+ }
+ }
+ }
+ break;
+ case QQuickCanvasItem::Brightness :
+ {
+ int adjustment = 1;
+ if (args.Length() > 1)
+ adjustment = args[1]->IntegerValue();
+
+ for (int y = 0; y < r->image.height(); ++y) {
+ QRgb *row = (QRgb*)r->image.scanLine(y);
+ for (int x = 0; x < r->image.width(); ++x) {
+ ((unsigned char*)&row[x])[0] += adjustment;
+ ((unsigned char*)&row[x])[1] += adjustment;
+ ((unsigned char*)&row[x])[2] += adjustment;
+ }
+ }
+ }
+ break;
+ case QQuickCanvasItem::Invert :
+ {
+ r->image.invertPixels();
+ }
+ break;
+ case QQuickCanvasItem::Blur :
+ {
+ int radius = 3;
+ bool quality = false;
+
+ if (args.Length() > 1)
+ radius = args[1]->IntegerValue() / 2;
+ if (args.Length() > 2)
+ quality = args[2]->BooleanValue();
+
+ qt_image_boxblur(r->image, radius, quality);
+ }
+ break;
+ case QQuickCanvasItem::Opaque :
+ {
+ for (int y = 0; y < r->image.height(); ++y) {
+ QRgb *row = (QRgb*)r->image.scanLine(y);
+ for (int x = 0; x < r->image.width(); ++x) {
+ ((unsigned char*)&row[x])[3] = 255;
+ }
+ }
+ }
+ break;
+ case QQuickCanvasItem::Convolute :
+ {
+ if (args.Length() > 1 && args[1]->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]);
+ QVector<qreal> weights;
+ for (uint32_t i = 0; i < array->Length(); ++i)
+ weights.append(array->Get(i)->NumberValue());
+ r->image = qt_image_convolute_filter(r->image, weights);
+ } else {
+ //error
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return args.This();
+}
+/*!
+ \qmlclass QtQuick2::CanvasPixelArray
+ The CanvasPixelArray object provides ordered, indexed access to the color components of each pixel of the image data.
+ The CanvasPixelArray can be accessed as normal Javascript array.
+ \sa QtQuick2::CanvasImageData
+ \sa {http://www.w3.org/TR/2dcontext/#canvaspixelarray}{W3C 2d context standard for PixelArray}
+ */
+
+/*!
+ \qmlproperty QtQuick2::CanvasPixelArray::length
+ The CanvasPixelArray object represents h×w×4 integers which w and h comes from CanvasImageData.
+ The length attribute of a CanvasPixelArray object must return this h×w×4 number value.
+ This property is read only.
+*/
+v8::Handle<v8::Value> ctx2d_pixelArray_length(v8::Local<v8::String>, const v8::AccessorInfo &args)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This());
+ if (!r || r->image.isNull()) return v8::Undefined();
+
+ return v8::Integer::New(r->image.width() * r->image.height() * 4);
+}
+
+v8::Handle<v8::Value> ctx2d_pixelArray_indexed(uint32_t index, const v8::AccessorInfo& args)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(args.This());
+
+ if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4)) {
+ const quint32 w = r->image.width();
+ const quint32 row = (index / 4) / w;
+ const quint32 col = (index / 4) % w;
+ const QRgb* pixel = reinterpret_cast<const QRgb*>(r->image.constScanLine(row));
+ pixel += col;
+ switch (index % 4) {
+ case 0:
+ return v8::Integer::New(qRed(*pixel));
+ case 1:
+ return v8::Integer::New(qGreen(*pixel));
+ case 2:
+ return v8::Integer::New(qBlue(*pixel));
+ case 3:
+ return v8::Integer::New(qAlpha(*pixel));
+ }
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> ctx2d_pixelArray_indexed_set(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+ QV8Context2DPixelArrayResource *r = v8_resource_cast<QV8Context2DPixelArrayResource>(info.This());
+
+ const int v = value->Uint32Value();
+ if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4) && v > 0 && v <= 255) {
+ const quint32 w = r->image.width();
+ const quint32 row = (index / 4) / w;
+ const quint32 col = (index / 4) % w;
+
+ QRgb* pixel = reinterpret_cast<QRgb*>(r->image.scanLine(row));
+ pixel += col;
+ switch (index % 4) {
+ case 0:
+ *pixel = qRgba(v, qGreen(*pixel), qBlue(*pixel), qAlpha(*pixel));
+ break;
+ case 1:
+ *pixel = qRgba(qRed(*pixel), v, qBlue(*pixel), qAlpha(*pixel));
+ break;
+ case 2:
+ *pixel = qRgba(qRed(*pixel), qGreen(*pixel), v, qAlpha(*pixel));
+ break;
+ case 3:
+ *pixel = qRgba(qRed(*pixel), qGreen(*pixel), qBlue(*pixel), v);
+ break;
+ }
+ }
+ return v8::Undefined();
+}
+/*!
+ \qmlmethod QtQuick2::CanvasImageData createImageData(real sw, real sh)
+ Creates a CanvasImageData object with the given dimensions(\a sw, \a sh).
+ */
+/*!
+ \qmlmethod QtQuick2::CanvasImageData createImageData(QtQuick2::CanvasImageData imageData)
+ Creates a CanvasImageData object with the same dimensions as the argument.
+ */
+/*!
+ \qmlmethod QtQuick2::CanvasImageData createImageData(Url imageUrl)
+ Creates a CanvasImageData object with the given image loaded from \a imageUrl.
+ Note:The \a imageUrl must be already loaded before this function call, if not, an empty
+ CanvasImageData obect will be returned.
+
+ \sa QtQuick2::Canvas::loadImage, QtQuick2::Canvas::unloadImage, QtQuick2::Canvas::isImageLoaded
+ */
+static v8::Handle<v8::Value> ctx2d_createImageData(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 1) {
+ if (args[0]->IsObject()) {
+ v8::Local<v8::Object> imgData = args[0]->ToObject();
+ QV8Context2DPixelArrayResource *pa = v8_resource_cast<QV8Context2DPixelArrayResource>(imgData->GetInternalField(0)->ToObject());
+ if (pa) {
+ qreal w = imgData->Get(v8::String::New("width"))->NumberValue();
+ qreal h = imgData->Get(v8::String::New("height"))->NumberValue();
+ return qt_create_image_data(w, h, engine, QImage());
+ }
+ } else if (args[0]->IsString()) {
+ QImage image = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+ return qt_create_image_data(image.width(), image.height(), engine, image);
+ }
+ } else if (args.Length() == 2) {
+ qreal w = args[0]->NumberValue();
+ qreal h = args[1]->NumberValue();
+
+ if (!qIsFinite(w) || !qIsFinite(h))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
+
+ if (w > 0 && h > 0)
+ return qt_create_image_data(w, h, engine, QImage());
+ else
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments");
+ }
+ return v8::Undefined();
+}
+
+/*!
+ \qmlmethod QtQuick2::CanvasImageData getImageData(real sx, real sy, real sw, real sh)
+ Returns an CanvasImageData object containing the image data for the given rectangle of the canvas.
+ */
+static v8::Handle<v8::Value> ctx2d_getImageData(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+
+ QV8Engine *engine = V8ENGINE();
+ if (args.Length() == 4) {
+ qreal x = args[0]->NumberValue();
+ qreal y = args[1]->NumberValue();
+ qreal w = args[2]->NumberValue();
+ qreal h = args[3]->NumberValue();
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(w))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
+
+ if (w <= 0 || h <= 0)
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments");
+
+ QImage image = r->context->canvas()->toImage(QRectF(x, y, w, h));
+ v8::Local<v8::Object> imageData = qt_create_image_data(w, h, engine, image);
+
+ return imageData;
+ }
+ return v8::Null();
+}
+
+/*!
+ \qmlmethod object QtQuick2::Context2D::putImageData(QtQuick2::CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight)
+ Paints the data from the given ImageData object onto the canvas. If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight) is provided, only the pixels from that rectangle are painted.
+ */
+static v8::Handle<v8::Value> ctx2d_putImageData(const v8::Arguments &args)
+{
+ QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
+ CHECK_CONTEXT(r)
+ if (args.Length() != 3 && args.Length() != 7)
+ return v8::Undefined();
+
+ if (args[0]->IsNull() || !args[0]->IsObject()) {
+ V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch");
+ }
+ qreal dx = args[1]->NumberValue();
+ qreal dy = args[2]->NumberValue();
+ qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
+
+ if (!qIsFinite(dx) || !qIsFinite(dy))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
+
+ v8::Local<v8::Object> imageData = args[0]->ToObject();
+ QV8Context2DPixelArrayResource *pixelArray = v8_resource_cast<QV8Context2DPixelArrayResource>(imageData->Get(v8::String::New("data"))->ToObject());
+ if (pixelArray) {
+ w = imageData->Get(v8::String::New("width"))->NumberValue();
+ h = imageData->Get(v8::String::New("height"))->NumberValue();
+
+ if (args.Length() == 7) {
+ dirtyX = args[3]->NumberValue();
+ dirtyY = args[4]->NumberValue();
+ dirtyWidth = args[5]->NumberValue();
+ dirtyHeight = args[6]->NumberValue();
+
+ if (!qIsFinite(dirtyX) || !qIsFinite(dirtyY) || !qIsFinite(dirtyWidth) || !qIsFinite(dirtyHeight))
+ V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
+
+
+ if (dirtyWidth < 0) {
+ dirtyX = dirtyX+dirtyWidth;
+ dirtyWidth = -dirtyWidth;
+ }
+
+ if (dirtyHeight < 0) {
+ dirtyY = dirtyY+dirtyHeight;
+ dirtyHeight = -dirtyHeight;
+ }
+
+ if (dirtyX < 0) {
+ dirtyWidth = dirtyWidth+dirtyX;
+ dirtyX = 0;
+ }
+
+ if (dirtyY < 0) {
+ dirtyHeight = dirtyHeight+dirtyY;
+ dirtyY = 0;
+ }
+
+ if (dirtyX+dirtyWidth > w) {
+ dirtyWidth = w - dirtyX;
+ }
+
+ if (dirtyY+dirtyHeight > h) {
+ dirtyHeight = h - dirtyY;
+ }
+
+ if (dirtyWidth <=0 || dirtyHeight <= 0)
+ return args.This();
+ } else {
+ dirtyX = 0;
+ dirtyY = 0;
+ dirtyWidth = w;
+ dirtyHeight = h;
+ }
+
+ QImage image = pixelArray->image.copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
+ r->context->buffer()->drawImage(image, dirtyX, dirtyY, dirtyWidth, dirtyHeight, dx, dy, dirtyWidth, dirtyHeight);
+ }
+ return args.This();
+}
+
+/*!
+ \qmlclass QtQuick2::CanvasGradient
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.0
+ \brief The Context2D opaque CanvasGradient interface.
+ */
+
+/*!
+ \qmlmethod QtQuick2::CanvasGradient QtQuick2::CanvasGradient::addColorStop(real offsetof, string color)
+ Adds a color stop with the given color to the gradient at the given offset.
+ 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end.
+
+ For example:
+ \code
+ var gradient = ctx.createLinearGradient(0, 0, 100, 100);
+ gradient.addColorStop(0.3, Qt.rgba(1, 0, 0, 1));
+ gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1');
+ \endcode
+ */
+static v8::Handle<v8::Value> ctx2d_gradient_addColorStop(const v8::Arguments &args)
+{
+ QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(args.This());
+ if (!style)
+ V8THROW_ERROR("Not a CanvasGradient object");
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (args.Length() == 2) {
+
+ if (!style->brush.gradient())
+ V8THROW_ERROR("Not a valid CanvasGradient object, can't get the gradient information");
+ QGradient gradient = *(style->brush.gradient());
+ qreal pos = args[0]->NumberValue();
+ QColor color;
+
+ if (args[1]->IsObject()) {
+ color = engine->toVariant(args[1], qMetaTypeId<QColor>()).value<QColor>();
+ } else {
+ color = qt_color_from_string(args[1]);
+ }
+ if (pos < 0.0 || pos > 1.0 || !qIsFinite(pos)) {
+ V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
+ }
+
+ if (color.isValid()) {
+ gradient.setColorAt(pos, color);
+ } else {
+ V8THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string");
+ }
+ style->brush = gradient;
+ }
+
+ return args.This();
+}
+
+
+void QQuickContext2D::beginPath()
+{
+ m_path = QPainterPath();
+ m_path.setFillRule(state.fillRule);
+}
+
+void QQuickContext2D::closePath()
+{
+ if (m_path.isEmpty())
+ return;
+
+ QRectF boundRect = m_path.boundingRect();
+ if (boundRect.width() || boundRect.height())
+ m_path.closeSubpath();
+ //FIXME:QPainterPath set the current point to (0,0) after close subpath
+ //should be the first point of the previous subpath
+}
+
+void QQuickContext2D::moveTo( qreal x, qreal y)
+{
+ //FIXME: moveTo should not close the previous subpath
+ m_path.moveTo(state.matrix.map(QPointF(x, y)));
+}
+
+void QQuickContext2D::lineTo( qreal x, qreal y)
+{
+ m_path.lineTo(state.matrix.map(QPointF(x, y)));
+}
+
+void QQuickContext2D::quadraticCurveTo(qreal cpx, qreal cpy,
+ qreal x, qreal y)
+{
+ m_path.quadTo(state.matrix.map(QPointF(cpx, cpy)),
+ state.matrix.map(QPointF(x, y)));
+}
+
+void QQuickContext2D::bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y,
+ qreal x, qreal y)
+{
+ m_path.cubicTo(state.matrix.map(QPointF(cp1x, cp1y)),
+ state.matrix.map(QPointF(cp2x, cp2y)),
+ state.matrix.map(QPointF(x, y)));
+}
+
+void QQuickContext2D::addArcTo(const QPointF& p1, const QPointF& p2, float radius)
+{
+ QPointF p0(m_path.currentPosition());
+
+ QPointF p1p0((p0.x() - p1.x()), (p0.y() - p1.y()));
+ QPointF p1p2((p2.x() - p1.x()), (p2.y() - p1.y()));
+ float p1p0_length = qSqrt(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y());
+ float p1p2_length = qSqrt(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y());
+
+ double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length);
+
+ // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8)
+ // We could have used areCollinear() here, but since we're reusing
+ // the variables computed above later on we keep this logic.
+ if (qFuzzyCompare(qAbs(cos_phi), 1.0)) {
+ m_path.lineTo(p1);
+ return;
+ }
+
+ float tangent = radius / tan(acos(cos_phi) / 2);
+ float factor_p1p0 = tangent / p1p0_length;
+ QPointF t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));
+
+ QPointF orth_p1p0(p1p0.y(), -p1p0.x());
+ float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y());
+ float factor_ra = radius / orth_p1p0_length;
+
+ // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
+ double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length);
+ if (cos_alpha < 0.f)
+ orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
+
+ QPointF p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));
+
+ // calculate angles for addArc
+ orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
+ float sa = acos(orth_p1p0.x() / orth_p1p0_length);
+ if (orth_p1p0.y() < 0.f)
+ sa = 2 * Q_PI - sa;
+
+ // anticlockwise logic
+ bool anticlockwise = false;
+
+ float factor_p1p2 = tangent / p1p2_length;
+ QPointF t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
+ QPointF orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y()));
+ float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y());
+ float ea = acos(orth_p1p2.x() / orth_p1p2_length);
+ if (orth_p1p2.y() < 0)
+ ea = 2 * Q_PI - ea;
+ if ((sa > ea) && ((sa - ea) < Q_PI))
+ anticlockwise = true;
+ if ((sa < ea) && ((ea - sa) > Q_PI))
+ anticlockwise = true;
+
+ arc(p.x(), p.y(), radius, sa, ea, anticlockwise, false);
+}
+
+void QQuickContext2D::arcTo(qreal x1, qreal y1,
+ qreal x2, qreal y2,
+ qreal radius)
+{
+ QPointF st = state.matrix.map(QPointF(x1, y1));
+ QPointF end = state.matrix.map(QPointF(x2, y2));
+
+ if (!m_path.elementCount()) {
+ m_path.moveTo(st);
+ } else if (st == m_path.currentPosition() || st == end || !radius) {
+ m_path.lineTo(st);
+ } else {
+ addArcTo(st, end, radius);
+ }
+}
+
+void QQuickContext2D::rect(qreal x, qreal y,
+ qreal w, qreal h)
+{
+ m_path.addPolygon(state.matrix.map(QRectF(x, y, w, h)));
+}
+
+void QQuickContext2D::roundedRect(qreal x, qreal y,
+ qreal w, qreal h,
+ qreal xr, qreal yr)
+{
+ QPainterPath path;
+ path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
+ m_path.addPath(state.matrix.map(path));
+}
+
+void QQuickContext2D::ellipse(qreal x, qreal y,
+ qreal w, qreal h)
+{
+ QPainterPath path;
+ path.addEllipse(x, y, w, h);
+ m_path.addPath(state.matrix.map(path));
+}
+
+void QQuickContext2D::text(const QString& str, qreal x, qreal y)
+{
+ QPainterPath path;
+ path.addText(x, y, state.font, str);
+ m_path.addPath(state.matrix.map(path));
+}
+
+void QQuickContext2D::arc(qreal xc,
+ qreal yc,
+ qreal radius,
+ qreal sar,
+ qreal ear,
+ bool antiClockWise,
+ bool transform)
+{
+
+ if (transform) {
+ QPointF point = state.matrix.map(QPointF(xc, yc));
+ xc = point.x();
+ yc = point.y();
+ }
+ //### HACK
+
+ // In Qt we don't switch the coordinate system for degrees
+ // and still use the 0,0 as bottom left for degrees so we need
+ // to switch
+ sar = -sar;
+ ear = -ear;
+ antiClockWise = !antiClockWise;
+ //end hack
+
+ float sa = DEGREES(sar);
+ float ea = DEGREES(ear);
+
+ double span = 0;
+
+ double xs = xc - radius;
+ double ys = yc - radius;
+ double width = radius*2;
+ double height = radius*2;
+ if ((!antiClockWise && (ea - sa >= 360)) || (antiClockWise && (sa - ea >= 360)))
+ // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
+ // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
+ // circumference of this circle.
+ span = 360;
+ else {
+ if (!antiClockWise && (ea < sa)) {
+ span += 360;
+ } else if (antiClockWise && (sa < ea)) {
+ span -= 360;
+ }
+ //### this is also due to switched coordinate system
+ // we would end up with a 0 span instead of 360
+ if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
+ qFuzzyCompare(qAbs(span), 360))) {
+ span += ea - sa;
+ }
+ if (!m_path.elementCount())
+ m_path.moveTo(xs, ys);
+ }
+
+
+ if (transform) {
+ QPointF currentPos = m_path.currentPosition();
+ QPointF startPos = QPointF(xc + radius * qCos(sar),
+ yc - radius * qSin(sar));
+ if (currentPos != startPos)
+ m_path.lineTo(startPos);
+ }
+
+ m_path.arcTo(xs, ys, width, height, sa, span);
+}
+
+int baseLineOffset(QQuickContext2D::TextBaseLineType value, const QFontMetrics &metrics)
+{
+ int offset = 0;
+ switch (value) {
+ case QQuickContext2D::Top:
+ break;
+ case QQuickContext2D::Alphabetic:
+ case QQuickContext2D::Middle:
+ case QQuickContext2D::Hanging:
+ offset = metrics.ascent();
+ break;
+ case QQuickContext2D::Bottom:
+ offset = metrics.height();
+ break;
+ }
+ return offset;
+}
+
+static int textAlignOffset(QQuickContext2D::TextAlignType value, const QFontMetrics &metrics, const QString &text)
+{
+ int offset = 0;
+ if (value == QQuickContext2D::Start)
+ value = QGuiApplication::layoutDirection() == Qt::LeftToRight ? QQuickContext2D::Left : QQuickContext2D::Right;
+ else if (value == QQuickContext2D::End)
+ value = QGuiApplication::layoutDirection() == Qt::LeftToRight ? QQuickContext2D::Right: QQuickContext2D::Left;
+ switch (value) {
+ case QQuickContext2D::Center:
+ offset = metrics.width(text)/2;
+ break;
+ case QQuickContext2D::Right:
+ offset = metrics.width(text);
+ case QQuickContext2D::Left:
+ default:
+ break;
+ }
+ return offset;
+}
+
+
+QImage QQuickContext2D::createImage(const QUrl& url)
+{
+ return m_canvas->loadedImage(url);
+}
+
+QPainterPath QQuickContext2D::createTextGlyphs(qreal x, qreal y, const QString& text)
+{
+ const QFontMetrics metrics(state.font);
+ int yoffset = baseLineOffset(static_cast<QQuickContext2D::TextBaseLineType>(state.textBaseline), metrics);
+ int xoffset = textAlignOffset(static_cast<QQuickContext2D::TextAlignType>(state.textAlign), metrics, text);
+
+ QPainterPath textPath;
+
+ textPath.addText(x - xoffset, y - yoffset+metrics.ascent(), state.font, text);
+ textPath = state.matrix.map(textPath);
+ return textPath;
+}
+
+
+bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
+{
+ return m_path.contains(QPointF(x, y));
+}
+
+QQuickContext2D::QQuickContext2D(QQuickCanvasItem* item)
+ : m_canvas(item)
+ , m_buffer(new QQuickContext2DCommandBuffer)
+ , m_v8engine(0)
+{
+ reset();
+}
+
+QQuickContext2D::~QQuickContext2D()
+{
+ delete m_buffer;
+}
+
+v8::Handle<v8::Object> QQuickContext2D::v8value() const
+{
+ return m_v8value;
+}
+
+QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
+{
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("canvas"), ctx2d_canvas, 0, v8::External::Wrap(engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("restore"), V8FUNCTION(ctx2d_restore, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("reset"), V8FUNCTION(ctx2d_reset, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("save"), V8FUNCTION(ctx2d_save, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("rotate"), V8FUNCTION(ctx2d_rotate, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("scale"), V8FUNCTION(ctx2d_scale, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("resetTransform"), V8FUNCTION(ctx2d_resetTransform, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("setTransform"), V8FUNCTION(ctx2d_setTransform, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("transform"), V8FUNCTION(ctx2d_transform, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("translate"), V8FUNCTION(ctx2d_translate, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("shear"), V8FUNCTION(ctx2d_shear, engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("globalAlpha"), ctx2d_globalAlpha, ctx2d_globalAlpha_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("globalCompositeOperation"), ctx2d_globalCompositeOperation, ctx2d_globalCompositeOperation_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("fillRule"), ctx2d_fillRule, ctx2d_fillRule_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("fillStyle"), ctx2d_fillStyle, ctx2d_fillStyle_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("strokeStyle"), ctx2d_strokeStyle, ctx2d_strokeStyle_set, v8::External::Wrap(engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("createLinearGradient"), V8FUNCTION(ctx2d_createLinearGradient, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("createRadialGradient"), V8FUNCTION(ctx2d_createRadialGradient, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("createConicalGradient"), V8FUNCTION(ctx2d_createConicalGradient, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("createPattern"), V8FUNCTION(ctx2d_createPattern, engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineCap"), ctx2d_lineCap, ctx2d_lineCap_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineJoin"), ctx2d_lineJoin, ctx2d_lineJoin_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("lineWidth"), ctx2d_lineWidth, ctx2d_lineWidth_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("miterLimit"), ctx2d_miterLimit, ctx2d_miterLimit_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowBlur"), ctx2d_shadowBlur, ctx2d_shadowBlur_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowColor"), ctx2d_shadowColor, ctx2d_shadowColor_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetX"), ctx2d_shadowOffsetX, ctx2d_shadowOffsetX_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("shadowOffsetY"), ctx2d_shadowOffsetY, ctx2d_shadowOffsetY_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("path"), ctx2d_path, ctx2d_path_set, v8::External::Wrap(engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("clearRect"), V8FUNCTION(ctx2d_clearRect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("fillRect"), V8FUNCTION(ctx2d_fillRect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("strokeRect"), V8FUNCTION(ctx2d_strokeRect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("arc"), V8FUNCTION(ctx2d_arc, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("arcTo"), V8FUNCTION(ctx2d_arcTo, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("beginPath"), V8FUNCTION(ctx2d_beginPath, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("bezierCurveTo"), V8FUNCTION(ctx2d_bezierCurveTo, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("clip"), V8FUNCTION(ctx2d_clip, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("closePath"), V8FUNCTION(ctx2d_closePath, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("fill"), V8FUNCTION(ctx2d_fill, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("lineTo"), V8FUNCTION(ctx2d_lineTo, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("moveTo"), V8FUNCTION(ctx2d_moveTo, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("quadraticCurveTo"), V8FUNCTION(ctx2d_quadraticCurveTo, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("rect"), V8FUNCTION(ctx2d_rect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("roundedRect"), V8FUNCTION(ctx2d_roundedRect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("text"), V8FUNCTION(ctx2d_text, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("ellipse"), V8FUNCTION(ctx2d_ellipse, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("stroke"), V8FUNCTION(ctx2d_stroke, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("isPointInPath"), V8FUNCTION(ctx2d_isPointInPath, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("drawFocusRing"), V8FUNCTION(ctx2d_drawFocusRing, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("caretBlinkRate"), V8FUNCTION(ctx2d_caretBlinkRate, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("setCaretSelectionRect"), V8FUNCTION(ctx2d_setCaretSelectionRect, engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("font"), ctx2d_font, ctx2d_font_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("textAlign"), ctx2d_textAlign, ctx2d_textAlign_set, v8::External::Wrap(engine));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("textBaseline"), ctx2d_textBaseline, ctx2d_textBaseline_set, v8::External::Wrap(engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("fillText"), V8FUNCTION(ctx2d_fillText, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("measureText"), V8FUNCTION(ctx2d_measureText, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("strokeText"), V8FUNCTION(ctx2d_strokeText, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("drawImage"), V8FUNCTION(ctx2d_drawImage, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("createImageData"), V8FUNCTION(ctx2d_createImageData, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("getImageData"), V8FUNCTION(ctx2d_getImageData, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("putImageData"), V8FUNCTION(ctx2d_putImageData, engine));
+
+ constructorContext = qPersistentNew(ft->GetFunction());
+
+ v8::Local<v8::FunctionTemplate> ftGradient = v8::FunctionTemplate::New();
+ ftGradient->InstanceTemplate()->SetHasExternalResource(true);
+ ftGradient->PrototypeTemplate()->Set(v8::String::New("addColorStop"), V8FUNCTION(ctx2d_gradient_addColorStop, engine));
+ constructorGradient = qPersistentNew(ftGradient->GetFunction());
+
+ v8::Local<v8::FunctionTemplate> ftPattern = v8::FunctionTemplate::New();
+ ftPattern->InstanceTemplate()->SetHasExternalResource(true);
+ constructorPattern = qPersistentNew(ftPattern->GetFunction());
+
+ v8::Local<v8::FunctionTemplate> ftPixelArray = v8::FunctionTemplate::New();
+ ftPixelArray->InstanceTemplate()->SetHasExternalResource(true);
+ ftPixelArray->InstanceTemplate()->SetAccessor(v8::String::New("length"), ctx2d_pixelArray_length, 0, v8::External::Wrap(engine));
+ ftPixelArray->InstanceTemplate()->SetIndexedPropertyHandler(ctx2d_pixelArray_indexed, ctx2d_pixelArray_indexed_set, 0, 0, 0, v8::External::Wrap(engine));
+ constructorPixelArray = qPersistentNew(ftPixelArray->GetFunction());
+
+ v8::Local<v8::FunctionTemplate> ftImageData = v8::FunctionTemplate::New();
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("width"), ctx2d_imageData_width, 0, v8::External::Wrap(engine));
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("height"), ctx2d_imageData_height, 0, v8::External::Wrap(engine));
+ ftImageData->InstanceTemplate()->SetAccessor(v8::String::New("data"), ctx2d_imageData_data, 0, v8::External::Wrap(engine));
+ ftImageData->PrototypeTemplate()->Set(v8::String::New("mirror"), V8FUNCTION(ctx2d_imageData_mirror, engine));
+ ftImageData->PrototypeTemplate()->Set(v8::String::New("filter"), V8FUNCTION(ctx2d_imageData_filter, engine));
+ ftImageData->InstanceTemplate()->SetInternalFieldCount(1);
+ constructorImageData = qPersistentNew(ftImageData->GetFunction());
+}
+
+QQuickContext2DEngineData::~QQuickContext2DEngineData()
+{
+ qPersistentDispose(constructorContext);
+ qPersistentDispose(constructorGradient);
+ qPersistentDispose(constructorPattern);
+ qPersistentDispose(constructorImageData);
+ qPersistentDispose(constructorPixelArray);
+}
+
+void QQuickContext2D::popState()
+{
+ if (m_stateStack.isEmpty())
+ return;
+
+ QQuickContext2D::State newState = m_stateStack.pop();
+
+ if (state.matrix != newState.matrix)
+ buffer()->updateMatrix(newState.matrix);
+
+ if (newState.globalAlpha != state.globalAlpha)
+ buffer()->setGlobalAlpha(newState.globalAlpha);
+
+ if (newState.globalCompositeOperation != state.globalCompositeOperation)
+ buffer()->setGlobalCompositeOperation(newState.globalCompositeOperation);
+
+ if (newState.fillStyle != state.fillStyle)
+ buffer()->setFillStyle(newState.fillStyle);
+
+ if (newState.strokeStyle != state.strokeStyle)
+ buffer()->setStrokeStyle(newState.strokeStyle);
+
+ if (newState.lineWidth != state.lineWidth)
+ buffer()->setLineWidth(newState.lineWidth);
+
+ if (newState.lineCap != state.lineCap)
+ buffer()->setLineCap(newState.lineCap);
+
+ if (newState.lineJoin != state.lineJoin)
+ buffer()->setLineJoin(newState.lineJoin);
+
+ if (newState.miterLimit != state.miterLimit)
+ buffer()->setMiterLimit(newState.miterLimit);
+
+ if (newState.clipPath != state.clipPath) {
+ buffer()->clip(newState.clipPath);
+ }
+
+ if (newState.shadowBlur != state.shadowBlur)
+ buffer()->setShadowBlur(newState.shadowBlur);
+
+ if (newState.shadowColor != state.shadowColor)
+ buffer()->setShadowColor(newState.shadowColor);
+
+ if (newState.shadowOffsetX != state.shadowOffsetX)
+ buffer()->setShadowOffsetX(newState.shadowOffsetX);
+
+ if (newState.shadowOffsetY != state.shadowOffsetY)
+ buffer()->setShadowOffsetY(newState.shadowOffsetY);
+ state = newState;
+}
+void QQuickContext2D::pushState()
+{
+ m_stateStack.push(state);
+}
+
+void QQuickContext2D::reset()
+{
+ QQuickContext2D::State newState;
+ newState.matrix = QTransform();
+
+ QPainterPath defaultClipPath;
+
+ QRect r(0, 0, m_canvas->canvasSize().width(), m_canvas->canvasSize().height());
+ r = r.united(m_canvas->canvasWindow().toRect());
+ defaultClipPath.addRect(r);
+ newState.clipPath = defaultClipPath;
+ newState.clipPath.setFillRule(Qt::WindingFill);
+
+ newState.strokeStyle = QColor("#000000");
+ newState.fillStyle = QColor("#000000");
+ newState.fillPatternRepeatX = false;
+ newState.fillPatternRepeatY = false;
+ newState.strokePatternRepeatX = false;
+ newState.strokePatternRepeatY = false;
+ newState.fillRule = Qt::WindingFill;
+ newState.globalAlpha = 1.0;
+ newState.lineWidth = 1;
+ newState.lineCap = Qt::FlatCap;
+ newState.lineJoin = Qt::MiterJoin;
+ newState.miterLimit = 10;
+ newState.shadowOffsetX = 0;
+ newState.shadowOffsetY = 0;
+ newState.shadowBlur = 0;
+ newState.shadowColor = qRgba(0, 0, 0, 0);
+ newState.globalCompositeOperation = QPainter::CompositionMode_SourceOver;
+ newState.font = QFont(QLatin1String("sans-serif"), 10);
+ newState.textAlign = QQuickContext2D::Start;
+ newState.textBaseline = QQuickContext2D::Alphabetic;
+
+ m_stateStack.clear();
+ m_stateStack.push(newState);
+ popState();
+ m_buffer->clearRect(0, 0, m_canvas->width(), m_canvas->height());
+}
+
+void QQuickContext2D::setV8Engine(QV8Engine *engine)
+{
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ if (m_v8engine != engine) {
+ m_v8engine = engine;
+
+ qPersistentDispose(m_v8value);
+
+ if (m_v8engine == 0)
+ return;
+
+ QQuickContext2DEngineData *ed = engineData(engine);
+ m_v8value = qPersistentNew(ed->constructorContext->NewInstance());
+ QV8Context2DResource *r = new QV8Context2DResource(engine);
+ r->context = this;
+ m_v8value->SetExternalResource(r);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
new file mode 100644
index 0000000000..0f320d9a7f
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCONTEXT2D_P_H
+#define QQUICKCONTEXT2D_P_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstack.h>
+#include <private/qv8engine_p.h>
+
+
+
+#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
+
+#ifdef QQUICKCONTEXT2D_DEBUG
+#include <QElapsedTimer>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCanvasItem;
+class QQuickContext2DCommandBuffer;
+class QDeclarativePixmap;
+
+class Q_QUICK_EXPORT QQuickContext2D
+{
+public:
+ enum TextBaseLineType { Alphabetic=0, Top, Middle, Bottom, Hanging};
+ enum TextAlignType { Start=0, End, Left, Right, Center};
+ enum PaintCommand {
+ Invalid = 0,
+ UpdateMatrix,
+ ClearRect,
+ FillRect,
+ StrokeRect,
+ Fill,
+ Stroke,
+ Clip,
+ UpdateBrush,
+ GlobalAlpha,
+ GlobalCompositeOperation,
+ StrokeStyle,
+ FillStyle,
+ LineWidth,
+ LineCap,
+ LineJoin,
+ MiterLimit,
+ ShadowOffsetX,
+ ShadowOffsetY,
+ ShadowBlur,
+ ShadowColor,
+ Font,
+ TextBaseline,
+ TextAlign,
+ FillText,
+ StrokeText,
+ DrawImage,
+ GetImageData
+ };
+
+
+ struct State {
+ State()
+ : strokeStyle(QColor("#000000"))
+ , fillStyle(QColor("#000000"))
+ , fillPatternRepeatX(false)
+ , fillPatternRepeatY(false)
+ , strokePatternRepeatX(false)
+ , strokePatternRepeatY(false)
+ , fillRule(Qt::WindingFill)
+ , globalAlpha(1.0)
+ , lineWidth(1)
+ , lineCap(Qt::FlatCap)
+ , lineJoin(Qt::MiterJoin)
+ , miterLimit(10)
+ , shadowOffsetX(0)
+ , shadowOffsetY(0)
+ , shadowBlur(0)
+ , shadowColor(qRgba(0, 0, 0, 0))
+ , globalCompositeOperation(QPainter::CompositionMode_SourceOver)
+ , font(QFont(QLatin1String("sans-serif"), 10))
+ , textAlign(QQuickContext2D::Start)
+ , textBaseline(QQuickContext2D::Alphabetic)
+ {
+ }
+
+ QTransform matrix;
+ QPainterPath clipPath;
+ QBrush strokeStyle;
+ QBrush fillStyle;
+ bool fillPatternRepeatX:1;
+ bool fillPatternRepeatY:1;
+ bool strokePatternRepeatX:1;
+ bool strokePatternRepeatY:1;
+ Qt::FillRule fillRule;
+ qreal globalAlpha;
+ qreal lineWidth;
+ Qt::PenCapStyle lineCap;
+ Qt::PenJoinStyle lineJoin;
+ qreal miterLimit;
+ qreal shadowOffsetX;
+ qreal shadowOffsetY;
+ qreal shadowBlur;
+ QColor shadowColor;
+ QPainter::CompositionMode globalCompositeOperation;
+ QFont font;
+ QQuickContext2D::TextAlignType textAlign;
+ QQuickContext2D::TextBaseLineType textBaseline;
+ };
+
+ QQuickContext2D(QQuickCanvasItem* item);
+ ~QQuickContext2D();
+
+ inline QQuickCanvasItem* canvas() const {return m_canvas;}
+ inline QQuickContext2DCommandBuffer* buffer() const {return m_buffer;}
+
+ v8::Handle<v8::Object> v8value() const;
+ void setV8Engine(QV8Engine *eng);
+ void popState();
+ void pushState();
+ void reset();
+
+ // path API
+ void beginPath();
+ void closePath();
+ void moveTo(qreal x, qreal y);
+ void lineTo(qreal x, qreal y);
+ void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y);
+ void bezierCurveTo(qreal cp1x, qreal cp1y,
+ qreal cp2x, qreal cp2y, qreal x, qreal y);
+ void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius);
+ void rect(qreal x, qreal y, qreal w, qreal h);
+ void roundedRect(qreal x, qreal y,qreal w, qreal h, qreal xr, qreal yr);
+ void ellipse(qreal x, qreal y,qreal w, qreal h);
+ void text(const QString& str, qreal x, qreal y);
+ void arc(qreal x, qreal y, qreal radius,
+ qreal startAngle, qreal endAngle,
+ bool anticlockwise, bool transform=true);
+ void addArcTo(const QPointF& p1, const QPointF& p2, float radius);
+
+ bool isPointInPath(qreal x, qreal y) const;
+
+ QPainterPath createTextGlyphs(qreal x, qreal y, const QString& text);
+ QImage createImage(const QUrl& url);
+
+ State state;
+ QStack<QQuickContext2D::State> m_stateStack;
+ QQuickCanvasItem* m_canvas;
+ QQuickContext2DCommandBuffer* m_buffer;
+ QPainterPath m_path;
+ v8::Local<v8::Value> m_fillStyle;
+ v8::Local<v8::Value> m_strokeStyle;
+ v8::Handle<v8::Value> m_v8path;
+ QV8Engine *m_v8engine;
+ v8::Persistent<v8::Object> m_v8value;
+};
+
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QQuickContext2D)
+
+QT_END_HEADER
+
+#endif // QQUICKCONTEXT2D_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 476e7e2cf8..476e7e2cf8 100644
--- a/src/declarative/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
new file mode 100644
index 0000000000..2029198648
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCONTEXT2DCOMMANDBUFFER_P_H
+#define QQUICKCONTEXT2DCOMMANDBUFFER_P_H
+
+#include "qquickcontext2d_p.h"
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCanvasItem;
+class QMutex;
+
+class QQuickContext2DCommandBuffer
+{
+public:
+ QQuickContext2DCommandBuffer();
+ ~QQuickContext2DCommandBuffer();
+ void reset();
+ void clear();
+ inline int size() {return commands.size();}
+ inline bool isEmpty() const {return commands.isEmpty(); }
+ inline bool hasNext() const {return cmdIdx < commands.size(); }
+ inline QQuickContext2D::PaintCommand takeNextCommand() { return commands[cmdIdx++]; }
+
+ inline qreal takeGlobalAlpha() { return takeReal(); }
+ inline QPainter::CompositionMode takeGlobalCompositeOperation(){ return static_cast<QPainter::CompositionMode>(takeInt()); }
+ inline QBrush takeStrokeStyle() { return takeBrush(); }
+ inline QBrush takeFillStyle() { return takeBrush(); }
+
+ inline qreal takeLineWidth() { return takeReal(); }
+ inline Qt::PenCapStyle takeLineCap() { return static_cast<Qt::PenCapStyle>(takeInt());}
+ inline Qt::PenJoinStyle takeLineJoin(){ return static_cast<Qt::PenJoinStyle>(takeInt());}
+ inline qreal takeMiterLimit() { return takeReal(); }
+
+ inline void setGlobalAlpha( qreal alpha)
+ {
+ commands << QQuickContext2D::GlobalAlpha;
+ reals << alpha;
+ }
+
+ inline void setGlobalCompositeOperation(QPainter::CompositionMode cm)
+ {
+ commands << QQuickContext2D::GlobalCompositeOperation;
+ ints << cm;
+ }
+
+ inline void setStrokeStyle(const QBrush &style, bool repeatX = false, bool repeatY = false)
+ {
+ commands << QQuickContext2D::StrokeStyle;
+ brushes << style;
+ bools << repeatX << repeatY;
+ }
+
+ inline void drawImage(const QImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh)
+ {
+ commands << QQuickContext2D::DrawImage;
+ images << image;
+ reals << sx << sy << sw << sh << dx << dy << dw << dh;
+ }
+
+ inline qreal takeShadowOffsetX() { return takeReal(); }
+ inline qreal takeShadowOffsetY() { return takeReal(); }
+ inline qreal takeShadowBlur() { return takeReal(); }
+ inline QColor takeShadowColor() { return takeColor(); }
+
+
+ inline void updateMatrix(const QTransform& matrix)
+ {
+ commands << QQuickContext2D::UpdateMatrix;
+ matrixes << matrix;
+ }
+
+ inline void clearRect(qreal x, qreal y, qreal w, qreal h)
+ {
+ commands << QQuickContext2D::ClearRect;
+ reals << x << y << w << h;
+ }
+
+ inline void fillRect(qreal x, qreal y, qreal w, qreal h)
+ {
+ commands << QQuickContext2D::FillRect;
+ reals << x << y << w << h;
+ }
+
+ inline void strokeRect(qreal x, qreal y, qreal w, qreal h)
+ {
+ QPainterPath p;
+ p.addRect(x, y, w, h);
+
+ commands << QQuickContext2D::Stroke;
+ pathes << p;
+ }
+
+
+ inline void fill(const QPainterPath& path)
+ {
+ commands << QQuickContext2D::Fill;
+ pathes << path;
+
+ }
+
+ inline void stroke(const QPainterPath& path)
+ {
+ commands << QQuickContext2D::Stroke;
+ pathes << path;
+ }
+
+ inline void clip(const QPainterPath& path)
+ {
+ commands << QQuickContext2D::Clip;
+ pathes << path;
+ }
+
+
+
+ inline void setFillStyle(const QBrush &style, bool repeatX = false, bool repeatY = false)
+ {
+ commands << QQuickContext2D::FillStyle;
+ brushes << style;
+ bools << repeatX << repeatY;
+ }
+
+
+ inline void setLineWidth( qreal w)
+ {
+ commands << QQuickContext2D::LineWidth;
+ reals << w;
+ }
+
+ inline void setLineCap(Qt::PenCapStyle cap)
+ {
+ commands << QQuickContext2D::LineCap;
+ ints << cap;
+ }
+
+ inline void setLineJoin(Qt::PenJoinStyle join)
+ {
+ commands << QQuickContext2D::LineJoin;
+ ints << join;
+ }
+
+ inline void setMiterLimit( qreal limit)
+ {
+ commands << QQuickContext2D::MiterLimit;
+ reals << limit;
+ }
+
+ inline void setShadowOffsetX( qreal x)
+ {
+ commands << QQuickContext2D::ShadowOffsetX;
+ reals << x;
+ }
+
+ inline void setShadowOffsetY( qreal y)
+ {
+ commands << QQuickContext2D::ShadowOffsetY;
+ reals << y;
+ }
+
+ inline void setShadowBlur( qreal b)
+ {
+ commands << QQuickContext2D::ShadowBlur;
+ reals << b;
+ }
+
+ inline void setShadowColor(const QColor &color)
+ {
+ commands << QQuickContext2D::ShadowColor;
+ colors << color;
+ }
+
+ inline QTransform takeMatrix() { return matrixes[matrixIdx++]; }
+
+ // rects
+ inline QRectF takeRect() {
+ qreal x, y, w, h;
+ x = takeReal();
+ y = takeReal();
+ w = takeReal();
+ h = takeReal();
+ return QRectF(x, y, w ,h);
+ }
+
+ inline QPainterPath takePath() { return pathes[pathIdx++]; }
+
+ inline const QImage& takeImage() { return images[imageIdx++]; }
+
+ inline int takeInt() { return ints[intIdx++]; }
+ inline bool takeBool() {return bools[boolIdx++]; }
+ inline qreal takeReal() { return reals[realIdx++]; }
+ inline QColor takeColor() { return colors[colorIdx++]; }
+ inline QBrush takeBrush() { return brushes[brushIdx++]; }
+
+ void replay(QPainter* painter, QQuickContext2D::State& state);
+private:
+ QPen makePen(const QQuickContext2D::State& state);
+ void setPainterState(QPainter* painter, const QQuickContext2D::State& state, const QPen& pen);
+ int cmdIdx;
+ int intIdx;
+ int boolIdx;
+ int realIdx;
+ int colorIdx;
+ int matrixIdx;
+ int brushIdx;
+ int pathIdx;
+ int imageIdx;
+ QVector<QQuickContext2D::PaintCommand> commands;
+
+ QVector<int> ints;
+ QVector<bool> bools;
+ QVector<qreal> reals;
+ QVector<QColor> colors;
+ QVector<QTransform> matrixes;
+ QVector<QBrush> brushes;
+ QVector<QPainterPath> pathes;
+ QVector<QImage> images;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCONTEXT2DCOMMANDBUFFER_P_H
diff --git a/src/quick/items/context2d/qquickcontext2dnode.cpp b/src/quick/items/context2d/qquickcontext2dnode.cpp
new file mode 100644
index 0000000000..445cde8964
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dnode.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickcontext2dnode_p.h"
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QQuickContext2DNode::QQuickContext2DNode(QQuickCanvasItem* item)
+ : QSGGeometryNode()
+ , m_item(item)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+ , m_texture(0)
+ , m_size(1, 1)
+ , m_dirtyGeometry(false)
+ , m_dirtyTexture(false)
+{
+ setMaterial(&m_materialO);
+ setOpaqueMaterial(&m_material);
+ setGeometry(&m_geometry);
+ setFlag(UsePreprocess, true);
+}
+
+QQuickContext2DNode::~QQuickContext2DNode()
+{
+ delete m_texture;
+}
+
+void QQuickContext2DNode::setSize(const QSizeF& size)
+{
+ if (m_size != size) {
+ m_dirtyGeometry = true;
+ m_size = size;
+ }
+}
+
+void QQuickContext2DNode::preprocess()
+{
+ bool doDirty = false;
+ QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
+ if (t) {
+ doDirty = t->updateTexture();
+ }
+ if (doDirty) {
+ m_dirtyTexture = true;
+ markDirty(DirtyMaterial);
+ }
+}
+void QQuickContext2DNode::setTexture(QQuickContext2DTexture* texture)
+{
+ if (texture != m_texture) {
+ m_dirtyTexture = true;
+ m_texture = texture;
+ }
+}
+
+void QQuickContext2DNode::update()
+{
+ if (m_dirtyGeometry)
+ updateGeometry();
+ if (m_dirtyTexture)
+ updateTexture();
+
+ m_dirtyGeometry = false;
+ m_dirtyTexture = false;
+}
+
+void QQuickContext2DNode::updateTexture()
+{
+ m_material.setTexture(m_texture);
+ m_materialO.setTexture(m_texture);
+ markDirty(DirtyMaterial);
+}
+
+void QQuickContext2DNode::updateGeometry()
+{
+ QRectF source = m_texture->textureSubRect();
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry,
+ QRectF(0, 0, m_size.width(), m_size.height()),
+ source);
+ markDirty(DirtyGeometry);
+}
+QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcontext2dnode_p.h b/src/quick/items/context2d/qquickcontext2dnode_p.h
new file mode 100644
index 0000000000..a00c939896
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dnode_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCONTEXT2DNODE_P_H
+#define QQUICKCONTEXT2DNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgtexturematerial.h>
+
+#include "qquickcanvasitem_p.h"
+#include "qquickcontext2dtexture_p.h"
+#include "qquickcontext2d_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickContext2DNode : public QSGGeometryNode
+{
+public:
+ QQuickContext2DNode(QQuickCanvasItem* item);
+ virtual ~QQuickContext2DNode();
+ void setTexture(QQuickContext2DTexture* texture);
+ void update();
+ void preprocess();
+ void setSize(const QSizeF& size);
+private:
+ void updateTexture();
+ void updateGeometry();
+
+ QQuickCanvasItem* m_item;
+ QSGOpaqueTextureMaterial m_material;
+ QSGTextureMaterial m_materialO;
+ QSGGeometry m_geometry;
+ QQuickContext2DTexture* m_texture;
+ QSizeF m_size;
+
+ bool m_dirtyGeometry;
+ bool m_dirtyTexture;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCONTEXT2DNODE_P_H
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
new file mode 100644
index 0000000000..cbf1571189
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -0,0 +1,778 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickcontext2dtexture_p.h"
+#include "qquickcontext2dtile_p.h"
+#include "qquickcanvasitem_p.h"
+#include <private/qquickitem_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include "qquickcontext2dcommandbuffer_p.h"
+#include <QOpenGLPaintDevice>
+
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFramebufferObjectFormat>
+#include <QtCore/QThread>
+
+#define QT_MINIMUM_FBO_SIZE 64
+
+static inline int qt_next_power_of_two(int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+
+Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance)
+
+
+QQuickContext2DTexture::QQuickContext2DTexture()
+ : QSGDynamicTexture()
+ , m_context(0)
+ , m_item(0)
+ , m_canvasSize(QSize(1, 1))
+ , m_tileSize(QSize(1, 1))
+ , m_canvasWindow(QRect(0, 0, 1, 1))
+ , m_dirtyCanvas(false)
+ , m_dirtyTexture(false)
+ , m_threadRendering(false)
+ , m_smooth(false)
+ , m_tiledCanvas(false)
+ , m_doGrabImage(false)
+ , m_painting(false)
+{
+}
+
+QQuickContext2DTexture::~QQuickContext2DTexture()
+{
+ clearTiles();
+}
+
+QSize QQuickContext2DTexture::textureSize() const
+{
+ return m_canvasWindow.size();
+}
+
+void QQuickContext2DTexture::markDirtyTexture()
+{
+ lock();
+ m_dirtyTexture = true;
+ unlock();
+ emit textureChanged();
+}
+
+bool QQuickContext2DTexture::setCanvasSize(const QSize &size)
+{
+ if (m_canvasSize != size) {
+ m_canvasSize = size;
+ m_dirtyCanvas = true;
+ return true;
+ }
+ return false;
+}
+
+bool QQuickContext2DTexture::setTileSize(const QSize &size)
+{
+ if (m_tileSize != size) {
+ m_tileSize = size;
+ m_dirtyCanvas = true;
+ return true;
+ }
+ return false;
+}
+
+void QQuickContext2DTexture::setSmooth(bool smooth)
+{
+ m_smooth = smooth;
+}
+
+void QQuickContext2DTexture::setItem(QQuickCanvasItem* item)
+{
+ if (!item) {
+ lock();
+ m_item = 0;
+ m_context = 0;
+ unlock();
+ wake();
+ } else if (m_item != item) {
+ lock();
+ m_item = item;
+ m_context = item->context();
+ m_state = m_context->state;
+ unlock();
+ connect(this, SIGNAL(textureChanged()), m_item, SIGNAL(painted()));
+ }
+}
+
+bool QQuickContext2DTexture::setCanvasWindow(const QRect& r)
+{
+ if (m_canvasWindow != r) {
+ m_canvasWindow = r;
+ return true;
+ }
+ return false;
+}
+
+bool QQuickContext2DTexture::setDirtyRect(const QRect &r)
+{
+ bool doDirty = false;
+ if (m_tiledCanvas) {
+ foreach (QQuickContext2DTile* t, m_tiles) {
+ bool dirty = t->rect().intersected(r).isValid();
+ t->markDirty(dirty);
+ if (dirty)
+ doDirty = true;
+ }
+ } else {
+ doDirty = m_canvasWindow.intersected(r).isValid();
+ }
+ return doDirty;
+}
+
+void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth)
+{
+ lock();
+
+ QSize ts = tileSize;
+ if (ts.width() > canvasSize.width())
+ ts.setWidth(canvasSize.width());
+
+ if (ts.height() > canvasSize.height())
+ ts.setHeight(canvasSize.height());
+
+ setCanvasSize(canvasSize);
+ setTileSize(ts);
+
+ if (canvasSize == canvasWindow.size()) {
+ m_tiledCanvas = false;
+ m_dirtyCanvas = false;
+ } else {
+ m_tiledCanvas = true;
+ }
+
+ bool doDirty = false;
+ if (dirtyRect.isValid())
+ doDirty = setDirtyRect(dirtyRect);
+
+ bool windowChanged = setCanvasWindow(canvasWindow);
+ if (windowChanged || doDirty) {
+ if (m_threadRendering)
+ QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
+ else if (supportDirectRendering()) {
+ QMetaObject::invokeMethod(this, "paint", Qt::DirectConnection);
+ }
+ }
+
+ setSmooth(smooth);
+ unlock();
+}
+
+void QQuickContext2DTexture::paintWithoutTiles()
+{
+ QQuickContext2DCommandBuffer* ccb = m_context->buffer();
+
+ if (ccb->isEmpty() && m_threadRendering && !m_doGrabImage) {
+ lock();
+ if (m_item)
+ QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, QRectF(0, 0, m_canvasSize.width(), m_canvasSize.height())));
+ wait();
+ unlock();
+ }
+ if (ccb->isEmpty()) {
+ return;
+ }
+
+ QPaintDevice* device = beginPainting();
+ if (!device) {
+ endPainting();
+ return;
+ }
+
+ QPainter p;
+ p.begin(device);
+ if (m_smooth)
+ p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
+ | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
+ else
+ p.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
+ | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, false);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ ccb->replay(&p, m_state);
+
+ ccb->clear();
+ markDirtyTexture();
+ endPainting();
+}
+
+bool QQuickContext2DTexture::canvasDestroyed()
+{
+ bool noCanvas = false;
+ lock();
+ noCanvas = m_item == 0;
+ unlock();
+ return noCanvas;
+}
+
+void QQuickContext2DTexture::paint()
+{
+ if (canvasDestroyed())
+ return;
+
+ if (!m_tiledCanvas) {
+ paintWithoutTiles();
+ } else {
+ lock();
+ QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize)));
+ unlock();
+
+ if (!tiledRegion.isEmpty()) {
+ if (m_threadRendering && !m_doGrabImage) {
+ QRect dirtyRect;
+
+ lock();
+ foreach (QQuickContext2DTile* tile, m_tiles) {
+ if (tile->dirty()) {
+ if (dirtyRect.isEmpty())
+ dirtyRect = tile->rect();
+ else
+ dirtyRect |= tile->rect();
+ }
+ }
+ unlock();
+
+ if (dirtyRect.isValid()) {
+ lock();
+ if (m_item)
+ QMetaObject::invokeMethod(m_item, "_doPainting", Qt::QueuedConnection, Q_ARG(QRectF, dirtyRect));
+ wait();
+ unlock();
+ }
+ }
+
+ if (beginPainting()) {
+ QQuickContext2D::State oldState = m_state;
+ QQuickContext2DCommandBuffer* ccb = m_context->buffer();
+ foreach (QQuickContext2DTile* tile, m_tiles) {
+ bool dirtyTile = false, dirtyCanvas = false, smooth = false;
+
+ lock();
+ dirtyTile = tile->dirty();
+ smooth = m_smooth;
+ dirtyCanvas = m_dirtyCanvas;
+ unlock();
+
+ //canvas size or tile size may change during painting tiles
+ if (dirtyCanvas) {
+ if (m_threadRendering)
+ QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
+ endPainting();
+ return;
+ } else if (dirtyTile) {
+ ccb->replay(tile->createPainter(smooth), oldState);
+ tile->drawFinished();
+ lock();
+ tile->markDirty(false);
+ unlock();
+ }
+
+ compositeTile(tile);
+ }
+ ccb->clear();
+ endPainting();
+ m_state = oldState;
+ markDirtyTexture();
+ }
+ }
+ }
+}
+
+QRect QQuickContext2DTexture::tiledRect(const QRectF& window, const QSize& tileSize)
+{
+ if (window.isEmpty())
+ return QRect();
+
+ const int tw = tileSize.width();
+ const int th = tileSize.height();
+ const int h1 = window.left() / tw;
+ const int v1 = window.top() / th;
+
+ const int htiles = ((window.right() - h1 * tw) + tw - 1)/tw;
+ const int vtiles = ((window.bottom() - v1 * th) + th - 1)/th;
+
+ return QRect(h1 * tw, v1 * th, htiles * tw, vtiles * th);
+}
+
+QRect QQuickContext2DTexture::createTiles(const QRect& window)
+{
+ QList<QQuickContext2DTile*> oldTiles = m_tiles;
+ m_tiles.clear();
+
+ if (window.isEmpty()) {
+ m_dirtyCanvas = false;
+ return QRect();
+ }
+
+ QRect r = tiledRect(window, m_tileSize);
+
+ const int tw = m_tileSize.width();
+ const int th = m_tileSize.height();
+ const int h1 = window.left() / tw;
+ const int v1 = window.top() / th;
+
+
+ const int htiles = r.width() / tw;
+ const int vtiles = r.height() / th;
+
+ for (int yy = 0; yy < vtiles; ++yy) {
+ for (int xx = 0; xx < htiles; ++xx) {
+ int ht = xx + h1;
+ int vt = yy + v1;
+
+ QQuickContext2DTile* tile = 0;
+
+ QPoint pos(ht * tw, vt * th);
+ QRect rect(pos, m_tileSize);
+
+ for (int i = 0; i < oldTiles.size(); i++) {
+ if (oldTiles[i]->rect() == rect) {
+ tile = oldTiles.takeAt(i);
+ break;
+ }
+ }
+
+ if (!tile)
+ tile = createTile();
+
+ tile->setRect(rect);
+ m_tiles.append(tile);
+ }
+ }
+
+ qDeleteAll(oldTiles);
+
+ m_dirtyCanvas = false;
+ return r;
+}
+
+void QQuickContext2DTexture::clearTiles()
+{
+ qDeleteAll(m_tiles);
+ m_tiles.clear();
+}
+
+QQuickContext2DFBOTexture::QQuickContext2DFBOTexture()
+ : QQuickContext2DTexture()
+ , m_fbo(0)
+ , m_multisampledFbo(0)
+ , m_paint_device(0)
+{
+ m_threadRendering = false;
+}
+
+QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture()
+{
+ delete m_fbo;
+ delete m_multisampledFbo;
+ delete m_paint_device;
+}
+
+bool QQuickContext2DFBOTexture::setCanvasSize(const QSize &size)
+{
+ QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
+ , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
+
+ if (m_canvasSize != s) {
+ m_canvasSize = s;
+ m_dirtyCanvas = true;
+ return true;
+ }
+ return false;
+}
+
+bool QQuickContext2DFBOTexture::setTileSize(const QSize &size)
+{
+ QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.width()))
+ , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(size.height())));
+ if (m_tileSize != s) {
+ m_tileSize = s;
+ m_dirtyCanvas = true;
+ return true;
+ }
+ return false;
+}
+
+bool QQuickContext2DFBOTexture::setCanvasWindow(const QRect& canvasWindow)
+{
+ QSize s = QSize(qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().width()))
+ , qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(canvasWindow.size().height())));
+
+
+ bool doChanged = false;
+ if (m_fboSize != s) {
+ m_fboSize = s;
+ doChanged = true;
+ }
+
+ if (m_canvasWindow != canvasWindow)
+ m_canvasWindow = canvasWindow;
+
+ return doChanged;
+}
+
+void QQuickContext2DFBOTexture::bind()
+{
+ glBindTexture(GL_TEXTURE_2D, textureId());
+ updateBindOptions();
+}
+
+QRectF QQuickContext2DFBOTexture::textureSubRect() const
+{
+ return QRectF(0
+ , 0
+ , qreal(m_canvasWindow.width()) / m_fboSize.width()
+ , qreal(m_canvasWindow.height()) / m_fboSize.height());
+}
+
+
+int QQuickContext2DFBOTexture::textureId() const
+{
+ return m_fbo? m_fbo->texture() : 0;
+}
+
+
+bool QQuickContext2DFBOTexture::updateTexture()
+{
+ if (!m_context->buffer()->isEmpty()) {
+ paint();
+ }
+
+ bool textureUpdated = m_dirtyTexture;
+
+ m_dirtyTexture = false;
+
+ if (m_doGrabImage) {
+ grabImage();
+ m_condition.wakeOne();
+ m_doGrabImage = false;
+ }
+ return textureUpdated;
+}
+
+QQuickContext2DTile* QQuickContext2DFBOTexture::createTile() const
+{
+ return new QQuickContext2DFBOTile();
+}
+
+void QQuickContext2DFBOTexture::grabImage()
+{
+ if (m_fbo) {
+ m_grabedImage = m_fbo->toImage();
+ }
+}
+
+bool QQuickContext2DFBOTexture::doMultisampling() const
+{
+ static bool extensionsChecked = false;
+ static bool multisamplingSupported = false;
+
+ if (!extensionsChecked) {
+ QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
+ multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample")
+ && extensions.contains("GL_EXT_framebuffer_blit");
+ extensionsChecked = true;
+ }
+
+ return multisamplingSupported && m_smooth;
+}
+
+QImage QQuickContext2DFBOTexture::toImage(const QRectF& region)
+{
+#define QML_CONTEXT2D_WAIT_MAX 5000
+
+ m_doGrabImage = true;
+ if (m_item)
+ m_item->update();
+
+ QImage grabbed;
+ m_mutex.lock();
+ bool ok = m_condition.wait(&m_mutex, QML_CONTEXT2D_WAIT_MAX);
+
+ if (!ok)
+ grabbed = QImage();
+
+ if (region.isValid())
+ grabbed = m_grabedImage.copy(region.toRect());
+ else
+ grabbed = m_grabedImage;
+ m_grabedImage = QImage();
+ return grabbed;
+}
+
+void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile)
+{
+ QQuickContext2DFBOTile* t = static_cast<QQuickContext2DFBOTile*>(tile);
+ QRect target = t->rect().intersect(m_canvasWindow);
+ if (target.isValid()) {
+ QRect source = target;
+
+ source.moveTo(source.topLeft() - t->rect().topLeft());
+ target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
+
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, target, t->fbo(), source);
+ }
+}
+QQuickCanvasItem::RenderTarget QQuickContext2DFBOTexture::renderTarget() const
+{
+ return QQuickCanvasItem::FramebufferObject;
+}
+QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
+{
+ QQuickContext2DTexture::beginPainting();
+
+ if (m_canvasWindow.size().isEmpty() && !m_threadRendering) {
+ delete m_fbo;
+ delete m_multisampledFbo;
+ m_fbo = 0;
+ m_multisampledFbo = 0;
+ return 0;
+ } else if (!m_fbo || m_fbo->size() != m_fboSize) {
+ delete m_fbo;
+ delete m_multisampledFbo;
+ if (doMultisampling()) {
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(8);
+ m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ } else {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ }
+
+ if (doMultisampling())
+ m_multisampledFbo->bind();
+ else
+ m_fbo->bind();
+
+
+ if (!m_paint_device) {
+ QOpenGLPaintDevice *gl_device = new QOpenGLPaintDevice(m_fbo->size());
+ gl_device->setPaintFlipped(true);
+ m_paint_device = gl_device;
+ }
+
+ return m_paint_device;
+}
+
+void QQuickContext2DFBOTexture::endPainting()
+{
+ QQuickContext2DTexture::endPainting();
+ if (m_multisampledFbo) {
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo);
+ m_multisampledFbo->release();
+ } else if (m_fbo)
+ m_fbo->release();
+}
+void qt_quit_context2d_render_thread()
+{
+ QThread* thread = globalCanvasThreadRenderInstance();
+
+ if (thread->isRunning()) {
+ thread->exit(0);
+ thread->wait(1000);
+ }
+}
+
+QQuickContext2DImageTexture::QQuickContext2DImageTexture(bool threadRendering)
+ : QQuickContext2DTexture()
+ , m_texture(new QSGPlainTexture())
+{
+ m_texture->setOwnsTexture(true);
+ m_texture->setHasMipmaps(false);
+
+ m_threadRendering = threadRendering;
+
+ if (m_threadRendering) {
+ QThread* thread = globalCanvasThreadRenderInstance();
+ moveToThread(thread);
+
+ if (!thread->isRunning()) {
+ qAddPostRoutine(qt_quit_context2d_render_thread);
+ thread->start();
+ }
+ }
+}
+
+QQuickContext2DImageTexture::~QQuickContext2DImageTexture()
+{
+ delete m_texture;
+}
+
+int QQuickContext2DImageTexture::textureId() const
+{
+ return m_texture->textureId();
+}
+
+void QQuickContext2DImageTexture::lock()
+{
+ if (m_threadRendering)
+ m_mutex.lock();
+}
+void QQuickContext2DImageTexture::unlock()
+{
+ if (m_threadRendering)
+ m_mutex.unlock();
+}
+
+void QQuickContext2DImageTexture::wait()
+{
+ if (m_threadRendering)
+ m_waitCondition.wait(&m_mutex);
+}
+
+void QQuickContext2DImageTexture::wake()
+{
+ if (m_threadRendering)
+ m_waitCondition.wakeOne();
+}
+
+bool QQuickContext2DImageTexture::supportDirectRendering() const
+{
+ return !m_threadRendering;
+}
+
+QQuickCanvasItem::RenderTarget QQuickContext2DImageTexture::renderTarget() const
+{
+ return QQuickCanvasItem::Image;
+}
+
+void QQuickContext2DImageTexture::bind()
+{
+ m_texture->bind();
+}
+
+bool QQuickContext2DImageTexture::updateTexture()
+{
+ lock();
+ bool textureUpdated = m_dirtyTexture;
+ if (m_dirtyTexture) {
+ m_texture->setImage(m_image);
+ m_dirtyTexture = false;
+ }
+ unlock();
+ return textureUpdated;
+}
+
+QQuickContext2DTile* QQuickContext2DImageTexture::createTile() const
+{
+ return new QQuickContext2DImageTile();
+}
+
+void QQuickContext2DImageTexture::grabImage(const QRect& r)
+{
+ m_doGrabImage = true;
+ paint();
+ m_doGrabImage = false;
+ m_grabedImage = m_image.copy(r);
+}
+
+QImage QQuickContext2DImageTexture::toImage(const QRectF& region)
+{
+ QRect r = region.isValid() ? region.toRect() : QRect(QPoint(0, 0), m_canvasWindow.size());
+ if (threadRendering()) {
+ wake();
+ QMetaObject::invokeMethod(this, "grabImage", Qt::BlockingQueuedConnection, Q_ARG(QRect, r));
+ } else {
+ QMetaObject::invokeMethod(this, "grabImage", Qt::DirectConnection, Q_ARG(QRect, r));
+ }
+ QImage image = m_grabedImage;
+ m_grabedImage = QImage();
+ return image;
+}
+
+QPaintDevice* QQuickContext2DImageTexture::beginPainting()
+{
+ QQuickContext2DTexture::beginPainting();
+
+ if (m_canvasWindow.size().isEmpty())
+ return 0;
+
+ lock();
+ if (m_image.size() != m_canvasWindow.size()) {
+ m_image = QImage(m_canvasWindow.size(), QImage::Format_ARGB32_Premultiplied);
+ m_image.fill(0x00000000);
+ }
+ unlock();
+ return &m_image;
+}
+
+void QQuickContext2DImageTexture::compositeTile(QQuickContext2DTile* tile)
+{
+ Q_ASSERT(!tile->dirty());
+ QQuickContext2DImageTile* t = static_cast<QQuickContext2DImageTile*>(tile);
+ QRect target = t->rect().intersect(m_canvasWindow);
+ if (target.isValid()) {
+ QRect source = target;
+ source.moveTo(source.topLeft() - t->rect().topLeft());
+ target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
+
+ lock();
+ m_painter.begin(&m_image);
+ m_painter.setCompositionMode(QPainter::CompositionMode_Source);
+ m_painter.drawImage(target, t->image(), source);
+ m_painter.end();
+ unlock();
+ }
+}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
new file mode 100644
index 0000000000..d055db7c06
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCONTEXT2DTEXTURE_P_H
+#define QQUICKCONTEXT2DTEXTURE_P_H
+
+#include <QtQuick/qsgtexture.h>
+#include "qquickcanvasitem_p.h"
+#include "qquickcontext2d_p.h"
+
+#include <QOpenGLContext>
+#include <QOpenGLFramebufferObject>
+
+#include <QtCore/QMutex>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QThread>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickContext2DTile;
+class QQuickContext2DCommandBuffer;
+
+class QQuickContext2DTexture : public QSGDynamicTexture
+{
+ Q_OBJECT
+public:
+ QQuickContext2DTexture();
+ ~QQuickContext2DTexture();
+
+ virtual bool hasAlphaChannel() const {return true;}
+ virtual bool hasMipmaps() const {return false;}
+ virtual QSize textureSize() const;
+ virtual void lock() {}
+ virtual void unlock() {}
+ virtual void wait() {}
+ virtual void wake() {}
+ bool threadRendering() const {return m_threadRendering;}
+ virtual bool supportThreadRendering() const = 0;
+ virtual bool supportDirectRendering() const = 0;
+ virtual QQuickCanvasItem::RenderTarget renderTarget() const = 0;
+ virtual QImage toImage(const QRectF& region = QRectF()) = 0;
+ static QRect tiledRect(const QRectF& window, const QSize& tileSize);
+
+ virtual bool setCanvasSize(const QSize &size);
+ virtual bool setTileSize(const QSize &size);
+ virtual bool setCanvasWindow(const QRect& canvasWindow);
+ void setSmooth(bool smooth);
+ bool setDirtyRect(const QRect &dirtyRect);
+ virtual void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
+ bool canvasDestroyed();
+Q_SIGNALS:
+ void textureChanged();
+
+public Q_SLOTS:
+ void markDirtyTexture();
+ void setItem(QQuickCanvasItem* item);
+ void paint();
+
+protected:
+ void paintWithoutTiles();
+ virtual QPaintDevice* beginPainting() {m_painting = true; return 0; }
+ virtual void endPainting() {m_painting = false;}
+ virtual QQuickContext2DTile* createTile() const = 0;
+ virtual void compositeTile(QQuickContext2DTile* tile) = 0;
+
+ void clearTiles();
+ QRect createTiles(const QRect& window);
+
+ QList<QQuickContext2DTile*> m_tiles;
+ QQuickContext2D* m_context;
+
+ QQuickContext2D::State m_state;
+
+ QQuickCanvasItem* m_item;
+ QSize m_canvasSize;
+ QSize m_tileSize;
+ QRect m_canvasWindow;
+
+ uint m_dirtyCanvas : 1;
+ uint m_dirtyTexture : 1;
+ uint m_threadRendering : 1;
+ uint m_smooth : 1;
+ uint m_tiledCanvas : 1;
+ uint m_doGrabImage : 1;
+ uint m_painting : 1;
+};
+
+class QQuickContext2DFBOTexture : public QQuickContext2DTexture
+{
+ Q_OBJECT
+
+public:
+ QQuickContext2DFBOTexture();
+ ~QQuickContext2DFBOTexture();
+ virtual int textureId() const;
+ virtual bool updateTexture();
+ virtual QQuickContext2DTile* createTile() const;
+ virtual QImage toImage(const QRectF& region = QRectF());
+ virtual QPaintDevice* beginPainting();
+ virtual void endPainting();
+ QRectF textureSubRect() const;
+ virtual bool supportThreadRendering() const {return false;}
+ virtual bool supportDirectRendering() const {return false;}
+ virtual QQuickCanvasItem::RenderTarget renderTarget() const;
+ virtual void compositeTile(QQuickContext2DTile* tile);
+ virtual void bind();
+ virtual bool setCanvasSize(const QSize &size);
+ virtual bool setTileSize(const QSize &size);
+ virtual bool setCanvasWindow(const QRect& canvasWindow);
+private Q_SLOTS:
+ void grabImage();
+
+private:
+ bool doMultisampling() const;
+ QImage m_grabedImage;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_multisampledFbo;
+ QMutex m_mutex;
+ QWaitCondition m_condition;
+ QSize m_fboSize;
+ QPaintDevice *m_paint_device;
+};
+
+class QSGPlainTexture;
+class QQuickContext2DImageTexture : public QQuickContext2DTexture
+{
+ Q_OBJECT
+
+public:
+ QQuickContext2DImageTexture(bool threadRendering = true);
+ ~QQuickContext2DImageTexture();
+ virtual int textureId() const;
+ virtual void bind();
+ virtual bool supportThreadRendering() const {return true;}
+ virtual bool supportDirectRendering() const;
+ virtual QQuickCanvasItem::RenderTarget renderTarget() const;
+ virtual void lock();
+ virtual void unlock();
+ virtual void wait();
+ virtual void wake();
+
+ virtual bool updateTexture();
+ virtual QQuickContext2DTile* createTile() const;
+ virtual QImage toImage(const QRectF& region = QRectF());
+ virtual QPaintDevice* beginPainting();
+ virtual void compositeTile(QQuickContext2DTile* tile);
+
+private Q_SLOTS:
+ void grabImage(const QRect& r);
+private:
+ QImage m_image;
+ QImage m_grabedImage;
+ QMutex m_mutex;
+ QWaitCondition m_waitCondition;
+ QPainter m_painter;
+ QSGPlainTexture* m_texture;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCONTEXT2DTEXTURE_P_H
diff --git a/src/declarative/items/context2d/qquickcontext2dtile.cpp b/src/quick/items/context2d/qquickcontext2dtile.cpp
index 6217c66094..6217c66094 100644
--- a/src/declarative/items/context2d/qquickcontext2dtile.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtile.cpp
diff --git a/src/quick/items/context2d/qquickcontext2dtile_p.h b/src/quick/items/context2d/qquickcontext2dtile_p.h
new file mode 100644
index 0000000000..a38384d3c7
--- /dev/null
+++ b/src/quick/items/context2d/qquickcontext2dtile_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCONTEXT2DTILE_P_H
+#define QQUICKCONTEXT2DTILE_P_H
+
+#include "qquickcontext2d_p.h"
+#include <QOpenGLFramebufferObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickContext2DTexture;
+class QQuickContext2DCommandBuffer;
+
+class QQuickContext2DTile
+{
+public:
+ QQuickContext2DTile();
+ ~QQuickContext2DTile();
+
+ bool dirty() const {return m_dirty;}
+ void markDirty(bool dirty) {m_dirty = dirty;}
+
+ QRect rect() const {return m_rect;}
+
+ virtual void setRect(const QRect& r) = 0;
+ virtual QPainter* createPainter(bool smooth = false);
+ virtual void drawFinished() {}
+
+protected:
+ virtual void aboutToDraw() {}
+ uint m_dirty : 1;
+ QRect m_rect;
+ QPaintDevice* m_device;
+ QPainter m_painter;
+};
+
+
+class QQuickContext2DFBOTile : public QQuickContext2DTile
+{
+public:
+ QQuickContext2DFBOTile();
+ ~QQuickContext2DFBOTile();
+ virtual void setRect(const QRect& r);
+ QOpenGLFramebufferObject* fbo() const {return m_fbo;}
+ void drawFinished();
+
+protected:
+ void aboutToDraw();
+private:
+
+
+ QOpenGLFramebufferObject *m_fbo;
+};
+
+class QQuickContext2DImageTile : public QQuickContext2DTile
+{
+public:
+ QQuickContext2DImageTile();
+ ~QQuickContext2DImageTile();
+ void setRect(const QRect& r);
+ const QImage& image() const {return m_image;}
+private:
+ QImage m_image;
+};
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCONTEXT2DTILE_P_H
diff --git a/src/declarative/items/items.pri b/src/quick/items/items.pri
index 308706f0b9..308706f0b9 100644
--- a/src/declarative/items/items.pri
+++ b/src/quick/items/items.pri
diff --git a/src/declarative/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp
index 8ebdc374fb..8ebdc374fb 100644
--- a/src/declarative/items/qquickanchors.cpp
+++ b/src/quick/items/qquickanchors.cpp
diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h
new file mode 100644
index 0000000000..6f2224f0d4
--- /dev/null
+++ b/src/quick/items/qquickanchors_p.h
@@ -0,0 +1,199 @@
+// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKANCHORS_P_H
+#define QQUICKANCHORS_P_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/QObject>
+
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickAnchorsPrivate;
+class QQuickAnchorLine;
+class Q_QUICK_PRIVATE_EXPORT QQuickAnchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQuickAnchorLine left READ left WRITE setLeft RESET resetLeft NOTIFY leftChanged)
+ Q_PROPERTY(QQuickAnchorLine right READ right WRITE setRight RESET resetRight NOTIFY rightChanged)
+ Q_PROPERTY(QQuickAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter NOTIFY horizontalCenterChanged)
+ Q_PROPERTY(QQuickAnchorLine top READ top WRITE setTop RESET resetTop NOTIFY topChanged)
+ Q_PROPERTY(QQuickAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom NOTIFY bottomChanged)
+ Q_PROPERTY(QQuickAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged)
+ Q_PROPERTY(QQuickAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline NOTIFY baselineChanged)
+ Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged)
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged)
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
+ Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
+ Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged)
+
+public:
+ QQuickAnchors(QQuickItem *item, QObject *parent=0);
+ virtual ~QQuickAnchors();
+
+ enum Anchor {
+ LeftAnchor = 0x01,
+ RightAnchor = 0x02,
+ TopAnchor = 0x04,
+ BottomAnchor = 0x08,
+ HCenterAnchor = 0x10,
+ VCenterAnchor = 0x20,
+ BaselineAnchor = 0x40,
+ Horizontal_Mask = LeftAnchor | RightAnchor | HCenterAnchor,
+ Vertical_Mask = TopAnchor | BottomAnchor | VCenterAnchor | BaselineAnchor
+ };
+ Q_DECLARE_FLAGS(Anchors, Anchor)
+
+ QQuickAnchorLine left() const;
+ void setLeft(const QQuickAnchorLine &edge);
+ void resetLeft();
+
+ QQuickAnchorLine right() const;
+ void setRight(const QQuickAnchorLine &edge);
+ void resetRight();
+
+ QQuickAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QQuickAnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QQuickAnchorLine top() const;
+ void setTop(const QQuickAnchorLine &edge);
+ void resetTop();
+
+ QQuickAnchorLine bottom() const;
+ void setBottom(const QQuickAnchorLine &edge);
+ void resetBottom();
+
+ QQuickAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QQuickAnchorLine &edge);
+ void resetVerticalCenter();
+
+ QQuickAnchorLine baseline() const;
+ void setBaseline(const QQuickAnchorLine &edge);
+ void resetBaseline();
+
+ qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QQuickItem *fill() const;
+ void setFill(QQuickItem *);
+ void resetFill();
+
+ QQuickItem *centerIn() const;
+ void setCenterIn(QQuickItem *);
+ void resetCenterIn();
+
+ Anchors usedAnchors() const;
+
+ bool mirrored();
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void topChanged();
+ void bottomChanged();
+ void verticalCenterChanged();
+ void horizontalCenterChanged();
+ void baselineChanged();
+ void fillChanged();
+ void centerInChanged();
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();
+ void mirroredChanged();
+
+private:
+ friend class QQuickItemPrivate;
+ Q_DISABLE_COPY(QQuickAnchors)
+ Q_DECLARE_PRIVATE(QQuickAnchors)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAnchors::Anchors)
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickAnchors)
+
+QT_END_HEADER
+
+#endif // QQUICKANCHORS_P_H
diff --git a/src/declarative/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h
index 50d55b081f..50d55b081f 100644
--- a/src/declarative/items/qquickanchors_p_p.h
+++ b/src/quick/items/qquickanchors_p_p.h
diff --git a/src/declarative/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index 61447c87e2..61447c87e2 100644
--- a/src/declarative/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
new file mode 100644
index 0000000000..0bb3ad73f5
--- /dev/null
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -0,0 +1,115 @@
+// Commit: 80d0fe9cbd92288a08d5ced8767f1edb651dae37
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKANIMATEDIMAGE_P_H
+#define QQUICKANIMATEDIMAGE_P_H
+
+#include "qquickimage_p.h"
+
+#ifndef QT_NO_MOVIE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+class QQuickAnimatedImagePrivate;
+
+class Q_AUTOTEST_EXPORT QQuickAnimatedImage : public QQuickImage
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
+ Q_PROPERTY(int frameCount READ frameCount)
+
+ // read-only for AnimatedImage
+ Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+
+public:
+ QQuickAnimatedImage(QQuickItem *parent=0);
+ ~QQuickAnimatedImage();
+
+ bool isPlaying() const;
+ void setPlaying(bool play);
+
+ bool isPaused() const;
+ void setPaused(bool pause);
+
+ int currentFrame() const;
+ void setCurrentFrame(int frame);
+
+ int frameCount() const;
+
+ // Extends QQuickImage's src property*/
+ virtual void setSource(const QUrl&);
+
+Q_SIGNALS:
+ void playingChanged();
+ void pausedChanged();
+ void frameChanged();
+ void sourceSizeChanged();
+
+private Q_SLOTS:
+ void movieUpdate();
+ void movieRequestFinished();
+ void playingStatusChanged();
+
+protected:
+ virtual void load();
+ void componentComplete();
+
+private:
+ Q_DISABLE_COPY(QQuickAnimatedImage)
+ Q_DECLARE_PRIVATE(QQuickAnimatedImage)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickAnimatedImage)
+
+QT_END_HEADER
+
+#endif // QT_NO_MOVIE
+
+#endif // QQUICKANIMATEDIMAGE_P_H
diff --git a/src/declarative/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h
index 0d5dd4a3b7..0d5dd4a3b7 100644
--- a/src/declarative/items/qquickanimatedimage_p_p.h
+++ b/src/quick/items/qquickanimatedimage_p_p.h
diff --git a/src/declarative/items/qquickanimation.cpp b/src/quick/items/qquickanimation.cpp
index 55eb4e2e13..55eb4e2e13 100644
--- a/src/declarative/items/qquickanimation.cpp
+++ b/src/quick/items/qquickanimation.cpp
diff --git a/src/quick/items/qquickanimation_p.h b/src/quick/items/qquickanimation_p.h
new file mode 100644
index 0000000000..bf38bd4d9f
--- /dev/null
+++ b/src/quick/items/qquickanimation_p.h
@@ -0,0 +1,207 @@
+// Commit: e39a2e39451bf106a9845f8a60fc571faaa4dde5
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKANIMATION_H
+#define QQUICKANIMATION_H
+
+#include "qquickitem.h"
+
+#include <QtQuick/private/qdeclarativeanimation_p.h>
+
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParentAnimationPrivate;
+class QQuickParentAnimation : public QDeclarativeAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickParentAnimation)
+
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QQuickItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged)
+ Q_PROPERTY(QQuickItem *via READ via WRITE setVia NOTIFY viaChanged)
+
+public:
+ QQuickParentAnimation(QObject *parent=0);
+ virtual ~QQuickParentAnimation();
+
+ QQuickItem *target() const;
+ void setTarget(QQuickItem *);
+
+ QQuickItem *newParent() const;
+ void setNewParent(QQuickItem *);
+
+ QQuickItem *via() const;
+ void setVia(QQuickItem *);
+
+Q_SIGNALS:
+ void targetChanged();
+ void newParentChanged();
+ void viaChanged();
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QQuickAnchorAnimationPrivate;
+class QQuickAnchorAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickAnchorAnimation)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickItem> targets READ targets)
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+
+public:
+ QQuickAnchorAnimation(QObject *parent=0);
+ virtual ~QQuickAnchorAnimation();
+
+ QDeclarativeListProperty<QQuickItem> targets();
+
+ int duration() const;
+ void setDuration(int);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void easingChanged(const QEasingCurve&);
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QQuickItem;
+class QDeclarativePath;
+class QQuickPathAnimationPrivate;
+class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickPathAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged)
+ Q_PROPERTY(qreal orientationEntryInterval READ orientationEntryInterval WRITE setOrientationEntryInterval NOTIFY orientationEntryIntervalChanged)
+ Q_PROPERTY(qreal orientationExitInterval READ orientationExitInterval WRITE setOrientationExitInterval NOTIFY orientationExitIntervalChanged)
+ Q_PROPERTY(qreal endRotation READ endRotation WRITE setEndRotation NOTIFY endRotationChanged)
+
+public:
+ QQuickPathAnimation(QObject *parent=0);
+ virtual ~QQuickPathAnimation();
+
+ enum Orientation {
+ Fixed,
+ RightFirst,
+ LeftFirst,
+ BottomFirst,
+ TopFirst
+ };
+ Q_ENUMS(Orientation)
+
+ int duration() const;
+ void setDuration(int);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *);
+
+ QQuickItem *target() const;
+ void setTarget(QQuickItem *);
+
+ Orientation orientation() const;
+ void setOrientation(Orientation orientation);
+
+ QPointF anchorPoint() const;
+ void setAnchorPoint(const QPointF &point);
+
+ qreal orientationEntryInterval() const;
+ void setOrientationEntryInterval(qreal);
+
+ qreal orientationExitInterval() const;
+ void setOrientationExitInterval(qreal);
+
+ qreal endRotation() const;
+ void setEndRotation(qreal);
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void easingChanged(const QEasingCurve &);
+ void pathChanged();
+ void targetChanged();
+ void orientationChanged(Orientation);
+ void anchorPointChanged(const QPointF &);
+ void orientationEntryIntervalChanged(qreal);
+ void orientationExitIntervalChanged(qreal);
+ void endRotationChanged(qreal);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickParentAnimation)
+QML_DECLARE_TYPE(QQuickAnchorAnimation)
+QML_DECLARE_TYPE(QQuickPathAnimation)
+
+QT_END_HEADER
+
+#endif // QQUICKANIMATION_H
diff --git a/src/declarative/items/qquickanimation_p_p.h b/src/quick/items/qquickanimation_p_p.h
index de2b6d42f9..de2b6d42f9 100644
--- a/src/declarative/items/qquickanimation_p_p.h
+++ b/src/quick/items/qquickanimation_p_p.h
diff --git a/src/declarative/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index e0ffd716aa..e0ffd716aa 100644
--- a/src/declarative/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
new file mode 100644
index 0000000000..936467d580
--- /dev/null
+++ b/src/quick/items/qquickborderimage_p.h
@@ -0,0 +1,108 @@
+// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKBORDERIMAGE_P_H
+#define QQUICKBORDERIMAGE_P_H
+
+#include "qquickimagebase_p.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QQuickScaleGrid;
+class QQuickGridScaledImage;
+class QQuickBorderImagePrivate;
+class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(TileMode)
+
+ Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+ // read-only for BorderImage
+ Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+
+public:
+ QQuickBorderImage(QQuickItem *parent=0);
+ ~QQuickBorderImage();
+
+ QQuickScaleGrid *border();
+
+ enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+
+ TileMode horizontalTileMode() const;
+ void setHorizontalTileMode(TileMode);
+
+ TileMode verticalTileMode() const;
+ void setVerticalTileMode(TileMode);
+
+ void setSource(const QUrl &url);
+
+Q_SIGNALS:
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+ void sourceSizeChanged();
+
+protected:
+ virtual void load();
+ virtual void pixmapChange();
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+private:
+ void setGridScaledImage(const QQuickGridScaledImage& sci);
+
+private Q_SLOTS:
+ void doUpdate();
+ void requestFinished();
+ void sciRequestFinished();
+
+private:
+ Q_DISABLE_COPY(QQuickBorderImage)
+ Q_DECLARE_PRIVATE(QQuickBorderImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QQuickBorderImage)
+QT_END_HEADER
+
+#endif // QQUICKBORDERIMAGE_P_H
diff --git a/src/declarative/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 1875dc082a..1875dc082a 100644
--- a/src/declarative/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp
new file mode 100644
index 0000000000..9c6ab08fc7
--- /dev/null
+++ b/src/quick/items/qquickcanvas.cpp
@@ -0,0 +1,2646 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickcanvas.h"
+#include "qquickcanvas_p.h"
+
+#include "qquickitem.h"
+#include "qquickitem_p.h"
+
+#include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include <private/qsgflashnode_p.h>
+#include <QtQuick/qsgengine.h>
+
+#include <private/qguiapplication_p.h>
+#include <QtGui/QInputPanel>
+
+#include <private/qabstractanimation_p.h>
+
+#include <QtGui/qpainter.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qabstractanimation.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+
+#include <private/qdeclarativedebugtrace_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QQUICK_CANVAS_TIMING
+#ifdef QQUICK_CANVAS_TIMING
+static bool qquick_canvas_timing = !qgetenv("QML_CANVAS_TIMING").isEmpty();
+static QTime threadTimer;
+static int syncTime;
+static int renderTime;
+static int swapTime;
+#endif
+
+DEFINE_BOOL_CONFIG_OPTION(qmlFixedAnimationStep, QML_FIXED_ANIMATION_STEP)
+DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP)
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+void QQuickCanvasPrivate::updateFocusItemTransform()
+{
+ Q_Q(QQuickCanvas);
+ QQuickItem *focus = q->activeFocusItem();
+ if (focus && qApp->inputPanel()->inputItem() == focus)
+ qApp->inputPanel()->setInputItemTransform(QQuickItemPrivate::get(focus)->itemToCanvasTransform());
+}
+
+class QQuickCanvasIncubationController : public QObject, public QDeclarativeIncubationController
+{
+public:
+ QQuickCanvasIncubationController(QQuickCanvasPrivate *canvas)
+ : m_canvas(canvas), m_eventSent(false) {}
+
+protected:
+ virtual bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::User) {
+ Q_ASSERT(m_eventSent);
+
+ bool *amtp = m_canvas->thread->allowMainThreadProcessing();
+ while (incubatingObjectCount()) {
+ if (amtp)
+ incubateWhile(amtp);
+ else
+ incubateFor(5);
+ QCoreApplication::processEvents();
+ }
+
+ m_eventSent = false;
+ }
+ return QObject::event(e);
+ }
+
+ virtual void incubatingObjectCountChanged(int count)
+ {
+ if (count && !m_eventSent) {
+ m_eventSent = true;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+ }
+
+private:
+ QQuickCanvasPrivate *m_canvas;
+ bool m_eventSent;
+};
+
+class QQuickCanvasPlainRenderLoop : public QObject, public QQuickCanvasRenderLoop
+{
+public:
+ QQuickCanvasPlainRenderLoop()
+ : updatePending(false)
+ , animationRunning(false)
+ {
+ }
+
+ virtual void paint() {
+ updatePending = false;
+ if (animationRunning && animationDriver())
+ animationDriver()->advance();
+ polishItems();
+ syncSceneGraph();
+ makeCurrent();
+ glViewport(0, 0, size.width(), size.height());
+ renderSceneGraph(size);
+ swapBuffers();
+
+ if (animationRunning)
+ maybeUpdate();
+ }
+
+ virtual QImage grab() {
+ return qt_gl_read_framebuffer(size, false, false);
+ }
+
+ virtual void startRendering() {
+ if (!glContext()) {
+ createGLContext();
+ makeCurrent();
+ initializeSceneGraph();
+ } else {
+ makeCurrent();
+ }
+ maybeUpdate();
+ }
+
+ virtual void stopRendering() {
+ cleanupNodesOnShutdown();
+ }
+
+ virtual void maybeUpdate() {
+ if (!updatePending) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ updatePending = true;
+ }
+ }
+
+ virtual void animationStarted() {
+ animationRunning = true;
+ maybeUpdate();
+ }
+
+ virtual void animationStopped() {
+ animationRunning = false;
+ }
+
+ virtual bool isRunning() const { return glContext(); } // Event loop is always running...
+ virtual void resize(const QSize &s) { size = s; }
+ virtual void setWindowSize(const QSize &s) { size = s; }
+
+ bool event(QEvent *e) {
+ if (e->type() == QEvent::User) {
+ paint();
+ return true;
+ }
+ return QObject::event(e);
+ }
+
+ QSize size;
+
+ uint updatePending : 1;
+ uint animationRunning : 1;
+};
+
+
+
+/*
+Focus behavior
+==============
+
+Prior to being added to a valid canvas items can set and clear focus with no
+effect. Only once items are added to a canvas (by way of having a parent set that
+already belongs to a canvas) do the focus rules apply. Focus goes back to
+having no effect if an item is removed from a canvas.
+
+When an item is moved into a new focus scope (either being added to a canvas
+for the first time, or having its parent changed), if the focus scope already has
+a scope focused item that takes precedence over the item being added. Otherwise,
+the focus of the added tree is used. In the case of of a tree of items being
+added to a canvas for the first time, which may have a conflicted focus state (two
+or more items in one scope having focus set), the same rule is applied item by item -
+thus the first item that has focus will get it (assuming the scope doesn't already
+have a scope focused item), and the other items will have their focus cleared.
+*/
+
+/*
+ Threaded Rendering
+ ==================
+
+ The threaded rendering uses a number of different variables to track potential
+ states used to handle resizing, initial paint, grabbing and driving animations
+ while ALWAYS keeping the GL context in the rendering thread and keeping the
+ overhead of normal one-shot paints and vblank driven animations at a minimum.
+
+ Resize, initial show and grab suffer slightly in this model as they are locked
+ to the rendering in the rendering thread, but this is a necessary evil for
+ the system to work.
+
+ Variables that are used:
+
+ Private::animationRunning: This is true while the animations are running, and only
+ written to inside locks.
+
+ RenderThread::isGuiBlocked: This is used to indicate that the GUI thread owns the
+ lock. This variable is an integer to allow for recursive calls to lockInGui()
+ without using a recursive mutex. See isGuiBlockPending.
+
+ RenderThread::isPaintComplete: This variable is cleared when rendering starts and
+ set once rendering is complete. It is monitored in the paintEvent(),
+ resizeEvent() and grab() functions to force them to wait for rendering to
+ complete.
+
+ RenderThread::isGuiBlockPending: This variable is set in the render thread just
+ before the sync event is sent to the GUI thread. It is used to avoid deadlocks
+ in the case where render thread waits while waiting for GUI to pick up the sync
+ event and GUI thread gets a resizeEvent, the initial paintEvent or a grab.
+ When this happens, we use the
+ exhaustSyncEvent() function to do the sync right there and mark the coming
+ sync event to be discarded. There can only ever be one sync incoming.
+
+ RenderThread::isRenderBlock: This variable is true when animations are not
+ running and the render thread has gone to sleep, waiting for more to do.
+
+ RenderThread::isExternalUpdatePending: This variable is set to false when
+ a new render pass is started and to true in maybeUpdate(). It is an
+ indication to the render thread that another render pass needs to take
+ place, rather than the render thread going to sleep after completing its swap.
+
+ RenderThread::doGrab: This variable is set by the grab() function and
+ tells the renderer to do a grab after rendering is complete and before
+ swapping happens.
+
+ RenderThread::shouldExit: This variable is used to determine if the render
+ thread should do a nother pass. It is typically set as a result of show()
+ and unset as a result of hide() or during shutdown()
+
+ RenderThread::hasExited: Used by the GUI thread to synchronize the shutdown
+ after shouldExit has been set to true.
+ */
+
+// #define FOCUS_DEBUG
+// #define MOUSE_DEBUG
+// #define TOUCH_DEBUG
+// #define DIRTY_DEBUG
+// #define THREAD_DEBUG
+
+// #define FRAME_TIMING
+
+#ifdef FRAME_TIMING
+static QTime frameTimer;
+int sceneGraphRenderTime;
+int readbackTime;
+#endif
+
+QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
+: transformNode(0)
+{
+}
+
+QQuickRootItem::QQuickRootItem()
+{
+}
+
+void QQuickCanvas::exposeEvent(QExposeEvent *)
+{
+ Q_D(QQuickCanvas);
+ d->thread->paint();
+}
+
+void QQuickCanvas::resizeEvent(QResizeEvent *)
+{
+ Q_D(QQuickCanvas);
+ d->thread->resize(size());
+}
+
+void QQuickCanvas::animationStarted()
+{
+ d_func()->thread->animationStarted();
+}
+
+void QQuickCanvas::animationStopped()
+{
+ d_func()->thread->animationStopped();
+}
+
+void QQuickCanvas::showEvent(QShowEvent *)
+{
+ Q_D(QQuickCanvas);
+ if (d->vsyncAnimations) {
+ if (!d->animationDriver) {
+ d->animationDriver = d->context->createAnimationDriver(this);
+ connect(d->animationDriver, SIGNAL(started()), this, SLOT(animationStarted()), Qt::DirectConnection);
+ connect(d->animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()), Qt::DirectConnection);
+ }
+ d->animationDriver->install();
+ }
+
+ if (!d->thread->isRunning()) {
+ d->thread->setWindowSize(size());
+ d->thread->startRendering();
+ }
+}
+
+void QQuickCanvas::hideEvent(QHideEvent *)
+{
+ Q_D(QQuickCanvas);
+ d->thread->stopRendering();
+}
+
+void QQuickCanvas::focusOutEvent(QFocusEvent *)
+{
+ Q_D(QQuickCanvas);
+ d->rootItem->setFocus(false);
+}
+
+void QQuickCanvas::focusInEvent(QFocusEvent *)
+{
+ Q_D(QQuickCanvas);
+ d->rootItem->setFocus(true);
+}
+
+
+/*!
+ Sets weither this canvas should use vsync driven animations.
+
+ This option can only be set on one single QQuickCanvas, and that it's
+ vsync signal will then be used to drive all animations in the
+ process.
+
+ This feature is primarily useful for single QQuickCanvas, QML-only
+ applications.
+
+ \warning Enabling vsync on multiple QQuickCanvas instances has
+ undefined behavior.
+ */
+void QQuickCanvas::setVSyncAnimations(bool enabled)
+{
+ Q_D(QQuickCanvas);
+ if (visible()) {
+ qWarning("QQuickCanvas::setVSyncAnimations: Cannot be changed when widget is shown");
+ return;
+ }
+ d->vsyncAnimations = enabled;
+}
+
+
+
+/*!
+ Returns true if this canvas should use vsync driven animations;
+ otherwise returns false.
+ */
+bool QQuickCanvas::vsyncAnimations() const
+{
+ Q_D(const QQuickCanvas);
+ return d->vsyncAnimations;
+}
+
+void QQuickCanvasPrivate::initializeSceneGraph()
+{
+ if (!context)
+ context = QSGContext::createDefaultContext();
+
+ if (context->isReady())
+ return;
+
+ QOpenGLContext *glctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ context->initialize(glctx);
+
+ Q_Q(QQuickCanvas);
+
+ if (!QQuickItemPrivate::get(rootItem)->itemNode()->parent()) {
+ context->rootNode()->appendChildNode(QQuickItemPrivate::get(rootItem)->itemNode());
+ }
+
+ engine = new QSGEngine();
+ engine->setCanvas(q);
+
+ emit q_func()->sceneGraphInitialized();
+}
+
+void QQuickCanvasPrivate::polishItems()
+{
+ while (!itemsToPolish.isEmpty()) {
+ QSet<QQuickItem *>::Iterator iter = itemsToPolish.begin();
+ QQuickItem *item = *iter;
+ itemsToPolish.erase(iter);
+ QQuickItemPrivate::get(item)->polishScheduled = false;
+ item->updatePolish();
+ }
+ updateFocusItemTransform();
+}
+
+
+void QQuickCanvasPrivate::syncSceneGraph()
+{
+ updateDirtyNodes();
+
+ // Copy the current state of clearing from canvas into renderer.
+ context->renderer()->setClearColor(clearColor);
+ QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
+ if (clearBeforeRendering)
+ mode |= QSGRenderer::ClearColorBuffer;
+ context->renderer()->setClearMode(mode);
+}
+
+
+void QQuickCanvasPrivate::renderSceneGraph(const QSize &size)
+{
+ Q_Q(QQuickCanvas);
+ context->renderer()->setDeviceRect(QRect(QPoint(0, 0), size));
+ context->renderer()->setViewportRect(QRect(QPoint(0, 0), renderTarget ? renderTarget->size() : size));
+ context->renderer()->setProjectionMatrixToDeviceRect();
+
+ emit q->beforeRendering();
+ context->renderNextFrame(renderTarget);
+ emit q->afterRendering();
+
+#ifdef FRAME_TIMING
+ sceneGraphRenderTime = frameTimer.elapsed();
+#endif
+
+#ifdef FRAME_TIMING
+// int pixel;
+// glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+ readbackTime = frameTimer.elapsed();
+#endif
+}
+
+
+QQuickCanvasPrivate::QQuickCanvasPrivate()
+ : rootItem(0)
+ , activeFocusItem(0)
+ , mouseGrabberItem(0)
+ , dirtyItemList(0)
+ , context(0)
+ , clearColor(Qt::white)
+ , vsyncAnimations(false)
+ , clearBeforeRendering(true)
+ , thread(0)
+ , animationDriver(0)
+ , renderTarget(0)
+ , incubationController(0)
+{
+}
+
+QQuickCanvasPrivate::~QQuickCanvasPrivate()
+{
+}
+
+void QQuickCanvasPrivate::init(QQuickCanvas *c)
+{
+ QUnifiedTimer* ut = QUnifiedTimer::instance(true);
+ if (qmlFixedAnimationStep())
+ ut->setConsistentTiming(true);
+
+ q_ptr = c;
+
+ Q_Q(QQuickCanvas);
+
+ rootItem = new QQuickRootItem;
+ QQuickItemPrivate *rootItemPrivate = QQuickItemPrivate::get(rootItem);
+ rootItemPrivate->canvas = q;
+ rootItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
+
+ // In the absence of a focus in event on some platforms assume the window will
+ // be activated immediately and set focus on the rootItem
+ // ### Remove when QTBUG-22415 is resolved.
+ //It is important that this call happens after the rootItem has a canvas..
+ rootItem->setFocus(true);
+
+ bool threaded = !qmlNoThreadedRenderer();
+
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)) {
+ qWarning("QQuickCanvas: platform does not support threaded rendering!");
+ threaded = false;
+ }
+
+ if (threaded)
+ thread = new QQuickCanvasRenderThread();
+ else
+ thread = new QQuickCanvasPlainRenderLoop();
+
+ thread->renderer = q;
+ thread->d = this;
+
+ context = QSGContext::createDefaultContext();
+ thread->moveContextToThread(context);
+
+ q->setSurfaceType(QWindow::OpenGLSurface);
+ q->setFormat(context->defaultSurfaceFormat());
+}
+
+QDeclarativeListProperty<QObject> QQuickCanvasPrivate::data()
+{
+ initRootItem();
+ return QQuickItemPrivate::get(rootItem)->data();
+}
+
+void QQuickCanvasPrivate::initRootItem()
+{
+ Q_Q(QQuickCanvas);
+ q->connect(q, SIGNAL(widthChanged(int)),
+ rootItem, SLOT(setWidth(int)));
+ q->connect(q, SIGNAL(heightChanged(int)),
+ rootItem, SLOT(setHeight(int)));
+ rootItem->setWidth(q->width());
+ rootItem->setHeight(q->height());
+}
+
+void QQuickCanvasPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
+{
+ for (int i=0; i<touchPoints.count(); i++) {
+ QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+ touchPoint.setRect(transform.mapRect(touchPoint.sceneRect()));
+ touchPoint.setStartPos(transform.map(touchPoint.startScenePos()));
+ touchPoint.setLastPos(transform.map(touchPoint.lastScenePos()));
+ }
+}
+
+
+/*!
+Translates the data in \a touchEvent to this canvas. This method leaves the item local positions in
+\a touchEvent untouched (these are filled in later).
+*/
+void QQuickCanvasPrivate::translateTouchEvent(QTouchEvent *touchEvent)
+{
+// Q_Q(QQuickCanvas);
+
+// touchEvent->setWidget(q); // ### refactor...
+
+ QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+
+ touchPoint.setScreenRect(touchPoint.sceneRect());
+ touchPoint.setStartScreenPos(touchPoint.startScenePos());
+ touchPoint.setLastScreenPos(touchPoint.lastScenePos());
+
+ touchPoint.setSceneRect(touchPoint.rect());
+ touchPoint.setStartScenePos(touchPoint.startPos());
+ touchPoint.setLastScenePos(touchPoint.lastPos());
+
+ if (touchPoint.isPrimary())
+ lastMousePosition = touchPoint.pos().toPoint();
+ }
+ touchEvent->setTouchPoints(touchPoints);
+}
+
+void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+{
+ Q_Q(QQuickCanvas);
+
+ Q_ASSERT(item);
+ Q_ASSERT(scope || item == rootItem);
+
+#ifdef FOCUS_DEBUG
+ qWarning() << "QQuickCanvasPrivate::setFocusInScope():";
+ qWarning() << " scope:" << (QObject *)scope;
+ if (scope)
+ qWarning() << " scopeSubFocusItem:" << (QObject *)QQuickItemPrivate::get(scope)->subFocusItem;
+ qWarning() << " item:" << (QObject *)item;
+ qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
+#endif
+
+ QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ QQuickItem *oldActiveFocusItem = 0;
+ QQuickItem *newActiveFocusItem = 0;
+
+ QVarLengthArray<QQuickItem *, 20> changed;
+
+ // Does this change the active focus?
+ if (item == rootItem || scopePrivate->activeFocus) {
+ oldActiveFocusItem = activeFocusItem;
+ newActiveFocusItem = item;
+ while (newActiveFocusItem->isFocusScope() && newActiveFocusItem->scopedFocusItem())
+ newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
+
+ if (oldActiveFocusItem) {
+#ifndef QT_NO_IM
+ qApp->inputPanel()->commit();
+#endif
+
+ activeFocusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+ q->sendEvent(oldActiveFocusItem, &event);
+
+ QQuickItem *afi = oldActiveFocusItem;
+ while (afi != scope) {
+ if (QQuickItemPrivate::get(afi)->activeFocus) {
+ QQuickItemPrivate::get(afi)->activeFocus = false;
+ changed << afi;
+ }
+ afi = afi->parentItem();
+ }
+ }
+ }
+
+ if (item != rootItem) {
+ 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;
+ }
+ }
+
+ if (!(options & DontChangeFocusProperty)) {
+// if (item != rootItem || QGuiApplication::focusWindow() == q) { // QTBUG-22415
+ itemPrivate->focus = true;
+ changed << item;
+// }
+ }
+
+ if (newActiveFocusItem && rootItem->hasFocus()) {
+ activeFocusItem = newActiveFocusItem;
+
+ QQuickItemPrivate::get(newActiveFocusItem)->activeFocus = true;
+ changed << newActiveFocusItem;
+
+ QQuickItem *afi = newActiveFocusItem->parentItem();
+ while (afi && afi != scope) {
+ if (afi->isFocusScope()) {
+ QQuickItemPrivate::get(afi)->activeFocus = true;
+ changed << afi;
+ }
+ afi = afi->parentItem();
+ }
+
+ updateInputMethodData();
+
+ QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+ q->sendEvent(newActiveFocusItem, &event);
+ } else {
+ updateInputMethodData();
+ }
+
+ if (!changed.isEmpty())
+ notifyFocusChangesRecur(changed.data(), changed.count() - 1);
+}
+
+void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+{
+ Q_Q(QQuickCanvas);
+
+ Q_UNUSED(item);
+ Q_ASSERT(item);
+ Q_ASSERT(scope || item == rootItem);
+
+#ifdef FOCUS_DEBUG
+ qWarning() << "QQuickCanvasPrivate::clearFocusInScope():";
+ qWarning() << " scope:" << (QObject *)scope;
+ qWarning() << " item:" << (QObject *)item;
+ qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
+#endif
+
+ QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
+
+ QQuickItem *oldActiveFocusItem = 0;
+ QQuickItem *newActiveFocusItem = 0;
+
+ QVarLengthArray<QQuickItem *, 20> changed;
+
+ Q_ASSERT(item == rootItem || item == scopePrivate->subFocusItem);
+
+ // Does this change the active focus?
+ if (item == rootItem || scopePrivate->activeFocus) {
+ oldActiveFocusItem = activeFocusItem;
+ newActiveFocusItem = scope;
+
+ Q_ASSERT(oldActiveFocusItem);
+
+#ifndef QT_NO_IM
+ qApp->inputPanel()->commit();
+#endif
+
+ activeFocusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+ q->sendEvent(oldActiveFocusItem, &event);
+
+ QQuickItem *afi = oldActiveFocusItem;
+ while (afi != scope) {
+ if (QQuickItemPrivate::get(afi)->activeFocus) {
+ QQuickItemPrivate::get(afi)->activeFocus = false;
+ changed << afi;
+ }
+ afi = afi->parentItem();
+ }
+ }
+
+ if (item != rootItem) {
+ 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;
+ }
+ } else if (!(options & DontChangeFocusProperty)) {
+ QQuickItemPrivate::get(item)->focus = false;
+ changed << item;
+ }
+
+ if (newActiveFocusItem) {
+ Q_ASSERT(newActiveFocusItem == scope);
+ activeFocusItem = scope;
+
+ updateInputMethodData();
+
+ QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+ q->sendEvent(newActiveFocusItem, &event);
+ } else {
+ updateInputMethodData();
+ }
+
+ if (!changed.isEmpty())
+ notifyFocusChangesRecur(changed.data(), changed.count() - 1);
+}
+
+void QQuickCanvasPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining)
+{
+ QDeclarativeGuard<QQuickItem> item(*items);
+
+ if (remaining)
+ notifyFocusChangesRecur(items + 1, remaining - 1);
+
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ if (itemPrivate->notifiedFocus != itemPrivate->focus) {
+ itemPrivate->notifiedFocus = itemPrivate->focus;
+ emit item->focusChanged(itemPrivate->focus);
+ }
+
+ if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
+ itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
+ itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
+ emit item->activeFocusChanged(itemPrivate->activeFocus);
+ }
+ }
+}
+
+void QQuickCanvasPrivate::updateInputMethodData()
+{
+ QQuickItem *inputItem = 0;
+ if (activeFocusItem && activeFocusItem->flags() & QQuickItem::ItemAcceptsInputMethod)
+ inputItem = activeFocusItem;
+ qApp->inputPanel()->setInputItem(inputItem);
+}
+
+void QQuickCanvasPrivate::dirtyItem(QQuickItem *)
+{
+ Q_Q(QQuickCanvas);
+ q->maybeUpdate();
+}
+
+void QQuickCanvasPrivate::cleanup(QSGNode *n)
+{
+ Q_Q(QQuickCanvas);
+
+ Q_ASSERT(!cleanupNodeList.contains(n));
+ cleanupNodeList.append(n);
+ q->maybeUpdate();
+}
+
+
+/*!
+ \qmlclass Window QQuickCanvas
+ \inqmlmodule QtQuick.Window 2
+ \brief The Window object creates a new top-level window.
+
+ The Window object creates a new top-level window for a QtQuick scene. It automatically sets up the
+ window for use with QtQuick 2.0 graphical elements.
+*/
+/*!
+ \class QQuickCanvas
+ \since QtQuick 2.0
+ \brief The QQuickCanvas class provides the canvas for displaying a graphical QML scene
+
+ \inmodule QtQuick
+
+ QQuickCanvas provides the graphical scene management needed to interact with and display
+ a scene of QQuickItems.
+
+ A QQuickCanvas always has a single invisible root item. To add items to this canvas,
+ 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}.
+*/
+QQuickCanvas::QQuickCanvas(QWindow *parent)
+ : QWindow(*(new QQuickCanvasPrivate), parent)
+{
+ Q_D(QQuickCanvas);
+ d->init(this);
+}
+
+QQuickCanvas::QQuickCanvas(QQuickCanvasPrivate &dd, QWindow *parent)
+ : QWindow(dd, parent)
+{
+ Q_D(QQuickCanvas);
+ d->init(this);
+}
+
+QQuickCanvas::~QQuickCanvas()
+{
+ Q_D(QQuickCanvas);
+
+ if (d->thread->isRunning())
+ d->thread->stopRendering();
+
+ // ### 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();
+
+ delete d->incubationController; d->incubationController = 0;
+
+ delete d->rootItem; d->rootItem = 0;
+
+ delete d->thread; d->thread = 0;
+}
+
+/*!
+ Returns the invisible root item of the scene.
+
+ A QQuickCanvas always has a single invisible root item. To add items to this canvas,
+ reparent the items to the root item or to an existing item in the scene.
+*/
+QQuickItem *QQuickCanvas::rootItem() const
+{
+ Q_D(const QQuickCanvas);
+
+ return d->rootItem;
+}
+
+/*!
+ Returns the item which currently has active focus.
+*/
+QQuickItem *QQuickCanvas::activeFocusItem() const
+{
+ Q_D(const QQuickCanvas);
+
+ return d->activeFocusItem;
+}
+
+/*!
+ Returns the item which currently has the mouse grab.
+*/
+QQuickItem *QQuickCanvas::mouseGrabberItem() const
+{
+ Q_D(const QQuickCanvas);
+
+ return d->mouseGrabberItem;
+}
+
+
+/*!
+ \qmlproperty color QtQuick2.Window::Window::color
+
+ The background color for the window.
+
+ Setting this property is more efficient than using a separate Rectangle.
+*/
+
+bool QQuickCanvasPrivate::clearHover()
+{
+ if (hoverItems.isEmpty())
+ return false;
+
+ QPointF pos = QCursor::pos(); // ### refactor: q->mapFromGlobal(QCursor::pos());
+
+ bool accepted = false;
+ foreach (QQuickItem* item, hoverItems)
+ accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
+ hoverItems.clear();
+ return accepted;
+}
+
+
+bool QQuickCanvas::event(QEvent *e)
+{
+ Q_D(QQuickCanvas);
+
+ switch (e->type()) {
+
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ QTouchEvent *touch = static_cast<QTouchEvent *>(e);
+ d->translateTouchEvent(touch);
+ d->deliverTouchEvent(touch);
+ if (!touch->isAccepted())
+ return false;
+ break;
+ }
+ case QEvent::Leave:
+ d->clearHover();
+ d->lastMousePosition = QPoint();
+ break;
+ case QEvent::DragEnter:
+ case QEvent::DragLeave:
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ d->deliverDragEvent(&d->dragGrabber, e);
+ break;
+ case QEvent::WindowDeactivate:
+ rootItem()->windowDeactivateEvent();
+ break;
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void QQuickCanvas::keyPressEvent(QKeyEvent *e)
+{
+ Q_D(QQuickCanvas);
+
+ if (d->activeFocusItem)
+ sendEvent(d->activeFocusItem, e);
+}
+
+void QQuickCanvas::keyReleaseEvent(QKeyEvent *e)
+{
+ Q_D(QQuickCanvas);
+
+ if (d->activeFocusItem)
+ sendEvent(d->activeFocusItem, e);
+}
+
+bool QQuickCanvasPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouseEvent *event)
+{
+ Q_Q(QQuickCanvas);
+
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (itemPrivate->opacity == 0.0)
+ return false;
+
+ if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
+ QPointF p = item->mapFromScene(event->windowPos());
+ if (!QRectF(0, 0, item->width(), item->height()).contains(p))
+ return false;
+ }
+
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QQuickItem *child = children.at(ii);
+ if (!child->isVisible() || !child->isEnabled())
+ continue;
+ if (deliverInitialMousePressEvent(child, event))
+ return true;
+ }
+
+ if (itemPrivate->acceptedMouseButtons & event->button()) {
+ QPointF p = item->mapFromScene(event->windowPos());
+ if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
+ QMouseEvent me(event->type(), p, event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ me.accept();
+ mouseGrabberItem = item;
+ q->sendEvent(item, &me);
+ event->setAccepted(me.isAccepted());
+ if (me.isAccepted())
+ return true;
+ mouseGrabberItem->ungrabMouse();
+ mouseGrabberItem = 0;
+ }
+ }
+
+ return false;
+}
+
+bool QQuickCanvasPrivate::deliverMouseEvent(QMouseEvent *event)
+{
+ Q_Q(QQuickCanvas);
+
+ lastMousePosition = event->windowPos();
+
+ if (!mouseGrabberItem &&
+ event->type() == QEvent::MouseButtonPress &&
+ (event->button() & event->buttons()) == event->buttons()) {
+ return deliverInitialMousePressEvent(rootItem, event);
+ }
+
+ if (mouseGrabberItem) {
+ QQuickItemPrivate *mgPrivate = QQuickItemPrivate::get(mouseGrabberItem);
+ const QTransform &transform = mgPrivate->canvasToItemTransform();
+ QMouseEvent me(event->type(), transform.map(event->windowPos()), event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ me.accept();
+ q->sendEvent(mouseGrabberItem, &me);
+ event->setAccepted(me.isAccepted());
+ if (me.isAccepted())
+ return true;
+ }
+
+ return false;
+}
+
+void QQuickCanvas::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickCanvas);
+
+#ifdef MOUSE_DEBUG
+ qWarning() << "QQuickCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons();
+#endif
+
+ d->deliverMouseEvent(event);
+}
+
+void QQuickCanvas::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickCanvas);
+
+#ifdef MOUSE_DEBUG
+ qWarning() << "QQuickCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons();
+#endif
+
+ if (!d->mouseGrabberItem) {
+ QWindow::mouseReleaseEvent(event);
+ return;
+ }
+
+ d->deliverMouseEvent(event);
+ d->mouseGrabberItem = 0;
+}
+
+void QQuickCanvas::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QQuickCanvas);
+
+#ifdef MOUSE_DEBUG
+ qWarning() << "QQuickCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons();
+#endif
+
+ if (!d->mouseGrabberItem && (event->button() & event->buttons()) == event->buttons()) {
+ if (d->deliverInitialMousePressEvent(d->rootItem, event))
+ event->accept();
+ else
+ event->ignore();
+ return;
+ }
+
+ d->deliverMouseEvent(event);
+}
+
+bool QQuickCanvasPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
+ const QPointF &scenePos, const QPointF &lastScenePos,
+ Qt::KeyboardModifiers modifiers, bool accepted)
+{
+ Q_Q(QQuickCanvas);
+ const QTransform transform = QQuickItemPrivate::get(item)->canvasToItemTransform();
+
+ //create copy of event
+ QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
+ hoverEvent.setAccepted(accepted);
+
+ q->sendEvent(item, &hoverEvent);
+
+ return hoverEvent.isAccepted();
+}
+
+void QQuickCanvas::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickCanvas);
+
+#ifdef MOUSE_DEBUG
+ qWarning() << "QQuickCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons();
+#endif
+
+ if (!d->mouseGrabberItem) {
+ if (d->lastMousePosition.isNull())
+ d->lastMousePosition = event->windowPos();
+ QPointF last = d->lastMousePosition;
+ d->lastMousePosition = event->windowPos();
+
+ bool accepted = event->isAccepted();
+ bool delivered = d->deliverHoverEvent(d->rootItem, event->windowPos(), last, event->modifiers(), accepted);
+ if (!delivered) {
+ //take care of any exits
+ accepted = d->clearHover();
+ }
+ event->setAccepted(accepted);
+ return;
+ }
+
+ d->deliverMouseEvent(event);
+}
+
+bool QQuickCanvasPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
+ Qt::KeyboardModifiers modifiers, bool &accepted)
+{
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (itemPrivate->opacity == 0.0)
+ return false;
+
+ if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
+ QPointF p = item->mapFromScene(scenePos);
+ if (!QRectF(0, 0, item->width(), item->height()).contains(p))
+ return false;
+ }
+
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QQuickItem *child = children.at(ii);
+ if (!child->isVisible() || !child->isEnabled())
+ continue;
+ if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
+ return true;
+ }
+
+ if (itemPrivate->hoverEnabled) {
+ QPointF p = item->mapFromScene(scenePos);
+ if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
+ if (!hoverItems.isEmpty() && hoverItems[0] == item) {
+ //move
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ } else {
+ QList<QQuickItem *> itemsToHover;
+ QQuickItem* parent = item;
+ itemsToHover << item;
+ while ((parent = parent->parentItem()))
+ itemsToHover << parent;
+
+ // Leaving from previous hovered items until we reach the item or one of its ancestors.
+ while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
+ sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
+ hoverItems.removeFirst();
+ }
+
+ if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
+ // ### Shouldn't we send moves for the parent items as well?
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ } else {
+ // Enter items that are not entered yet.
+ int startIdx = -1;
+ if (!hoverItems.isEmpty())
+ startIdx = itemsToHover.indexOf(hoverItems[0]) - 1;
+ if (startIdx == -1)
+ startIdx = itemsToHover.count() - 1;
+
+ for (int i = startIdx; i >= 0; i--) {
+ QQuickItem *itemToHover = itemsToHover[i];
+ if (QQuickItemPrivate::get(itemToHover)->hoverEnabled) {
+ hoverItems.prepend(itemToHover);
+ sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QQuickCanvasPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
+{
+ Q_Q(QQuickCanvas);
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (itemPrivate->opacity == 0.0)
+ return false;
+
+ if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
+ QPointF p = item->mapFromScene(event->posF());
+ if (!QRectF(0, 0, item->width(), item->height()).contains(p))
+ return false;
+ }
+
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QQuickItem *child = children.at(ii);
+ if (!child->isVisible() || !child->isEnabled())
+ continue;
+ if (deliverWheelEvent(child, event))
+ return true;
+ }
+
+ QPointF p = item->mapFromScene(event->posF());
+ if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
+ QWheelEvent wheel(p, event->delta(), event->buttons(), event->modifiers(), event->orientation());
+ wheel.accept();
+ q->sendEvent(item, &wheel);
+ if (wheel.isAccepted()) {
+ event->accept();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QQuickCanvas::wheelEvent(QWheelEvent *event)
+{
+ Q_D(QQuickCanvas);
+#ifdef MOUSE_DEBUG
+ qWarning() << "QQuickCanvas::wheelEvent()" << event->pos() << event->delta() << event->orientation();
+#endif
+ event->ignore();
+ d->deliverWheelEvent(d->rootItem, event);
+}
+#endif // QT_NO_WHEELEVENT
+
+bool QQuickCanvasPrivate::deliverTouchEvent(QTouchEvent *event)
+{
+#ifdef TOUCH_DEBUG
+ if (event->type() == QEvent::TouchBegin)
+ qWarning("touchBeginEvent");
+ else if (event->type() == QEvent::TouchUpdate)
+ qWarning("touchUpdateEvent");
+ else if (event->type() == QEvent::TouchEnd)
+ qWarning("touchEndEvent");
+#endif
+
+ QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
+
+ if (event->type() == QTouchEvent::TouchBegin) { // all points are new touch points
+ QSet<int> acceptedNewPoints;
+ deliverTouchPoints(rootItem, event, event->touchPoints(), &acceptedNewPoints, &updatedPoints);
+ if (acceptedNewPoints.count() > 0)
+ event->accept();
+ return event->isAccepted();
+ }
+
+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
+ QList<QTouchEvent::TouchPoint> newPoints;
+ QQuickItem *item = 0;
+ for (int i=0; i<touchPoints.count(); i++) {
+ const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+ switch (touchPoint.state()) {
+ case Qt::TouchPointPressed:
+ newPoints << touchPoint;
+ break;
+ case Qt::TouchPointMoved:
+ case Qt::TouchPointStationary:
+ case Qt::TouchPointReleased:
+ if (itemForTouchPointId.contains(touchPoint.id())) {
+ item = itemForTouchPointId[touchPoint.id()];
+ if (item)
+ updatedPoints[item].append(touchPoint);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (newPoints.count() > 0 || updatedPoints.count() > 0) {
+ QSet<int> acceptedNewPoints;
+ int prevCount = updatedPoints.count();
+ deliverTouchPoints(rootItem, event, newPoints, &acceptedNewPoints, &updatedPoints);
+ if (acceptedNewPoints.count() > 0 || updatedPoints.count() != prevCount)
+ event->accept();
+ }
+
+ if (event->touchPointStates() & Qt::TouchPointReleased) {
+ for (int i=0; i<touchPoints.count(); i++) {
+ if (touchPoints[i].state() == Qt::TouchPointReleased)
+ itemForTouchPointId.remove(touchPoints[i].id());
+ }
+ }
+
+ return event->isAccepted();
+}
+
+bool QQuickCanvasPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints, QSet<int> *acceptedNewPoints, QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *updatedPoints)
+{
+ Q_Q(QQuickCanvas);
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ if (itemPrivate->opacity == 0.0)
+ return false;
+
+ if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
+ QRectF bounds(0, 0, item->width(), item->height());
+ for (int i=0; i<newPoints.count(); i++) {
+ QPointF p = item->mapFromScene(newPoints[i].scenePos());
+ if (!bounds.contains(p))
+ return false;
+ }
+ }
+
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ QQuickItem *child = children.at(ii);
+ if (!child->isEnabled())
+ continue;
+ if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints))
+ return true;
+ }
+
+ QList<QTouchEvent::TouchPoint> matchingPoints;
+ if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
+ QRectF bounds(0, 0, item->width(), item->height());
+ for (int i=0; i<newPoints.count(); i++) {
+ if (acceptedNewPoints->contains(newPoints[i].id()))
+ continue;
+ QPointF p = item->mapFromScene(newPoints[i].scenePos());
+ if (bounds.contains(p))
+ matchingPoints << newPoints[i];
+ }
+ }
+
+ if (matchingPoints.count() > 0 || (*updatedPoints)[item].count() > 0) {
+ QList<QTouchEvent::TouchPoint> &eventPoints = (*updatedPoints)[item];
+ eventPoints.append(matchingPoints);
+ transformTouchPoints(eventPoints, itemPrivate->canvasToItemTransform());
+
+ Qt::TouchPointStates eventStates;
+ for (int i=0; i<eventPoints.count(); i++)
+ eventStates |= eventPoints[i].state();
+ // if all points have the same state, set the event type accordingly
+ QEvent::Type eventType;
+ switch (eventStates) {
+ case Qt::TouchPointPressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ eventType = QEvent::TouchEnd;
+ break;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ if (eventStates != Qt::TouchPointStationary) {
+ QTouchEvent touchEvent(eventType);
+ // touchEvent.setWidget(q); // ### refactor: what is the consequence of not setting the widget?
+ touchEvent.setDeviceType(event->deviceType());
+ touchEvent.setModifiers(event->modifiers());
+ touchEvent.setTouchPointStates(eventStates);
+ touchEvent.setTouchPoints(eventPoints);
+ touchEvent.setTimestamp(event->timestamp());
+
+ touchEvent.accept();
+ q->sendEvent(item, &touchEvent);
+
+ if (touchEvent.isAccepted()) {
+ for (int i=0; i<matchingPoints.count(); i++) {
+ itemForTouchPointId[matchingPoints[i].id()] = item;
+ acceptedNewPoints->insert(matchingPoints[i].id());
+ }
+ }
+ }
+ }
+
+ updatedPoints->remove(item);
+ if (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty())
+ return true;
+
+ return false;
+}
+
+void QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
+{
+ Q_Q(QQuickCanvas);
+ grabber->resetTarget();
+ QQuickDragGrabber::iterator grabItem = grabber->begin();
+ if (grabItem != grabber->end()) {
+ Q_ASSERT(event->type() != QEvent::DragEnter);
+ if (event->type() == QEvent::Drop) {
+ QDropEvent *e = static_cast<QDropEvent *>(event);
+ for (e->setAccepted(false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
+ QPointF p = (**grabItem)->mapFromScene(e->pos());
+ QDropEvent translatedEvent(
+ p.toPoint(),
+ e->possibleActions(),
+ e->mimeData(),
+ e->mouseButtons(),
+ e->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&translatedEvent, *e);
+ q->sendEvent(**grabItem, &translatedEvent);
+ e->setAccepted(translatedEvent.isAccepted());
+ e->setDropAction(translatedEvent.dropAction());
+ grabber->setTarget(**grabItem);
+ }
+ }
+ if (event->type() != QEvent::DragMove) { // Either an accepted drop or a leave.
+ QDragLeaveEvent leaveEvent;
+ for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
+ q->sendEvent(**grabItem, &leaveEvent);
+ return;
+ } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
+ QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
+ if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
+ moveEvent->setAccepted(true);
+ for (++grabItem; grabItem != grabber->end();) {
+ QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
+ if (QRectF(0, 0, (**grabItem)->width(), (**grabItem)->height()).contains(p)) {
+ QDragMoveEvent translatedEvent(
+ p.toPoint(),
+ moveEvent->possibleActions(),
+ moveEvent->mimeData(),
+ moveEvent->mouseButtons(),
+ moveEvent->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
+ q->sendEvent(**grabItem, &translatedEvent);
+ ++grabItem;
+ } else {
+ QDragLeaveEvent leaveEvent;
+ q->sendEvent(**grabItem, &leaveEvent);
+ grabItem = grabber->release(grabItem);
+ }
+ }
+ return;
+ } else {
+ QDragLeaveEvent leaveEvent;
+ q->sendEvent(**grabItem, &leaveEvent);
+ }
+ }
+ }
+ if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
+ QDragMoveEvent *e = static_cast<QDragMoveEvent *>(event);
+ QDragEnterEvent enterEvent(
+ e->pos(),
+ e->possibleActions(),
+ e->mimeData(),
+ e->mouseButtons(),
+ e->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&enterEvent, *e);
+ event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
+ }
+}
+
+bool QQuickCanvasPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
+{
+ Q_Q(QQuickCanvas);
+ bool accepted = false;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (itemPrivate->opacity == 0.0 || !item->isVisible() || !item->isEnabled())
+ return false;
+
+ QPointF p = item->mapFromScene(event->pos());
+ if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
+ if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
+ QDragMoveEvent translatedEvent(
+ p.toPoint(),
+ event->possibleActions(),
+ event->mimeData(),
+ event->mouseButtons(),
+ event->keyboardModifiers(),
+ event->type());
+ QQuickDropEventEx::copyActions(&translatedEvent, *event);
+ q->sendEvent(item, &translatedEvent);
+ if (event->type() == QEvent::DragEnter) {
+ if (translatedEvent.isAccepted()) {
+ grabber->grab(item);
+ accepted = true;
+ }
+ } else {
+ accepted = true;
+ }
+ }
+ } else if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
+ return false;
+ }
+
+ QDragEnterEvent enterEvent(
+ event->pos(),
+ event->possibleActions(),
+ event->mimeData(),
+ event->mouseButtons(),
+ event->keyboardModifiers());
+ QQuickDropEventEx::copyActions(&enterEvent, *event);
+ QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
+ return true;
+ }
+
+ return accepted;
+}
+
+bool QQuickCanvasPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
+{
+ if (!target)
+ return false;
+
+ QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
+ if (targetPrivate->filtersChildMouseEvents)
+ if (target->childMouseEventFilter(item, event))
+ return true;
+
+ if (sendFilteredMouseEvent(target->parentItem(), item, event))
+ return true;
+
+ return false;
+}
+
+/*!
+ Propagates an event to a QQuickItem on the canvas
+*/
+bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
+{
+ Q_D(QQuickCanvas);
+
+ if (!item) {
+ qWarning("QQuickCanvas::sendEvent: Cannot send event to a null item");
+ return false;
+ }
+
+ Q_ASSERT(e);
+
+ switch (e->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
+ while (!e->isAccepted() && (item = item->parentItem())) {
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
+ }
+ break;
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ QQuickItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e));
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
+ if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e));
+ }
+ break;
+ case QEvent::Wheel:
+ QQuickItemPrivate::get(item)->deliverWheelEvent(static_cast<QWheelEvent *>(e));
+ break;
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ case QEvent::HoverMove:
+ QQuickItemPrivate::get(item)->deliverHoverEvent(static_cast<QHoverEvent *>(e));
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
+ if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
+ e->accept();
+ QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
+ }
+ break;
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::DragLeave:
+ case QEvent::Drop:
+ QQuickItemPrivate::get(item)->deliverDragEvent(e);
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void QQuickCanvasPrivate::cleanupNodes()
+{
+ for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
+ delete cleanupNodeList.at(ii);
+ cleanupNodeList.clear();
+}
+
+void QQuickCanvasPrivate::cleanupNodesOnShutdown(QQuickItem *item)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (p->itemNodeInstance) {
+ delete p->itemNodeInstance;
+ p->itemNodeInstance = 0;
+ p->opacityNode = 0;
+ p->clipNode = 0;
+ p->groupNode = 0;
+ p->paintNode = 0;
+ }
+
+ for (int ii = 0; ii < p->childItems.count(); ++ii)
+ cleanupNodesOnShutdown(p->childItems.at(ii));
+}
+
+// This must be called from the render thread, with the main thread frozen
+void QQuickCanvasPrivate::cleanupNodesOnShutdown()
+{
+ cleanupNodes();
+
+ cleanupNodesOnShutdown(rootItem);
+}
+
+void QQuickCanvasPrivate::updateDirtyNodes()
+{
+#ifdef DIRTY_DEBUG
+ qWarning() << "QQuickCanvasPrivate::updateDirtyNodes():";
+#endif
+
+ cleanupNodes();
+
+ QQuickItem *updateList = dirtyItemList;
+ dirtyItemList = 0;
+ if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
+
+ while (updateList) {
+ QQuickItem *item = updateList;
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
+ itemPriv->removeFromDirtyList();
+
+#ifdef DIRTY_DEBUG
+ qWarning() << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
+#endif
+ updateDirtyNode(item);
+ }
+}
+
+void QQuickCanvasPrivate::updateDirtyNode(QQuickItem *item)
+{
+#ifdef QML_RUNTIME_TESTING
+ bool didFlash = false;
+#endif
+
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
+ quint32 dirty = itemPriv->dirtyAttributes;
+ itemPriv->dirtyAttributes = 0;
+
+ if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
+ (dirty & QQuickItemPrivate::Size && itemPriv->origin != QQuickItem::TopLeft &&
+ (itemPriv->scale != 1. || itemPriv->rotation != 0.))) {
+
+ QMatrix4x4 matrix;
+
+ if (itemPriv->x != 0. || itemPriv->y != 0.)
+ matrix.translate(itemPriv->x, itemPriv->y);
+
+ for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
+ itemPriv->transforms.at(ii)->applyTo(&matrix);
+
+ if (itemPriv->scale != 1. || itemPriv->rotation != 0.) {
+ QPointF origin = item->transformOriginPoint();
+ matrix.translate(origin.x(), origin.y());
+ if (itemPriv->scale != 1.)
+ matrix.scale(itemPriv->scale, itemPriv->scale);
+ if (itemPriv->rotation != 0.)
+ matrix.rotate(itemPriv->rotation, 0, 0, 1);
+ matrix.translate(-origin.x(), -origin.y());
+ }
+
+ itemPriv->itemNode()->setMatrix(matrix);
+ }
+
+ bool clipEffectivelyChanged = dirty & QQuickItemPrivate::Clip &&
+ ((item->clip() == false) != (itemPriv->clipNode == 0));
+ bool effectRefEffectivelyChanged = dirty & QQuickItemPrivate::EffectReference &&
+ ((itemPriv->effectRefCount == 0) != (itemPriv->rootNode == 0));
+
+ if (clipEffectivelyChanged) {
+ QSGNode *parent = itemPriv->opacityNode ? (QSGNode *) itemPriv->opacityNode : (QSGNode *)itemPriv->itemNode();
+ QSGNode *child = itemPriv->rootNode ? (QSGNode *)itemPriv->rootNode : (QSGNode *)itemPriv->groupNode;
+
+ if (item->clip()) {
+ Q_ASSERT(itemPriv->clipNode == 0);
+ itemPriv->clipNode = new QQuickDefaultClipNode(item->boundingRect());
+ itemPriv->clipNode->update();
+
+ if (child)
+ parent->removeChildNode(child);
+ parent->appendChildNode(itemPriv->clipNode);
+ if (child)
+ itemPriv->clipNode->appendChildNode(child);
+
+ } else {
+ Q_ASSERT(itemPriv->clipNode != 0);
+ parent->removeChildNode(itemPriv->clipNode);
+ if (child)
+ itemPriv->clipNode->removeChildNode(child);
+ delete itemPriv->clipNode;
+ itemPriv->clipNode = 0;
+ if (child)
+ parent->appendChildNode(child);
+ }
+ }
+
+ if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
+ itemPriv->childContainerNode()->removeAllChildNodes();
+
+ if (effectRefEffectivelyChanged) {
+ QSGNode *parent = itemPriv->clipNode;
+ if (!parent)
+ parent = itemPriv->opacityNode;
+ if (!parent)
+ parent = itemPriv->itemNode();
+ QSGNode *child = itemPriv->groupNode;
+
+ if (itemPriv->effectRefCount) {
+ Q_ASSERT(itemPriv->rootNode == 0);
+ itemPriv->rootNode = new QSGRootNode;
+
+ if (child)
+ parent->removeChildNode(child);
+ parent->appendChildNode(itemPriv->rootNode);
+ if (child)
+ itemPriv->rootNode->appendChildNode(child);
+ } else {
+ Q_ASSERT(itemPriv->rootNode != 0);
+ parent->removeChildNode(itemPriv->rootNode);
+ if (child)
+ itemPriv->rootNode->removeChildNode(child);
+ delete itemPriv->rootNode;
+ itemPriv->rootNode = 0;
+ if (child)
+ parent->appendChildNode(child);
+ }
+ }
+
+ if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
+ QSGNode *groupNode = itemPriv->groupNode;
+ if (groupNode)
+ groupNode->removeAllChildNodes();
+
+ QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
+ int ii = 0;
+
+ for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
+ if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
+ continue;
+ if (childPrivate->itemNode()->parent())
+ childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
+
+ itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
+ }
+ itemPriv->beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
+
+ if (itemPriv->paintNode)
+ itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
+
+ for (; ii < orderedChildren.count(); ++ii) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
+ if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
+ continue;
+ if (childPrivate->itemNode()->parent())
+ childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
+
+ itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
+ }
+ }
+
+ if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode) {
+ itemPriv->clipNode->setRect(item->boundingRect());
+ itemPriv->clipNode->update();
+ }
+
+ if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible | QQuickItemPrivate::HideReference)) {
+ qreal opacity = itemPriv->explicitVisible && itemPriv->hideRefCount == 0
+ ? itemPriv->opacity : qreal(0);
+
+ if (opacity != 1 && !itemPriv->opacityNode) {
+ itemPriv->opacityNode = new QSGOpacityNode;
+
+ QSGNode *parent = itemPriv->itemNode();
+ QSGNode *child = itemPriv->clipNode;
+ if (!child)
+ child = itemPriv->rootNode;
+ if (!child)
+ child = itemPriv->groupNode;
+
+ if (child)
+ parent->removeChildNode(child);
+ parent->appendChildNode(itemPriv->opacityNode);
+ if (child)
+ itemPriv->opacityNode->appendChildNode(child);
+ }
+ if (itemPriv->opacityNode)
+ itemPriv->opacityNode->setOpacity(opacity);
+ }
+
+ if (dirty & QQuickItemPrivate::ContentUpdateMask) {
+
+ if (itemPriv->flags & QQuickItem::ItemHasContents) {
+ updatePaintNodeData.transformNode = itemPriv->itemNode();
+ itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
+
+ Q_ASSERT(itemPriv->paintNode == 0 ||
+ itemPriv->paintNode->parent() == 0 ||
+ itemPriv->paintNode->parent() == itemPriv->childContainerNode());
+
+ if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
+ if (itemPriv->beforePaintNode)
+ itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->beforePaintNode);
+ else
+ itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
+ }
+ } else if (itemPriv->paintNode) {
+ delete itemPriv->paintNode;
+ itemPriv->paintNode = 0;
+ }
+ }
+
+#ifndef QT_NO_DEBUG
+ // Check consistency.
+ const QSGNode *nodeChain[] = {
+ itemPriv->itemNodeInstance,
+ itemPriv->opacityNode,
+ itemPriv->clipNode,
+ itemPriv->rootNode,
+ itemPriv->groupNode,
+ itemPriv->paintNode,
+ };
+
+ int ip = 0;
+ for (;;) {
+ while (ip < 5 && nodeChain[ip] == 0)
+ ++ip;
+ if (ip == 5)
+ break;
+ int ic = ip + 1;
+ while (ic < 5 && nodeChain[ic] == 0)
+ ++ic;
+ const QSGNode *parent = nodeChain[ip];
+ const QSGNode *child = nodeChain[ic];
+ if (child == 0) {
+ Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
+ } else {
+ Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
+ Q_ASSERT(child->parent() == parent);
+ bool containsChild = false;
+ for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
+ containsChild |= (n == child);
+ Q_ASSERT(containsChild);
+ }
+ ip = ic;
+ }
+#endif
+
+#ifdef QML_RUNTIME_TESTING
+ if (itemPriv->sceneGraphContext()->isFlashModeEnabled()) {
+ QSGFlashNode *flash = new QSGFlashNode();
+ flash->setRect(item->boundingRect());
+ itemPriv->childContainerNode()->appendChildNode(flash);
+ didFlash = true;
+ }
+ Q_Q(QQuickCanvas);
+ if (didFlash) {
+ q->maybeUpdate();
+ }
+#endif
+
+}
+
+void QQuickCanvas::maybeUpdate()
+{
+ Q_D(QQuickCanvas);
+
+ if (d->thread && d->thread->isRunning())
+ d->thread->maybeUpdate();
+}
+
+/*!
+ \fn void QSGEngine::sceneGraphInitialized();
+
+ This signal is emitted when the scene graph has been initialized.
+
+ This signal will be emitted from the scene graph rendering thread.
+ */
+
+/*!
+ Returns the QSGEngine used for this scene.
+
+ The engine will only be available once the scene graph has been
+ initialized. Register for the sceneGraphEngine() signal to get
+ notification about this.
+
+ \deprecated
+ */
+
+QSGEngine *QQuickCanvas::sceneGraphEngine() const
+{
+ Q_D(const QQuickCanvas);
+ qWarning("QQuickCanvas::sceneGraphEngine() is deprecated, use members of QQuickCanvas instead");
+ if (d->context && d->context->isReady())
+ return d->engine;
+ return 0;
+}
+
+
+
+/*!
+ Sets the render target for this canvas to be \a fbo.
+
+ The specified fbo must be created in the context of the canvas
+ or one that shares with it.
+
+ \warning
+ This function can only be called from the thread doing
+ the rendering.
+ */
+
+void QQuickCanvas::setRenderTarget(QOpenGLFramebufferObject *fbo)
+{
+ Q_D(QQuickCanvas);
+ if (d->context && d->context && QThread::currentThread() != d->context->thread()) {
+ qWarning("QQuickCanvas::setRenderThread: Cannot set render target from outside the rendering thread");
+ return;
+ }
+
+ d->renderTarget = fbo;
+}
+
+
+
+/*!
+ Returns the render target for this canvas.
+
+ The default is to render to the surface of the canvas, in which
+ case the render target is 0.
+ */
+QOpenGLFramebufferObject *QQuickCanvas::renderTarget() const
+{
+ Q_D(const QQuickCanvas);
+ return d->renderTarget;
+}
+
+
+/*!
+ Grabs the contents of the framebuffer and returns it as an image.
+
+ This function might not work if the view is not visible.
+
+ \warning Calling this function will cause performance problems.
+
+ \warning This function can only be called from the GUI thread.
+ */
+QImage QQuickCanvas::grabFrameBuffer()
+{
+ Q_D(QQuickCanvas);
+ return d->thread ? d->thread->grab() : QImage();
+}
+
+/*!
+ Returns an incubation controller that splices incubation between frames
+ for this canvas. QQuickView automatically installs this controller for you,
+ otherwise you will need to install it yourself using \l{QDeclarativeEngine::setIncubationController}
+
+ The controller is owned by the canvas and will be destroyed when the canvas
+ is deleted.
+*/
+QDeclarativeIncubationController *QQuickCanvas::incubationController() const
+{
+ Q_D(const QQuickCanvas);
+
+ if (!d->incubationController)
+ d->incubationController = new QQuickCanvasIncubationController(const_cast<QQuickCanvasPrivate *>(d));
+ return d->incubationController;
+}
+
+
+
+/*!
+ \enum QQuickCanvas::CreateTextureOption
+
+ The CreateTextureOption enums are used to customize a texture is wrapped.
+
+ \value TextureHasAlphaChannel The texture has an alpha channel and should
+ be drawn using blending.
+
+ \value TextureHasMipmaps The texture has mipmaps and can be drawn with
+ mipmapping enabled.
+
+ \value TextureOwnsGLTexture The texture object owns the texture id and
+ will delete the GL texture when the texture object is deleted.
+ */
+
+/*!
+ \fn void QQuickCanvas::beforeRendering()
+
+ This signal is emitted before the scene starts rendering.
+
+ Combined with the modes for clearing the background, this option
+ can be used to paint using raw GL under QML content.
+
+ The GL context used for rendering the scene graph will be bound
+ at this point.
+
+ Since this signal is emitted from the scene graph rendering thread, the receiver should
+ be on the scene graph thread or the connection should be Qt::DirectConnection.
+
+*/
+
+/*!
+ \fn void QQuickCanvas::afterRendering()
+
+ This signal is emitted after the scene has completed rendering, before swapbuffers is called.
+
+ This signal can be used to paint using raw GL on top of QML content,
+ or to do screen scraping of the current frame buffer.
+
+ The GL context used for rendering the scene graph will be bound at this point.
+
+ Since this signal is emitted from the scene graph rendering thread, the receiver should
+ be on the scene graph thread or the connection should be Qt::DirectConnection.
+ */
+
+
+
+/*!
+ Sets weither the scene graph rendering of QML should clear the color buffer
+ before it starts rendering to \a enbled.
+
+ By disabling clearing of the color buffer, it is possible to do GL painting
+ under the scene graph.
+
+ The color buffer is cleared by default.
+
+ \sa beforeRendering()
+ */
+
+void QQuickCanvas::setClearBeforeRendering(bool enabled)
+{
+ Q_D(QQuickCanvas);
+ d->clearBeforeRendering = enabled;
+}
+
+
+
+/*!
+ Returns weither clearing of the color buffer is done before rendering or not.
+ */
+
+bool QQuickCanvas::clearBeforeRendering() const
+{
+ Q_D(const QQuickCanvas);
+ return d->clearBeforeRendering;
+}
+
+
+
+/*!
+ Creates a new QSGTexture from the supplied \a image. If the image has an
+ alpha channel, the corresponding texture will have an alpha channel.
+
+ The caller of the function is responsible for deleting the returned texture.
+ The actual GL texture will be deleted when the texture object is deleted.
+
+ \warning This function will return 0 if the scene graph has not yet been
+ initialized.
+
+ This function can be called both from the GUI thread and the rendering thread.
+
+ \sa sceneGraphInitialized()
+ */
+
+QSGTexture *QQuickCanvas::createTextureFromImage(const QImage &image) const
+{
+ Q_D(const QQuickCanvas);
+ if (d->context)
+ return d->context->createTexture(image);
+ else
+ return 0;
+}
+
+
+
+/*!
+ Creates a new QSGTexture object from an existing GL texture \a id.
+
+ The caller of the function is responsible for deleting the returned texture.
+
+ Use \a options to customize the texture attributes.
+
+ \warning This function will return 0 if the scenegraph has not yet been
+ initialized.
+
+ \sa sceneGraphInitialized()
+ */
+QSGTexture *QQuickCanvas::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
+{
+ Q_D(const QQuickCanvas);
+ if (d->context) {
+ QSGPlainTexture *texture = new QSGPlainTexture();
+ texture->setTextureId(id);
+ texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
+ texture->setHasMipmaps(options & TextureHasMipmaps);
+ texture->setOwnsTexture(options & TextureOwnsGLTexture);
+ texture->setTextureSize(size);
+ return texture;
+ }
+ return 0;
+}
+
+
+/*!
+ Sets the color used to clear the opengl context to \a color.
+
+ Setting the clear color has no effect when clearing is disabled.
+
+ \sa setClearBeforeRendering()
+ */
+
+void QQuickCanvas::setClearColor(const QColor &color)
+{
+ if (color == d_func()->clearColor)
+ return;
+ d_func()->clearColor = color;
+ emit clearColorChanged(color);
+}
+
+
+
+/*!
+ Returns the color used to clear the opengl context.
+ */
+
+QColor QQuickCanvas::clearColor() const
+{
+ return d_func()->clearColor;
+}
+
+
+
+void QQuickCanvasRenderLoop::createGLContext()
+{
+ gl = new QOpenGLContext();
+ gl->setFormat(renderer->requestedFormat());
+ gl->create();
+}
+
+void QQuickCanvasRenderThread::run()
+{
+#ifdef THREAD_DEBUG
+ qDebug("QML Rendering Thread Started");
+#endif
+
+ if (!glContext()) {
+ createGLContext();
+ makeCurrent();
+ initializeSceneGraph();
+ } else {
+ makeCurrent();
+ }
+
+ while (!shouldExit) {
+ lock();
+
+ bool sizeChanged = false;
+ isExternalUpdatePending = false;
+
+ if (renderedSize != windowSize) {
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: window has changed size...\n");
+#endif
+ glViewport(0, 0, windowSize.width(), windowSize.height());
+ sizeChanged = true;
+ }
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: preparing to sync...\n");
+#endif
+
+ if (!isGuiBlocked) {
+ isGuiBlockPending = true;
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: aquired sync lock...\n");
+#endif
+ allowMainThreadProcessingFlag = false;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: going to sleep...\n");
+#endif
+ wait();
+
+ isGuiBlockPending = false;
+ }
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: Doing locked sync\n");
+#endif
+#ifdef QQUICK_CANVAS_TIMING
+ if (qquick_canvas_timing)
+ threadTimer.start();
+#endif
+ inSync = true;
+ syncSceneGraph();
+ inSync = false;
+
+ // Wake GUI after sync to let it continue animating and event processing.
+ allowMainThreadProcessingFlag = true;
+ wake();
+ unlock();
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: sync done\n");
+#endif
+#ifdef QQUICK_CANVAS_TIMING
+ if (qquick_canvas_timing)
+ syncTime = threadTimer.elapsed();
+#endif
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: rendering... %d x %d\n", windowSize.width(), windowSize.height());
+#endif
+
+ renderSceneGraph(windowSize);
+#ifdef QQUICK_CANVAS_TIMING
+ if (qquick_canvas_timing)
+ renderTime = threadTimer.elapsed() - syncTime;
+#endif
+
+ // The content of the target buffer is undefined after swap() so grab needs
+ // to happen before swap();
+ if (doGrab) {
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: doing a grab...\n");
+#endif
+ grabContent = qt_gl_read_framebuffer(windowSize, false, false);
+ doGrab = false;
+ }
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: wait for swap...\n");
+#endif
+
+ swapBuffers();
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: swap complete...\n");
+#endif
+#ifdef QQUICK_CANVAS_TIMING
+ if (qquick_canvas_timing) {
+ swapTime = threadTimer.elapsed() - renderTime;
+ qDebug() << "- Breakdown of frame time: sync:" << syncTime
+ << "ms render:" << renderTime << "ms swap:" << swapTime
+ << "ms total:" << swapTime + renderTime << "ms";
+ }
+#endif
+
+ lock();
+ isPaintCompleted = true;
+ if (sizeChanged)
+ renderedSize = windowSize;
+
+ // Wake the GUI thread now that rendering is complete, to signal that painting
+ // is done, resizing is done or grabbing is completed. For grabbing, we're
+ // signalling this much later than needed (we could have done it before swap)
+ // but we don't want to lock an extra time.
+ wake();
+
+ if (!animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: nothing to do, going to sleep...\n");
+#endif
+ isRenderBlocked = true;
+ wait();
+ isRenderBlocked = false;
+ }
+
+ unlock();
+
+ QCoreApplication::processEvents();
+
+ // Process any "deleteLater" objects...
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: deleting all outstanding nodes\n");
+#endif
+ cleanupNodesOnShutdown();
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: render loop exited... Good Night!\n");
+#endif
+
+ doneCurrent();
+
+ lock();
+ hasExited = true;
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: waking GUI for final sleep..\n");
+#endif
+ wake();
+ unlock();
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: All done...\n");
+#endif
+}
+
+
+
+bool QQuickCanvasRenderThread::event(QEvent *e)
+{
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+
+ if (e->type() == QEvent::User) {
+ if (!syncAlreadyHappened)
+ sync(false);
+
+ syncAlreadyHappened = false;
+
+ if (animationRunning && animationDriver()) {
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Advancing animations...\n");
+#endif
+
+ animationDriver()->advance();
+
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Animations advanced...\n");
+#endif
+ }
+
+ return true;
+ }
+
+ return QThread::event(e);
+}
+
+
+
+void QQuickCanvasRenderThread::exhaustSyncEvent()
+{
+ if (isGuiBlockPending) {
+ sync(true);
+ syncAlreadyHappened = true;
+ }
+}
+
+
+
+void QQuickCanvasRenderThread::sync(bool guiAlreadyLocked)
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event");
+#endif
+ if (!guiAlreadyLocked)
+ lockInGui();
+
+ renderThreadAwakened = false;
+
+ polishItems();
+
+ wake();
+ wait();
+
+ if (!guiAlreadyLocked)
+ unlockInGui();
+}
+
+
+
+
+/*!
+ Acquires the mutex for the GUI thread. The function uses the isGuiBlocked
+ variable to keep track of how many recursion levels the gui is locked with.
+ We only actually acquire the mutex for the first level to avoid deadlocking
+ ourselves.
+ */
+
+void QQuickCanvasRenderThread::lockInGui()
+{
+ // We must avoid recursive locking in the GUI thread, hence we
+ // only lock when we are the first one to try to block.
+ if (!isGuiBlocked)
+ lock();
+
+ isGuiBlocked++;
+
+#ifdef THREAD_DEBUG
+ printf("GUI: aquired lock... %d\n", isGuiBlocked);
+#endif
+}
+
+
+
+void QQuickCanvasRenderThread::unlockInGui()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: releasing lock... %d\n", isGuiBlocked);
+#endif
+ --isGuiBlocked;
+ if (!isGuiBlocked)
+ unlock();
+}
+
+
+
+
+void QQuickCanvasRenderThread::animationStarted()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: animationStarted()\n");
+#endif
+
+ lockInGui();
+
+ animationRunning = true;
+
+ if (isRenderBlocked)
+ wake();
+
+ unlockInGui();
+}
+
+
+
+void QQuickCanvasRenderThread::animationStopped()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: animationStopped()...\n");
+#endif
+
+ lockInGui();
+ animationRunning = false;
+ unlockInGui();
+}
+
+
+void QQuickCanvasRenderThread::paint()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: paint called..\n");
+#endif
+
+ lockInGui();
+ exhaustSyncEvent();
+
+ isPaintCompleted = false;
+ while (isRunning() && !isPaintCompleted) {
+ if (isRenderBlocked)
+ wake();
+ wait();
+ }
+ unlockInGui();
+}
+
+
+
+void QQuickCanvasRenderThread::resize(const QSize &size)
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: Resize Event: %dx%d\n", size.width(), size.height());
+#endif
+
+ if (!isRunning()) {
+ windowSize = size;
+ return;
+ }
+
+ lockInGui();
+ exhaustSyncEvent();
+
+ windowSize = size;
+
+ while (isRunning() && renderedSize != windowSize) {
+ if (isRenderBlocked)
+ wake();
+ wait();
+ }
+ unlockInGui();
+}
+
+
+
+void QQuickCanvasRenderThread::startRendering()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: Starting Render Thread\n");
+#endif
+ hasExited = false;
+ shouldExit = false;
+ isGuiBlocked = 0;
+ isGuiBlockPending = false;
+ start();
+}
+
+
+
+void QQuickCanvasRenderThread::stopRendering()
+{
+#ifdef THREAD_DEBUG
+ printf("GUI: stopping render thread\n");
+#endif
+
+ lockInGui();
+ exhaustSyncEvent();
+ shouldExit = true;
+
+ if (isRenderBlocked) {
+#ifdef THREAD_DEBUG
+ printf("GUI: waking up render thread\n");
+#endif
+ wake();
+ }
+
+ while (!hasExited) {
+#ifdef THREAD_DEBUG
+ printf("GUI: waiting for render thread to have exited..\n");
+#endif
+ wait();
+ }
+
+ unlockInGui();
+
+#ifdef THREAD_DEBUG
+ printf("GUI: waiting for render thread to terminate..\n");
+#endif
+ // Actually wait for the thread to terminate. Otherwise we can delete it
+ // too early and crash.
+ QThread::wait();
+
+#ifdef THREAD_DEBUG
+ printf("GUI: thread has terminated and we're all good..\n");
+#endif
+
+}
+
+
+
+QImage QQuickCanvasRenderThread::grab()
+{
+ if (!isRunning())
+ return QImage();
+
+ if (QThread::currentThread() != qApp->thread()) {
+ qWarning("QQuickCanvas::grabFrameBuffer: can only be called from the GUI thread");
+ return QImage();
+ }
+
+#ifdef THREAD_DEBUG
+ printf("GUI: doing a pixelwise grab..\n");
+#endif
+
+ lockInGui();
+ exhaustSyncEvent();
+
+ doGrab = true;
+ isPaintCompleted = false;
+ while (isRunning() && !isPaintCompleted) {
+ if (isRenderBlocked)
+ wake();
+ wait();
+ }
+
+ QImage grabbed = grabContent;
+ grabContent = QImage();
+
+ unlockInGui();
+
+ return grabbed;
+}
+
+
+
+void QQuickCanvasRenderThread::maybeUpdate()
+{
+ Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || inSync,
+ "QQuickCanvas::update",
+ "Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
+
+ if (inSync) {
+ isExternalUpdatePending = true;
+
+ } else if (!renderThreadAwakened) {
+#ifdef THREAD_DEBUG
+ printf("GUI: doing update...\n");
+#endif
+ renderThreadAwakened = true;
+ lockInGui();
+ isExternalUpdatePending = true;
+ if (isRenderBlocked)
+ wake();
+ unlockInGui();
+ }
+}
+
+
+#include "moc_qquickcanvas.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickcanvas.h b/src/quick/items/qquickcanvas.h
new file mode 100644
index 0000000000..9ea73b087b
--- /dev/null
+++ b/src/quick/items/qquickcanvas.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCANVAS_H
+#define QQUICKCANVAS_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtCore/qmetatype.h>
+#include <QtGui/qopengl.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGEngine;
+class QQuickItem;
+class QSGTexture;
+class QInputMethodEvent;
+class QQuickCanvasPrivate;
+class QOpenGLFramebufferObject;
+class QDeclarativeIncubationController;
+class QInputMethodEvent;
+
+class Q_QUICK_EXPORT QQuickCanvas : public QWindow
+{
+ Q_OBJECT
+ Q_PRIVATE_PROPERTY(QQuickCanvas::d_func(), QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
+ Q_PROPERTY(QColor color READ clearColor WRITE setClearColor NOTIFY clearColorChanged)
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_DECLARE_PRIVATE(QQuickCanvas)
+public:
+ enum CreateTextureOption {
+ TextureHasAlphaChannel = 0x0001,
+ TextureHasMipmaps = 0x0002,
+ TextureOwnsGLTexture = 0x0004
+ };
+
+ Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
+
+ QQuickCanvas(QWindow *parent = 0);
+
+ virtual ~QQuickCanvas();
+
+ QQuickItem *rootItem() const;
+ QQuickItem *activeFocusItem() const;
+
+ QQuickItem *mouseGrabberItem() const;
+
+ bool sendEvent(QQuickItem *, QEvent *);
+
+ QSGEngine *sceneGraphEngine() const;
+
+ void setVSyncAnimations(bool enabled);
+ bool vsyncAnimations() const;
+
+ QImage grabFrameBuffer();
+
+ void setRenderTarget(QOpenGLFramebufferObject *fbo);
+ QOpenGLFramebufferObject *renderTarget() const;
+
+ QDeclarativeIncubationController *incubationController() const;
+
+ // Scene graph specific functions
+ QSGTexture *createTextureFromImage(const QImage &image) const;
+ QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption(0)) const;
+
+ void setClearBeforeRendering(bool enabled);
+ bool clearBeforeRendering() const;
+
+ void setClearColor(const QColor &color);
+ QColor clearColor() const;
+
+ QOpenGLContext *openglContext() const;
+
+Q_SIGNALS:
+ void frameSwapped();
+ void sceneGraphInitialized();
+ void beforeRendering();
+ void afterRendering();
+ void clearColorChanged(const QColor &);
+
+protected:
+ QQuickCanvas(QQuickCanvasPrivate &dd, QWindow *parent = 0);
+
+ virtual void exposeEvent(QExposeEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+
+ virtual void showEvent(QShowEvent *);
+ virtual void hideEvent(QHideEvent *);
+
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+
+ virtual bool event(QEvent *);
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent(QWheelEvent *);
+#endif
+
+private Q_SLOTS:
+ void maybeUpdate();
+ void animationStarted();
+ void animationStopped();
+
+private:
+ friend class QQuickItem;
+ friend class QQuickCanvasRenderLoop;
+ Q_DISABLE_COPY(QQuickCanvas)
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQuickCanvas *)
+
+QT_END_HEADER
+
+#endif // QQUICKCANVAS_H
+
diff --git a/src/quick/items/qquickcanvas_p.h b/src/quick/items/qquickcanvas_p.h
new file mode 100644
index 0000000000..633f382954
--- /dev/null
+++ b/src/quick/items/qquickcanvas_p.h
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCANVAS_P_H
+#define QQUICKCANVAS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickitem.h"
+#include "qquickcanvas.h"
+#include <private/qdeclarativeguard_p.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qquickdrag_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <private/qwindow_p.h>
+#include <private/qopengl_p.h>
+#include <qopenglcontext.h>
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qinputpanel.h>
+
+QT_BEGIN_NAMESPACE
+
+//Make it easy to identify and customize the root item if needed
+
+class QQuickRootItem : public QQuickItem
+{
+ Q_OBJECT
+public:
+ QQuickRootItem();
+public Q_SLOTS:
+ void setWidth(int w) {QQuickItem::setWidth(qreal(w));}
+ void setHeight(int h) {QQuickItem::setHeight(qreal(h));}
+};
+
+class QQuickItemPrivate;
+class QQuickCanvasPrivate;
+
+class QTouchEvent;
+class QQuickCanvasRenderLoop;
+class QQuickCanvasIncubationController;
+
+class QQuickCanvasPrivate : public QWindowPrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QQuickCanvas)
+
+ static inline QQuickCanvasPrivate *get(QQuickCanvas *c) { return c->d_func(); }
+
+ QQuickCanvasPrivate();
+ virtual ~QQuickCanvasPrivate();
+
+ void init(QQuickCanvas *);
+ void initRootItem();//Currently only used if items added in QML
+
+ QQuickRootItem *rootItem;
+ QDeclarativeListProperty<QObject> data();
+
+ QQuickItem *activeFocusItem;
+ QQuickItem *mouseGrabberItem;
+ QQuickDragGrabber dragGrabber;
+
+ // Mouse positions are saved in widget coordinates
+ QPointF lastMousePosition;
+ void translateTouchEvent(QTouchEvent *touchEvent);
+ static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
+ bool deliverInitialMousePressEvent(QQuickItem *, QMouseEvent *);
+ bool deliverMouseEvent(QMouseEvent *);
+ bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *);
+ bool deliverWheelEvent(QQuickItem *, QWheelEvent *);
+ bool deliverTouchPoints(QQuickItem *, QTouchEvent *, const QList<QTouchEvent::TouchPoint> &, QSet<int> *,
+ QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *);
+ bool deliverTouchEvent(QTouchEvent *);
+ bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
+ bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
+ Qt::KeyboardModifiers modifiers, bool accepted);
+ bool clearHover();
+ void deliverDragEvent(QQuickDragGrabber *, QEvent *);
+ bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
+
+ QList<QQuickItem*> hoverItems;
+ enum FocusOption {
+ DontChangeFocusProperty = 0x01,
+ };
+ Q_DECLARE_FLAGS(FocusOptions, FocusOption)
+
+ void setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
+ void clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
+ void notifyFocusChangesRecur(QQuickItem **item, int remaining);
+
+ void updateInputMethodData();
+ void updateFocusItemTransform();
+
+ void dirtyItem(QQuickItem *);
+ void cleanup(QSGNode *);
+
+ void initializeSceneGraph();
+ void polishItems();
+ void syncSceneGraph();
+ void renderSceneGraph(const QSize &size);
+
+ QQuickItem::UpdatePaintNodeData updatePaintNodeData;
+
+ QQuickItem *dirtyItemList;
+ QList<QSGNode *> cleanupNodeList;
+
+ QSet<QQuickItem *> itemsToPolish;
+
+ void updateDirtyNodes();
+ void cleanupNodes();
+ void cleanupNodesOnShutdown();
+ bool updateEffectiveOpacity(QQuickItem *);
+ void updateEffectiveOpacityRoot(QQuickItem *, qreal);
+ void updateDirtyNode(QQuickItem *);
+
+ QSGEngine *engine;
+ QSGContext *context;
+ QColor clearColor;
+
+ uint vsyncAnimations : 1;
+ uint clearBeforeRendering : 1;
+
+ QQuickCanvasRenderLoop *thread;
+ QSize widgetSize;
+ QSize viewportSize;
+
+ QAnimationDriver *animationDriver;
+
+ QOpenGLFramebufferObject *renderTarget;
+
+ QHash<int, QQuickItem *> itemForTouchPointId;
+
+ mutable QQuickCanvasIncubationController *incubationController;
+
+private:
+ static void cleanupNodesOnShutdown(QQuickItem *);
+};
+
+class QQuickCanvasRenderLoop
+{
+public:
+ QQuickCanvasRenderLoop()
+ : d(0)
+ , renderer(0)
+ , gl(0)
+ {
+ }
+ virtual ~QQuickCanvasRenderLoop()
+ {
+ delete gl;
+ }
+
+ friend class QQuickCanvasPrivate;
+
+ virtual void paint() = 0;
+ virtual void resize(const QSize &size) = 0;
+ virtual void startRendering() = 0;
+ virtual void stopRendering() = 0;
+ virtual QImage grab() = 0;
+ virtual void setWindowSize(const QSize &size) = 0;
+ virtual void maybeUpdate() = 0;
+ virtual bool isRunning() const = 0;
+ virtual void animationStarted() = 0;
+ virtual void animationStopped() = 0;
+ virtual void moveContextToThread(QSGContext *) { }
+ virtual bool *allowMainThreadProcessing() { return 0; }
+
+protected:
+ void initializeSceneGraph() { d->initializeSceneGraph(); }
+ void syncSceneGraph() { d->syncSceneGraph(); }
+ void cleanupNodesOnShutdown() { d->cleanupNodesOnShutdown(); }
+ void renderSceneGraph(const QSize &size) { d->renderSceneGraph(size); }
+ void polishItems() { d->polishItems(); }
+ QAnimationDriver *animationDriver() const { return d->animationDriver; }
+
+ inline QOpenGLContext *glContext() const { return gl; }
+ void createGLContext();
+ void makeCurrent() { gl->makeCurrent(renderer); }
+ void doneCurrent() { gl->doneCurrent(); }
+ void swapBuffers() {
+ gl->swapBuffers(renderer);
+ emit renderer->frameSwapped();
+ }
+
+private:
+ QQuickCanvasPrivate *d;
+ QQuickCanvas *renderer;
+
+ QOpenGLContext *gl;
+};
+
+class QQuickCanvasRenderThread : public QThread, public QQuickCanvasRenderLoop
+{
+ Q_OBJECT
+public:
+ QQuickCanvasRenderThread()
+ : mutex(QMutex::NonRecursive)
+ , allowMainThreadProcessingFlag(true)
+ , animationRunning(false)
+ , isGuiBlocked(0)
+ , isPaintCompleted(false)
+ , isGuiBlockPending(false)
+ , isRenderBlocked(false)
+ , isExternalUpdatePending(false)
+ , syncAlreadyHappened(false)
+ , inSync(false)
+ , doGrab(false)
+ , shouldExit(false)
+ , hasExited(false)
+ , renderThreadAwakened(false)
+ {}
+
+ inline void lock() { mutex.lock(); }
+ inline void unlock() { mutex.unlock(); }
+ inline void wait() { condition.wait(&mutex); }
+ inline void wake() { condition.wakeOne(); }
+
+ void lockInGui();
+ void unlockInGui();
+
+ void paint();
+ void resize(const QSize &size);
+ void startRendering();
+ void stopRendering();
+ void exhaustSyncEvent();
+ void sync(bool guiAlreadyLocked);
+ bool isRunning() const { return QThread::isRunning(); }
+ void setWindowSize(const QSize &size) { windowSize = size; }
+ void maybeUpdate();
+ void moveContextToThread(QSGContext *c) { c->moveToThread(this); }
+ bool *allowMainThreadProcessing() { return &allowMainThreadProcessingFlag; }
+
+ bool event(QEvent *);
+
+ QImage grab();
+
+public slots:
+ void animationStarted();
+ void animationStopped();
+
+public:
+ QMutex mutex;
+ QWaitCondition condition;
+
+ bool allowMainThreadProcessingFlag;
+
+ QSize windowSize;
+ QSize renderedSize;
+
+ uint animationRunning: 1;
+ int isGuiBlocked;
+ uint isPaintCompleted : 1;
+ uint isGuiBlockPending : 1;
+ uint isRenderBlocked : 1;
+ uint isExternalUpdatePending : 1;
+ uint syncAlreadyHappened : 1;
+ uint inSync : 1;
+ uint doGrab : 1;
+ uint shouldExit : 1;
+ uint hasExited : 1;
+ uint renderThreadAwakened : 1;
+
+ QImage grabContent;
+
+ void run();
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickCanvasPrivate::FocusOptions)
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCANVAS_P_H
diff --git a/src/declarative/items/qquickclipnode.cpp b/src/quick/items/qquickclipnode.cpp
index 4aeb2dcf69..4aeb2dcf69 100644
--- a/src/declarative/items/qquickclipnode.cpp
+++ b/src/quick/items/qquickclipnode.cpp
diff --git a/src/quick/items/qquickclipnode_p.h b/src/quick/items/qquickclipnode_p.h
new file mode 100644
index 0000000000..ee85409c9d
--- /dev/null
+++ b/src/quick/items/qquickclipnode_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKCLIPNODE_P_H
+#define QQUICKCLIPNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+
+class QQuickDefaultClipNode : public QSGClipNode
+{
+public:
+ QQuickDefaultClipNode(const QRectF &);
+
+ void setRect(const QRectF &);
+ QRectF rect() const { return m_rect; }
+
+ void setRadius(qreal radius);
+ qreal radius() const { return m_radius; }
+
+ virtual void update();
+
+private:
+ void updateGeometry();
+ QRectF m_rect;
+ qreal m_radius;
+
+ uint m_dirty_geometry : 1;
+ uint m_reserved : 31;
+
+ QSGGeometry m_geometry;
+};
+
+#endif // QQUICKCLIPNODE_P_H
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
new file mode 100644
index 0000000000..12d8cbea98
--- /dev/null
+++ b/src/quick/items/qquickdrag.cpp
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickdrag_p.h"
+
+#include <private/qquickitem_p.h>
+#include <QtQuick/private/qquickevents_p_p.h>
+#include <private/qquickitemchangelistener_p.h>
+#include <private/qv8engine_p.h>
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDragAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickDragAttached)
+public:
+ static QQuickDragAttachedPrivate *get(QQuickDragAttached *attached) {
+ return static_cast<QQuickDragAttachedPrivate *>(QObjectPrivate::get(attached)); }
+
+ QQuickDragAttachedPrivate()
+ : attachedItem(0)
+ , mimeData(0)
+ , proposedAction(Qt::MoveAction)
+ , supportedActions(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction)
+ , active(false)
+ , listening(false)
+ {
+ }
+
+ void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
+ void start() { start(supportedActions); }
+ void start(Qt::DropActions supportedActions);
+ void setTarget(QQuickItem *item);
+
+ QQuickDragGrabber dragGrabber;
+
+ QDeclarativeGuard<QObject> source;
+ QDeclarativeGuard<QObject> target;
+ QQuickItem *attachedItem;
+ QQuickDragMimeData *mimeData;
+ Qt::DropAction proposedAction;
+ Qt::DropActions supportedActions;
+ bool active : 1;
+ bool listening : 1;
+ QPointF hotSpot;
+ QStringList keys;
+};
+
+/*!
+ \qmlclass Drag QQuickDrag
+ \inqmlmodule QtQuick 2
+ \brief The Drag attached property provides drag and drop events for moved Items.
+
+ Using the Drag attached property any Item can made a source of drag and drop
+ events within a scene.
+
+ When a drag is \l active on an item any change in that items position will
+ generate a drag events that will be sent to any DropArea that intersects
+ the with new position of the item. Other items which implement drag and
+ drop event handlers can also receive these events.
+
+ The following snippet shows how an item can be dragged with a MouseArea.
+ However, dragging is not limited to mouse drags, anything that can move an item
+ can generate drag events, this can include touch events, animations and bindings.
+
+ \snippet doc/src/snippets/declarative/drag.qml 0
+
+ A drag can be terminated either by canceling it with Drag.cancel() or setting
+ Drag.active to false, or it can be terminated with a drop event by calling
+ Drag.drop(). If the drop event is accepted Drag.drop() will return the
+ \l {supportedActions}{drop action} chosen by the recipient of the event,
+ otherwise it will return Qt.IgnoreAction.
+
+*/
+
+void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QQuickDragAttached);
+ if (newGeometry.topLeft() == oldGeometry.topLeft() || !active)
+ return;
+
+ if (QQuickCanvas *canvas = attachedItem->canvas()) {
+ QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
+ QDragMoveEvent event(scenePos, mimeData->m_supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
+ QQuickDropEventEx::setProposedAction(&event, proposedAction);
+ QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+ if (target != dragGrabber.target()) {
+ target = dragGrabber.target();
+ emit q->targetChanged();
+ }
+ }
+}
+
+QQuickDragAttached::QQuickDragAttached(QObject *parent)
+ : QObject(*new QQuickDragAttachedPrivate, parent)
+{
+ Q_D(QQuickDragAttached);
+ d->attachedItem = qobject_cast<QQuickItem *>(parent);
+ d->source = d->attachedItem;
+}
+
+QQuickDragAttached::~QQuickDragAttached()
+{
+ Q_D(QQuickDragAttached);
+ delete d->mimeData;
+}
+
+/*!
+ \qmlattachedproperty bool QtQuick2::Drag::active
+
+ This property holds whether a drag event sequence is currently active.
+
+ Setting this property to true will send a QDragEnter event to the scene
+ with the item's current position. Setting it to false will send a
+ QDragLeave event.
+
+ While a drag is active any change in an item's position will send a QDragMove
+ event with item's new position to the scene.
+*/
+
+bool QQuickDragAttached::isActive() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->active;
+}
+
+void QQuickDragAttached::setActive(bool active)
+{
+ Q_D(QQuickDragAttached);
+ if (d->active != active) {
+ if (active)
+ d->start(d->supportedActions);
+ else
+ cancel();
+ }
+}
+
+/*!
+ \qmlattachedproperty Object QtQuick2::Drag::source
+
+ This property holds an object that is identified to recipients of drag events as
+ the source of the events. By default this is the item Drag property is attached to.
+
+ Changes to source while a Drag is active don't take effect until a new drag is started.
+*/
+
+QObject *QQuickDragAttached::source() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->source;
+}
+
+void QQuickDragAttached::setSource(QObject *item)
+{
+ Q_D(QQuickDragAttached);
+ if (d->source != item) {
+ d->source = item;
+ emit sourceChanged();
+ }
+}
+
+void QQuickDragAttached::resetSource()
+{
+ Q_D(QQuickDragAttached);
+ if (d->source != d->attachedItem) {
+ d->source = d->attachedItem;
+ emit sourceChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty Object QtQuick2::Drag::target
+
+ While a drag is active this property holds the last object to accept an
+ enter event from the dragged item, if the current drag position doesn't
+ intersect any accepting targets it is null.
+
+ When a drag is not active this property holds the object that accepted
+ the drop event that ended the drag, if no object accepted the drop or
+ the drag was canceled the target will then be null.
+*/
+
+QObject *QQuickDragAttached::target() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->target;
+}
+
+/*!
+ \qmlattachedproperty QPointF QtQuick2::Drag::hotSpot
+
+ This property holds the drag position relative to the top left of the item.
+
+ By default this is (0, 0).
+
+ Changes to hotSpot will take effect when the next event is sent.
+*/
+
+QPointF QQuickDragAttached::hotSpot() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->hotSpot;
+}
+
+void QQuickDragAttached::setHotSpot(const QPointF &hotSpot)
+{
+ Q_D(QQuickDragAttached);
+ if (d->hotSpot != hotSpot) {
+ d->hotSpot = hotSpot;
+ emit hotSpotChanged();
+ // Send a move event if active?
+ }
+}
+
+/*!
+ \qmlattachedproperty stringlist QtQuick2::Drag::keys
+
+ This property holds a list of keys that can be used by a DropArea to filter drag events.
+
+ Changes to keys while a Drag is active don't take effect until a new drag is started.
+*/
+
+QStringList QQuickDragAttached::keys() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->keys;
+}
+
+void QQuickDragAttached::setKeys(const QStringList &keys)
+{
+ Q_D(QQuickDragAttached);
+ if (d->keys != keys) {
+ d->keys = keys;
+ emit keysChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty flags QtQuick2::Drag::supportedActions
+
+ This property holds return values of Drag.drop() supported by the drag source.
+
+ Changes to supportedActions while a Drag is active don't take effect
+ until a new drag is started.
+*/
+
+Qt::DropActions QQuickDragAttached::supportedActions() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->supportedActions;
+}
+
+void QQuickDragAttached::setSupportedActions(Qt::DropActions actions)
+{
+ Q_D(QQuickDragAttached);
+ if (d->supportedActions != actions) {
+ d->supportedActions = actions;
+ emit supportedActionsChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty enumeration QtQuick2::Drag::proposedAction
+
+ This property holds an action that is recommended by the drag source as a
+ return value from Drag.drop().
+
+ Changes to proposedAction will take effect when the next event is sent.
+*/
+
+Qt::DropAction QQuickDragAttached::proposedAction() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->proposedAction;
+}
+
+void QQuickDragAttached::setProposedAction(Qt::DropAction action)
+{
+ Q_D(QQuickDragAttached);
+ if (d->proposedAction != action) {
+ d->proposedAction = action;
+ emit proposedActionChanged();
+ // send a move event with the new default action if active?
+ }
+}
+
+void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
+{
+ Q_Q(QQuickDragAttached);
+ Q_ASSERT(!active);
+
+ if (QQuickCanvas *canvas = attachedItem ? attachedItem->canvas() : 0) {
+ if (!mimeData)
+ mimeData = new QQuickDragMimeData;
+ if (!listening) {
+ QQuickItemPrivate::get(attachedItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ listening = true;
+ }
+
+ mimeData->m_source = source;
+ mimeData->m_supportedActions = supportedActions;
+ mimeData->m_keys = keys;
+ active = true;
+
+ QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
+ QDragEnterEvent event(scenePos, supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
+ QQuickDropEventEx::setProposedAction(&event, proposedAction);
+ QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+
+ emit q->activeChanged();
+ if (target != dragGrabber.target()) {
+ target = dragGrabber.target();
+ emit q->targetChanged();
+ }
+ }
+}
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::start(flags supportedActions)
+
+ Starts sending drag events.
+
+ The optional \a supportedActions argument can be used to override the \l supportedActions
+ property for the started sequence.
+*/
+
+void QQuickDragAttached::start(QDeclarativeV8Function *args)
+{
+ Q_D(QQuickDragAttached);
+ if (d->active)
+ cancel();
+
+ Qt::DropActions supportedActions = d->supportedActions;
+ // check arguments for supportedActions, maybe data?
+ if (args->Length() >= 1) {
+ v8::Local<v8::Value> v = (*args)[0];
+ if (v->IsInt32())
+ supportedActions = Qt::DropActions(v->Int32Value());
+ }
+
+ d->start(supportedActions);
+}
+
+/*!
+ \qmlattachedmethod enum QtQuick2::Drag::drop()
+
+ Ends a drag sequence by sending a drop event to the target item.
+
+ Returns the action accepted by the target item. If the target item or a parent doesn't accept
+ the drop event then Qt.IgnoreAction will be returned.
+
+ The returned drop action may be one of:
+
+ \list
+ \o Qt.CopyAction Copy the data to the target
+ \o Qt.MoveAction Move the data from the source to the target
+ \o Qt.LinkAction Create a link from the source to the target.
+ \o Qt.IgnoreAction Ignore the action (do nothing with the data).
+ \endlist
+
+*/
+
+int QQuickDragAttached::drop()
+{
+ Q_D(QQuickDragAttached);
+ Qt::DropAction acceptedAction = Qt::IgnoreAction;
+
+ if (!d->active)
+ return acceptedAction;
+
+ QObject *target = 0;
+
+ if (QQuickCanvas *canvas = d->attachedItem->canvas()) {
+ QPoint scenePos = d->attachedItem->mapToScene(d->hotSpot).toPoint();
+
+ QDropEvent event(
+ scenePos, d->mimeData->m_supportedActions, d->mimeData, Qt::NoButton, Qt::NoModifier);
+ QQuickDropEventEx::setProposedAction(&event, d->proposedAction);
+ QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+
+ if (event.isAccepted()) {
+ acceptedAction = event.dropAction();
+ target = d->dragGrabber.target();
+ }
+ }
+
+ d->active = false;
+ if (d->target != target) {
+ d->target = target;
+ emit targetChanged();
+ }
+
+ emit activeChanged();
+ return acceptedAction;
+}
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::cancel()
+
+ Ends a drag sequence.
+*/
+
+void QQuickDragAttached::cancel()
+{
+ Q_D(QQuickDragAttached);
+ if (!d->active)
+ return;
+
+ if (QQuickCanvas *canvas = d->attachedItem->canvas()) {
+ QDragLeaveEvent event;
+ QQuickCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+ }
+
+ d->active = false;
+ if (d->target) {
+ d->target = 0;
+ emit targetChanged();
+ }
+ emit activeChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
new file mode 100644
index 0000000000..830c665899
--- /dev/null
+++ b/src/quick/items/qquickdrag_p.h
@@ -0,0 +1,206 @@
+// Commit: c6e6a35aeb8794d68a3ca0c4e27a3a1181c066b5
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKDRAG_P_H
+#define QQUICKDRAG_P_H
+
+#include <QtQuick/qquickitem.h>
+
+#include <private/qv8engine_p.h>
+
+#include <QtCore/qmimedata.h>
+#include <QtCore/qstringlist.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickDrag;
+class QQuickDragPrivate;
+
+class QQuickDragGrabber
+{
+ class Item : public QDeclarativeGuard<QQuickItem>
+ {
+ public:
+ Item(QQuickItem *item) : QDeclarativeGuard<QQuickItem>(item) {}
+
+ QIntrusiveListNode node;
+ protected:
+ void objectDestroyed(QQuickItem *) { delete this; }
+ };
+
+ typedef QIntrusiveList<Item, &Item::node> ItemList;
+
+public:
+ QQuickDragGrabber() : m_target(0) {}
+ ~QQuickDragGrabber() { while (!m_items.isEmpty()) delete m_items.first(); }
+
+
+ QObject *target() const
+ {
+ if (m_target)
+ return m_target;
+ else if (!m_items.isEmpty())
+ return *m_items.first();
+ else
+ return 0;
+ }
+ void setTarget(QObject *target) { m_target = target; }
+ void resetTarget() { m_target = 0; }
+
+ typedef ItemList::iterator iterator;
+ iterator begin() { return m_items.begin(); }
+ iterator end() { return m_items.end(); }
+
+ void grab(QQuickItem *item) { m_items.insert(new Item(item)); }
+ iterator release(iterator at) { Item *item = *at; at = at.erase(); delete item; return at; }
+
+private:
+
+ ItemList m_items;
+ QObject *m_target;
+};
+
+class QQuickDropEventEx : public QDropEvent
+{
+public:
+ void setProposedAction(Qt::DropAction action) { default_action = action; drop_action = action; }
+
+ static void setProposedAction(QDropEvent *event, Qt::DropAction action) {
+ static_cast<QQuickDropEventEx *>(event)->setProposedAction(action);
+ }
+
+ void copyActions(const QDropEvent &from) {
+ default_action = from.proposedAction(); drop_action = from.dropAction(); }
+
+ static void copyActions(QDropEvent *to, const QDropEvent &from) {
+ static_cast<QQuickDropEventEx *>(to)->copyActions(from);
+ }
+};
+
+class QQuickDragMimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ QQuickDragMimeData()
+ : m_source(0)
+ {
+ }
+
+ QStringList keys() const { return m_keys; }
+ QObject *source() const { return m_source; }
+
+private:
+ QObject *m_source;
+ Qt::DropActions m_supportedActions;
+ QStringList m_keys;
+
+ friend class QQuickDragAttached;
+ friend class QQuickDragAttachedPrivate;
+};
+
+class QDeclarativeV8Function;
+
+class QQuickDragAttachedPrivate;
+class QQuickDragAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
+ Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
+ Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
+ Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
+ Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
+ Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
+public:
+ QQuickDragAttached(QObject *parent);
+ ~QQuickDragAttached();
+
+ bool isActive() const;
+ void setActive(bool active);
+
+ QObject *source() const;
+ void setSource(QObject *item);
+ void resetSource();
+
+ QObject *target() const;
+
+ QPointF hotSpot() const;
+ void setHotSpot(const QPointF &hotSpot);
+
+ QStringList keys() const;
+ void setKeys(const QStringList &keys);
+
+ Qt::DropActions supportedActions() const;
+ void setSupportedActions(Qt::DropActions actions);
+
+ Qt::DropAction proposedAction() const;
+ void setProposedAction(Qt::DropAction action);
+
+ Q_INVOKABLE int drop();
+
+public Q_SLOTS:
+ void start(QDeclarativeV8Function *);
+ void cancel();
+
+Q_SIGNALS:
+ void activeChanged();
+ void sourceChanged();
+ void targetChanged();
+ void hotSpotChanged();
+ void keysChanged();
+ void supportedActionsChanged();
+ void proposedActionChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickDragAttached)
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index 6ea1467e41..6ea1467e41 100644
--- a/src/declarative/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
new file mode 100644
index 0000000000..6662b21faf
--- /dev/null
+++ b/src/quick/items/qquickdroparea_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKDROPAREA_P_H
+#define QQUICKDROPAREA_P_H
+
+#include "qquickitem.h"
+
+#include <private/qdeclarativeguard_p.h>
+#include <private/qv8engine_p.h>
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDropAreaPrivate;
+class QQuickDropEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x)
+ Q_PROPERTY(qreal y READ y)
+ Q_PROPERTY(QObject *source READ source)
+ Q_PROPERTY(QStringList keys READ keys)
+ Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions)
+ Q_PROPERTY(Qt::DropAction action READ action WRITE setAction RESET resetAction)
+ Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
+public:
+ QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
+
+ qreal x() const { return event->pos().x(); }
+ qreal y() const { return event->pos().y(); }
+
+ QObject *source();
+
+ Qt::DropActions supportedActions() const { return event->possibleActions(); }
+ Qt::DropAction action() const { return event->dropAction(); }
+ void setAction(Qt::DropAction action) { event->setDropAction(action); }
+ void resetAction() { event->setDropAction(event->proposedAction()); }
+
+ QStringList keys() const;
+
+ bool accepted() const { return event->isAccepted(); }
+ void setAccepted(bool accepted) { event->setAccepted(accepted); }
+
+ Q_INVOKABLE void accept(QDeclarativeV8Function *);
+
+private:
+ QQuickDropAreaPrivate *d;
+ QDropEvent *event;
+};
+
+class QQuickDropAreaDrag : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x NOTIFY positionChanged)
+ Q_PROPERTY(qreal y READ y NOTIFY positionChanged)
+ Q_PROPERTY(QObject *source READ source NOTIFY sourceChanged)
+public:
+ QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent = 0);
+ ~QQuickDropAreaDrag();
+
+ qreal x() const;
+ qreal y() const;
+ QObject *source() const;
+
+Q_SIGNALS:
+ void positionChanged();
+ void sourceChanged();
+
+private:
+ QQuickDropAreaPrivate *d;
+
+ friend class QQuickDropArea;
+ friend class QQuickDropAreaPrivate;
+};
+
+class QQuickDropAreaPrivate;
+class Q_AUTOTEST_EXPORT QQuickDropArea : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool containsDrag READ containsDrag NOTIFY containsDragChanged)
+ Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
+ Q_PROPERTY(QQuickDropAreaDrag *drag READ drag CONSTANT)
+
+public:
+ QQuickDropArea(QQuickItem *parent=0);
+ ~QQuickDropArea();
+
+ bool containsDrag() const;
+ void setContainsDrag(bool drag);
+
+ QStringList keys() const;
+ void setKeys(const QStringList &keys);
+
+ QQuickDropAreaDrag *drag();
+
+Q_SIGNALS:
+ void containsDragChanged();
+ void keysChanged();
+ void sourceChanged();
+
+ void entered(QQuickDropEvent *drag);
+ void exited();
+ void positionChanged(QQuickDropEvent *drag);
+ void dropped(QQuickDropEvent *drop);
+
+protected:
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+
+private:
+ Q_DISABLE_COPY(QQuickDropArea)
+ Q_DECLARE_PRIVATE(QQuickDropArea)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickDropEvent)
+QML_DECLARE_TYPE(QQuickDropArea)
+
+QT_END_HEADER
+
+#endif // QQUICKDROPAREA_P_H
diff --git a/src/declarative/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index c546dd305a..c546dd305a 100644
--- a/src/declarative/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
new file mode 100644
index 0000000000..81eb0dfd06
--- /dev/null
+++ b/src/quick/items/qquickevents_p_p.h
@@ -0,0 +1,145 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKEVENTS_P_P_H
+#define QQUICKEVENTS_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/qtquickglobal.h>
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickKeyEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key)
+ Q_PROPERTY(QString text READ text)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QQuickKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
+ : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
+ QQuickKeyEvent(const QKeyEvent &ke)
+ : event(ke) { event.setAccepted(false); }
+
+ int key() const { return event.key(); }
+ QString text() const { return event.text(); }
+ int modifiers() const { return event.modifiers(); }
+ bool isAutoRepeat() const { return event.isAutoRepeat(); }
+ int count() const { return event.count(); }
+
+ bool isAccepted() { return event.isAccepted(); }
+ void setAccepted(bool accepted) { event.setAccepted(accepted); }
+
+private:
+ QKeyEvent event;
+};
+
+// used in QtLocation
+class Q_QUICK_EXPORT QQuickMouseEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x)
+ Q_PROPERTY(qreal y READ y)
+ Q_PROPERTY(int button READ button)
+ Q_PROPERTY(int buttons READ buttons)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool wasHeld READ wasHeld)
+ Q_PROPERTY(bool isClick READ isClick)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QQuickMouseEvent(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
+ , bool isClick=false, bool wasHeld=false)
+ : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
+ , _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
+
+ qreal x() const { return _x; }
+ qreal y() const { return _y; }
+ int button() const { return _button; }
+ int buttons() const { return _buttons; }
+ int modifiers() const { return _modifiers; }
+ bool wasHeld() const { return _wasHeld; }
+ bool isClick() const { return _isClick; }
+
+ // only for internal usage
+ void setX(qreal x) { _x = x; }
+ void setY(qreal y) { _y = y; }
+ void setPosition(const QPointF &point) { _x = point.x(); _y = point.y(); }
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+private:
+ qreal _x;
+ qreal _y;
+ Qt::MouseButton _button;
+ Qt::MouseButtons _buttons;
+ Qt::KeyboardModifiers _modifiers;
+ bool _wasHeld;
+ bool _isClick;
+ bool _accepted;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickKeyEvent)
+QML_DECLARE_TYPE(QQuickMouseEvent)
+
+#endif // QQUICKEVENTS_P_P_H
diff --git a/src/declarative/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index aca3542a92..aca3542a92 100644
--- a/src/declarative/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
new file mode 100644
index 0000000000..63ff72c598
--- /dev/null
+++ b/src/quick/items/qquickflickable_p.h
@@ -0,0 +1,275 @@
+// Commit: 1bcddaaf318fc37c71c5191913f3487c49444ec6
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKFLICKABLE_P_H
+#define QQUICKFLICKABLE_P_H
+
+#include "qquickitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickFlickablePrivate;
+class QQuickFlickableVisibleArea;
+class Q_DECLARATIVE_EXPORT QQuickFlickable : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
+ Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
+ Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
+ Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT)
+
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal yOrigin READ yOrigin NOTIFY yOriginChanged)
+
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal xOrigin READ xOrigin NOTIFY xOriginChanged)
+
+ Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
+ Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
+
+ Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged)
+ Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
+ Q_PROPERTY(bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+ Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
+ Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
+ Q_PROPERTY(bool dragging READ isDragging NOTIFY draggingChanged)
+ Q_PROPERTY(bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
+ Q_PROPERTY(bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
+ Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged)
+
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+ Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
+
+ Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged)
+
+ Q_PROPERTY(QQuickFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+
+ Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
+
+ Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickItem> flickableChildren READ flickableChildren)
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+ Q_ENUMS(FlickableDirection)
+ Q_ENUMS(BoundsBehavior)
+
+public:
+ QQuickFlickable(QQuickItem *parent=0);
+ ~QQuickFlickable();
+
+ QDeclarativeListProperty<QObject> flickableData();
+ QDeclarativeListProperty<QQuickItem> flickableChildren();
+
+ enum BoundsBehavior { StopAtBounds, DragOverBounds, DragAndOvershootBounds };
+ BoundsBehavior boundsBehavior() const;
+ void setBoundsBehavior(BoundsBehavior);
+
+ qreal contentWidth() const;
+ void setContentWidth(qreal);
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal);
+
+ qreal contentX() const;
+ virtual void setContentX(qreal pos);
+
+ qreal contentY() const;
+ virtual void setContentY(qreal pos);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal m);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal m);
+
+ qreal leftMargin() const;
+ void setLeftMargin(qreal m);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal m);
+
+ virtual qreal yOrigin() const;
+ virtual qreal xOrigin() const;
+
+ bool isMoving() const;
+ bool isMovingHorizontally() const;
+ bool isMovingVertically() const;
+ bool isFlicking() const;
+ bool isFlickingHorizontally() const;
+ bool isFlickingVertically() const;
+ bool isDragging() const;
+ bool isDraggingHorizontally() const;
+ bool isDraggingVertically() const;
+
+ int pressDelay() const;
+ void setPressDelay(int delay);
+
+ qreal maximumFlickVelocity() const;
+ void setMaximumFlickVelocity(qreal);
+
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
+ qreal horizontalVelocity() const;
+ qreal verticalVelocity() const;
+
+ bool isAtXEnd() const;
+ bool isAtXBeginning() const;
+ bool isAtYEnd() const;
+ bool isAtYBeginning() const;
+
+ QQuickItem *contentItem();
+
+ enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ FlickableDirection flickableDirection() const;
+ void setFlickableDirection(FlickableDirection);
+
+ bool pixelAligned() const;
+ void setPixelAligned(bool align);
+
+ Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center);
+ Q_INVOKABLE void returnToBounds();
+
+Q_SIGNALS:
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void contentXChanged();
+ void contentYChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void yOriginChanged();
+ void xOriginChanged();
+ void movingChanged();
+ void movingHorizontallyChanged();
+ void movingVerticallyChanged();
+ void flickingChanged();
+ void flickingHorizontallyChanged();
+ void flickingVerticallyChanged();
+ void draggingChanged();
+ void draggingHorizontallyChanged();
+ void draggingVerticallyChanged();
+ void horizontalVelocityChanged();
+ void verticalVelocityChanged();
+ void isAtBoundaryChanged();
+ void flickableDirectionChanged();
+ void interactiveChanged();
+ void boundsBehaviorChanged();
+ void maximumFlickVelocityChanged();
+ void flickDecelerationChanged();
+ void pressDelayChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+ void dragStarted();
+ void dragEnded();
+ void pixelAlignedChanged();
+
+protected:
+ virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void wheelEvent(QWheelEvent *event);
+ virtual void timerEvent(QTimerEvent *event);
+
+ QQuickFlickableVisibleArea *visibleArea();
+
+protected Q_SLOTS:
+ virtual void ticked();
+ void movementStarting();
+ void movementEnding();
+
+protected:
+ void movementXEnding();
+ void movementYEnding();
+ virtual qreal minXExtent() const;
+ virtual qreal minYExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual qreal maxYExtent() const;
+ qreal vWidth() const;
+ qreal vHeight() const;
+ virtual void componentComplete();
+ virtual void viewportMoved();
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ void mouseUngrabEvent();
+ bool sendMouseEvent(QMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+ void cancelFlick();
+
+protected:
+ QQuickFlickable(QQuickFlickablePrivate &dd, QQuickItem *parent);
+
+private:
+ Q_DISABLE_COPY(QQuickFlickable)
+ Q_DECLARE_PRIVATE(QQuickFlickable)
+ friend class QQuickFlickableVisibleArea;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickFlickable)
+
+QT_END_HEADER
+
+#endif // QQUICKFLICKABLE_P_H
diff --git a/src/declarative/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 8ceea6162f..8ceea6162f 100644
--- a/src/declarative/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
diff --git a/src/declarative/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp
index ed89f2aaf5..ed89f2aaf5 100644
--- a/src/declarative/items/qquickflipable.cpp
+++ b/src/quick/items/qquickflipable.cpp
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
new file mode 100644
index 0000000000..9a39b95fbd
--- /dev/null
+++ b/src/quick/items/qquickflipable_p.h
@@ -0,0 +1,102 @@
+// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKFLIPABLE_P_H
+#define QQUICKFLIPABLE_P_H
+
+#include "qquickitem.h"
+
+#include <QtGui/qtransform.h>
+#include <QtGui/qvector3d.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickFlipablePrivate;
+class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side)
+ Q_PROPERTY(QQuickItem *front READ front WRITE setFront NOTIFY frontChanged)
+ Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+ //### flipAxis
+ //### flipRotation
+public:
+ QQuickFlipable(QQuickItem *parent=0);
+ ~QQuickFlipable();
+
+ QQuickItem *front();
+ void setFront(QQuickItem *);
+
+ QQuickItem *back();
+ void setBack(QQuickItem *);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+Q_SIGNALS:
+ void frontChanged();
+ void backChanged();
+ void sideChanged();
+
+protected:
+ virtual void updatePolish();
+
+private Q_SLOTS:
+ void retransformBack();
+
+private:
+ Q_DISABLE_COPY(QQuickFlipable)
+ Q_DECLARE_PRIVATE(QQuickFlipable)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickFlipable)
+
+QT_END_HEADER
+
+#endif // QQUICKFLIPABLE_P_H
diff --git a/src/declarative/items/qquickfocusscope.cpp b/src/quick/items/qquickfocusscope.cpp
index b807fe58f6..b807fe58f6 100644
--- a/src/declarative/items/qquickfocusscope.cpp
+++ b/src/quick/items/qquickfocusscope.cpp
diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h
new file mode 100644
index 0000000000..472aceed33
--- /dev/null
+++ b/src/quick/items/qquickfocusscope_p.h
@@ -0,0 +1,66 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKFOCUSSCOPE_P_H
+#define QQUICKFOCUSSCOPE_P_H
+
+#include "qquickitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QQuickFocusScope : public QQuickItem
+{
+ Q_OBJECT
+public:
+ QQuickFocusScope(QQuickItem *parent=0);
+ virtual ~QQuickFocusScope();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickFocusScope)
+
+QT_END_HEADER
+
+#endif // QQUICKFOCUSSCOPE_P_H
diff --git a/src/declarative/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 44e1f14c6f..44e1f14c6f 100644
--- a/src/declarative/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
new file mode 100644
index 0000000000..729c6e433e
--- /dev/null
+++ b/src/quick/items/qquickgridview_p.h
@@ -0,0 +1,145 @@
+// Commit: 95814418f9d6adeba365c795462e8afb00138211
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKGRIDVIEW_P_H
+#define QQUICKGRIDVIEW_P_H
+
+#include "qquickitemview_p.h"
+
+#include <private/qdeclarativeguard_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickVisualModel;
+class QQuickGridViewAttached;
+class QQuickGridViewPrivate;
+class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickGridView)
+
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
+ Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
+
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
+
+ Q_ENUMS(SnapMode)
+ Q_ENUMS(Flow)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QQuickGridView(QQuickItem *parent=0);
+ ~QQuickGridView();
+
+ virtual void setHighlightFollowsCurrentItem(bool);
+ virtual void setHighlightMoveDuration(int);
+
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ qreal cellWidth() const;
+ void setCellWidth(qreal);
+
+ qreal cellHeight() const;
+ void setCellHeight(qreal);
+
+ enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ static QQuickGridViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void moveCurrentIndexUp();
+ void moveCurrentIndexDown();
+ void moveCurrentIndexLeft();
+ void moveCurrentIndexRight();
+
+Q_SIGNALS:
+ void cellWidthChanged();
+ void cellHeightChanged();
+ void highlightMoveDurationChanged();
+ void flowChanged();
+ void snapModeChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual void keyPressEvent(QKeyEvent *);
+};
+
+class QQuickGridViewAttached : public QQuickItemViewAttached
+{
+ Q_OBJECT
+public:
+ QQuickGridViewAttached(QObject *parent)
+ : QQuickItemViewAttached(parent), m_view(0) {}
+ ~QQuickGridViewAttached() {}
+
+ Q_PROPERTY(QQuickGridView *view READ view NOTIFY viewChanged)
+ QQuickGridView *view() { return m_view; }
+ void setView(QQuickGridView *view) {
+ if (view != m_view) {
+ m_view = view;
+ emit viewChanged();
+ }
+ }
+
+Q_SIGNALS:
+ void viewChanged();
+
+public:
+ QDeclarativeGuard<QQuickGridView> m_view;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickGridView)
+QML_DECLARE_TYPEINFO(QQuickGridView, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QQUICKGRIDVIEW_P_H
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
new file mode 100644
index 0000000000..19a8ef1199
--- /dev/null
+++ b/src/quick/items/qquickimage.cpp
@@ -0,0 +1,746 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickimage_p.h"
+#include "qquickimage_p_p.h"
+
+#include <QtQuick/private/qsgtextureprovider_p.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+#include <QtGui/qpainter.h>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickImageTextureProvider : public QSGTextureProvider
+{
+ Q_OBJECT
+public:
+ QQuickImageTextureProvider()
+ : m_texture(0)
+ , m_smooth(false)
+ {
+ }
+
+ QSGTexture *texture() const {
+
+ if (m_texture && m_texture->isAtlasTexture())
+ const_cast<QQuickImageTextureProvider *>(this)->m_texture = m_texture->removedFromAtlas();
+
+ if (m_texture) {
+ m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
+ m_texture->setMipmapFiltering(QSGTexture::Nearest);
+ m_texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ m_texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ }
+ return m_texture;
+ }
+
+ friend class QQuickImage;
+
+ QSGTexture *m_texture;
+ bool m_smooth;
+};
+
+#include "qquickimage.moc"
+
+QQuickImagePrivate::QQuickImagePrivate()
+ : fillMode(QQuickImage::Stretch)
+ , paintedWidth(0)
+ , paintedHeight(0)
+ , pixmapChanged(false)
+ , hAlign(QQuickImage::AlignHCenter)
+ , vAlign(QQuickImage::AlignVCenter)
+ , provider(0)
+{
+}
+
+/*!
+ \qmlclass Image QQuickImage
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Image element displays an image in a declarative user interface
+ \inherits Item
+
+ The Image element is used to display images in a declarative user interface.
+
+ The source of the image is specified as a URL using the \l source property.
+ Images can be supplied in any of the standard image formats supported by Qt,
+ including bitmap formats such as PNG and JPEG, and vector graphics formats
+ such as SVG. If you need to display animated images, use the \l AnimatedImage
+ element.
+
+ If the \l{Item::width}{width} and \l{Item::height}{height} properties are not
+ specified, the Image element automatically uses the size of the loaded image.
+ By default, specifying the width and height of the element causes the image
+ to be scaled to that size. This behavior can be changed by setting the
+ \l fillMode property, allowing the image to be stretched and tiled instead.
+
+ \section1 Example Usage
+
+ The following example shows the simplest usage of the Image element.
+
+ \snippet doc/src/snippets/declarative/image.qml document
+
+ \beginfloatleft
+ \image declarative-qtlogo.png
+ \endfloat
+
+ \clearfloat
+
+ \section1 Performance
+
+ By default, locally available images are loaded immediately, and the user interface
+ is blocked until loading is complete. If a large image is to be loaded, it may be
+ preferable to load the image in a low priority thread, by enabling the \l asynchronous
+ property.
+
+ If the image is obtained from a network rather than a local resource, it is
+ automatically loaded asynchronously, and the \l progress and \l status properties
+ are updated as appropriate.
+
+ Images are cached and shared internally, so if several Image elements have the same \l source,
+ only one copy of the image will be loaded.
+
+ \bold Note: Images are often the greatest user of memory in QML user interfaces. It is recommended
+ that images which do not form part of the user interface have their
+ size bounded via the \l sourceSize property. This is especially important for content
+ that is loaded from external sources or provided by the user.
+
+ \sa {declarative/imageelements/image}{Image example}, QDeclarativeImageProvider
+*/
+
+QQuickImage::QQuickImage(QQuickItem *parent)
+ : QQuickImageBase(*(new QQuickImagePrivate), parent)
+{
+}
+
+QQuickImage::QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent)
+ : QQuickImageBase(dd, parent)
+{
+}
+
+QQuickImage::~QQuickImage()
+{
+ Q_D(QQuickImage);
+ if (d->provider)
+ d->provider->deleteLater();
+}
+
+void QQuickImagePrivate::setImage(const QImage &image)
+{
+ Q_Q(QQuickImage);
+ pix.setImage(image);
+
+ q->pixmapChange();
+ status = pix.isNull() ? QQuickImageBase::Null : QQuickImageBase::Ready;
+
+ q->update();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Image::fillMode
+
+ Set this property to define what happens when the source image has a different size
+ than the item.
+
+ \list
+ \o Image.Stretch - the image is scaled to fit
+ \o Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping
+ \o Image.PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary
+ \o Image.Tile - the image is duplicated horizontally and vertically
+ \o Image.TileVertically - the image is stretched horizontally and tiled vertically
+ \o Image.TileHorizontally - the image is stretched vertically and tiled horizontally
+ \o Image.Pad - the image is not transformed
+ \endlist
+
+ \table
+
+ \row
+ \o \image declarative-qtlogo-stretch.png
+ \o Stretch (default)
+ \qml
+ Image {
+ width: 130; height: 100
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-preserveaspectfit.png
+ \o PreserveAspectFit
+ \qml
+ Image {
+ width: 130; height: 100
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-preserveaspectcrop.png
+ \o PreserveAspectCrop
+ \qml
+ Image {
+ width: 130; height: 100
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ source: "qtlogo.png"
+ clip: true
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tile.png
+ \o Tile
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.Tile
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tilevertically.png
+ \o TileVertically
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.TileVertically
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tilehorizontally.png
+ \o TileHorizontally
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.TileHorizontally
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \endtable
+
+ Note that \c clip is \c false by default which means that the element might
+ paint outside its bounding rectangle even if the fillMode is set to \c PreserveAspectCrop.
+
+ \sa {declarative/imageelements/image}{Image example}
+*/
+QQuickImage::FillMode QQuickImage::fillMode() const
+{
+ Q_D(const QQuickImage);
+ return d->fillMode;
+}
+
+void QQuickImage::setFillMode(FillMode mode)
+{
+ Q_D(QQuickImage);
+ if (d->fillMode == mode)
+ return;
+ d->fillMode = mode;
+ update();
+ updatePaintedGeometry();
+ emit fillModeChanged();
+}
+
+/*!
+
+ \qmlproperty real QtQuick2::Image::paintedWidth
+ \qmlproperty real QtQuick2::Image::paintedHeight
+
+ These properties hold the size of the image that is actually painted.
+ In most cases it is the same as \c width and \c height, but when using a
+ \c fillMode \c PreserveAspectFit or \c fillMode \c PreserveAspectCrop
+ \c paintedWidth or \c paintedHeight can be smaller or larger than
+ \c width and \c height of the Image element.
+*/
+qreal QQuickImage::paintedWidth() const
+{
+ Q_D(const QQuickImage);
+ return d->paintedWidth;
+}
+
+qreal QQuickImage::paintedHeight() const
+{
+ Q_D(const QQuickImage);
+ return d->paintedHeight;
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Image.Null - no image has been set
+ \o Image.Ready - the image has been loaded
+ \o Image.Loading - the image is currently being loaded
+ \o Image.Error - an error occurred while loading the image
+ \endlist
+
+ Use this status to provide an update or respond to the status change in some way.
+ For example, you could:
+
+ \list
+ \o Trigger a state change:
+ \qml
+ State { name: 'loaded'; when: image.status == Image.Ready }
+ \endqml
+
+ \o Implement an \c onStatusChanged signal handler:
+ \qml
+ Image {
+ id: image
+ onStatusChanged: if (image.status == Image.Ready) console.log('Loaded')
+ }
+ \endqml
+
+ \o Bind to the status value:
+ \qml
+ Text { text: image.status == Image.Ready ? 'Loaded' : 'Not loaded' }
+ \endqml
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Image::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty QSize QtQuick2::Image::sourceSize
+
+ This property holds the actual width and height of the loaded image.
+
+ Unlike the \l {Item::}{width} and \l {Item::}{height} properties, which scale
+ the painting of the image, this property sets the actual number of pixels
+ stored for the loaded image so that large images do not use more
+ memory than necessary. For example, this ensures the image in memory is no
+ larger than 1024x1024 pixels, regardless of the Image's \l {Item::}{width} and
+ \l {Item::}{height} values:
+
+ \code
+ Rectangle {
+ width: ...
+ height: ...
+
+ Image {
+ anchors.fill: parent
+ source: "reallyBigImage.jpg"
+ sourceSize.width: 1024
+ sourceSize.height: 1024
+ }
+ }
+ \endcode
+
+ If the image's actual size is larger than the sourceSize, the image is scaled down.
+ If only one dimension of the size is set to greater than 0, the
+ other dimension is set in proportion to preserve the source image's aspect ratio.
+ (The \l fillMode is independent of this.)
+
+ If the source is an intrinsically scalable image (eg. SVG), this property
+ determines the size of the loaded image regardless of intrinsic size.
+ Avoid changing this property dynamically; rendering an SVG is \e slow compared
+ to an image.
+
+ If the source is a non-scalable image (eg. JPEG), the loaded image will
+ be no greater than this property specifies. For some formats (currently only JPEG),
+ the whole image will never actually be loaded into memory.
+
+ Since QtQuick 1.1 the sourceSize can be cleared to the natural size of the image
+ by setting sourceSize to \c undefined.
+
+ \note \e {Changing this property dynamically causes the image source to be reloaded,
+ potentially even from the network, if it is not in the disk cache.}
+*/
+
+/*!
+ \qmlproperty url QtQuick2::Image::source
+
+ Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ The URL may be absolute, or relative to the URL of the component.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Image::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchronously.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Image::cache
+
+ Specifies whether the image should be cached. The default value is
+ true. Setting \a cache to false is useful when dealing with large images,
+ to make sure that they aren't cached at the expense of small 'ui element' images.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Image::mirror
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Image::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::Image::verticalAlignment
+
+ Sets the horizontal and vertical alignment of the image. By default, the image is top-left aligned.
+
+ The valid values for \c horizontalAlignment are \c Image.AlignLeft, \c Image.AlignRight and \c Image.AlignHCenter.
+ The valid values for \c verticalAlignment are \c Image.AlignTop, \c Image.AlignBottom
+ and \c Image.AlignVCenter.
+*/
+void QQuickImage::updatePaintedGeometry()
+{
+ Q_D(QQuickImage);
+
+ if (d->fillMode == PreserveAspectFit) {
+ if (!d->pix.width() || !d->pix.height()) {
+ setImplicitSize(0, 0);
+ return;
+ }
+ qreal w = widthValid() ? width() : d->pix.width();
+ qreal widthScale = w / qreal(d->pix.width());
+ qreal h = heightValid() ? height() : d->pix.height();
+ qreal heightScale = h / qreal(d->pix.height());
+ if (widthScale <= heightScale) {
+ d->paintedWidth = w;
+ d->paintedHeight = widthScale * qreal(d->pix.height());
+ } else if (heightScale < widthScale) {
+ d->paintedWidth = heightScale * qreal(d->pix.width());
+ d->paintedHeight = h;
+ }
+ qreal iHeight = (widthValid() && !heightValid()) ? d->paintedHeight : d->pix.height();
+ qreal iWidth = (heightValid() && !widthValid()) ? d->paintedWidth : d->pix.width();
+ setImplicitSize(iWidth, iHeight);
+
+ } else if (d->fillMode == PreserveAspectCrop) {
+ if (!d->pix.width() || !d->pix.height())
+ return;
+ qreal widthScale = width() / qreal(d->pix.width());
+ qreal heightScale = height() / qreal(d->pix.height());
+ if (widthScale < heightScale) {
+ widthScale = heightScale;
+ } else if (heightScale < widthScale) {
+ heightScale = widthScale;
+ }
+
+ d->paintedHeight = heightScale * qreal(d->pix.height());
+ d->paintedWidth = widthScale * qreal(d->pix.width());
+ } else if (d->fillMode == Pad) {
+ d->paintedWidth = d->pix.width();
+ d->paintedHeight = d->pix.height();
+ } else {
+ d->paintedWidth = width();
+ d->paintedHeight = height();
+ }
+ emit paintedGeometryChanged();
+}
+
+void QQuickImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickImageBase::geometryChanged(newGeometry, oldGeometry);
+ updatePaintedGeometry();
+}
+
+QRectF QQuickImage::boundingRect() const
+{
+ Q_D(const QQuickImage);
+ return QRectF(0, 0, qMax(width(), d->paintedWidth), qMax(height(), d->paintedHeight));
+}
+
+QSGTextureProvider *QQuickImage::textureProvider() const
+{
+ Q_D(const QQuickImage);
+ if (!d->provider) {
+ // Make sure it gets thread affinity on the rendering thread so deletion works properly..
+ Q_ASSERT_X(d->canvas
+ && d->sceneGraphContext()
+ && QThread::currentThread() == d->sceneGraphContext()->thread(),
+ "QQuickImage::textureProvider",
+ "Cannot be used outside the GUI thread");
+ QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d);
+ dd->provider = new QQuickImageTextureProvider;
+ dd->provider->m_smooth = d->smooth;
+ dd->provider->m_texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory());
+ }
+
+ return d->provider;
+}
+
+QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ Q_D(QQuickImage);
+
+ QSGTexture *texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory());
+
+ // Copy over the current texture state into the texture provider...
+ if (d->provider) {
+ d->provider->m_smooth = d->smooth;
+ d->provider->m_texture = texture;
+ }
+
+ if (!texture || width() <= 0 || height() <= 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
+ if (!node) {
+ d->pixmapChanged = true;
+ node = d->sceneGraphContext()->createImageNode();
+ node->setTexture(texture);
+ }
+
+ if (d->pixmapChanged) {
+ // force update the texture in the node to trigger reconstruction of
+ // geometry and the likes when a atlas segment has changed.
+ node->setTexture(0);
+ node->setTexture(texture);
+ d->pixmapChanged = false;
+ }
+
+ QRectF targetRect;
+ QRectF sourceRect;
+ QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge;
+ QSGTexture::WrapMode vWrap = QSGTexture::ClampToEdge;
+
+ qreal pixWidth = (d->fillMode == PreserveAspectFit) ? d->paintedWidth : d->pix.width();
+ qreal pixHeight = (d->fillMode == PreserveAspectFit) ? d->paintedHeight : d->pix.height();
+
+ int xOffset = 0;
+ if (d->hAlign == QQuickImage::AlignHCenter)
+ xOffset = qCeil((width() - pixWidth) / 2.);
+ else if (d->hAlign == QQuickImage::AlignRight)
+ xOffset = qCeil(width() - pixWidth);
+
+ int yOffset = 0;
+ if (d->vAlign == QQuickImage::AlignVCenter)
+ yOffset = qCeil((height() - pixHeight) / 2.);
+ else if (d->vAlign == QQuickImage::AlignBottom)
+ yOffset = qCeil(height() - pixHeight);
+
+ switch (d->fillMode) {
+ default:
+ case Stretch:
+ targetRect = QRectF(0, 0, width(), height());
+ sourceRect = d->pix.rect();
+ break;
+
+ case PreserveAspectFit:
+ targetRect = QRectF(xOffset, yOffset, d->paintedWidth, d->paintedHeight);
+ sourceRect = d->pix.rect();
+ break;
+
+ case PreserveAspectCrop: {
+ targetRect = QRect(0, 0, width(), height());
+ qreal wscale = width() / qreal(d->pix.width());
+ qreal hscale = height() / qreal(d->pix.height());
+
+ if (wscale > hscale) {
+ int src = (hscale / wscale) * qreal(d->pix.height());
+ int y = 0;
+ if (d->vAlign == QQuickImage::AlignVCenter)
+ y = qCeil((d->pix.height() - src) / 2.);
+ else if (d->vAlign == QQuickImage::AlignBottom)
+ y = qCeil(d->pix.height() - src);
+ sourceRect = QRectF(0, y, d->pix.width(), src);
+
+ } else {
+ int src = (wscale / hscale) * qreal(d->pix.width());
+ int x = 0;
+ if (d->hAlign == QQuickImage::AlignHCenter)
+ x = qCeil((d->pix.width() - src) / 2.);
+ else if (d->hAlign == QQuickImage::AlignRight)
+ x = qCeil(d->pix.width() - src);
+ sourceRect = QRectF(x, 0, src, d->pix.height());
+ }
+ }
+ break;
+
+ case Tile:
+ targetRect = QRectF(0, 0, width(), height());
+ sourceRect = QRectF(-xOffset, -yOffset, width(), height());
+ hWrap = QSGTexture::Repeat;
+ vWrap = QSGTexture::Repeat;
+ break;
+
+ case TileHorizontally:
+ targetRect = QRectF(0, 0, width(), height());
+ sourceRect = QRectF(-xOffset, 0, width(), d->pix.height());
+ hWrap = QSGTexture::Repeat;
+ break;
+
+ case TileVertically:
+ targetRect = QRectF(0, 0, width(), height());
+ sourceRect = QRectF(0, -yOffset, d->pix.width(), height());
+ vWrap = QSGTexture::Repeat;
+ break;
+
+ case Pad:
+ qreal w = qMin(qreal(d->pix.width()), width());
+ qreal h = qMin(qreal(d->pix.height()), height());
+ qreal x = (d->pix.width() > width()) ? -xOffset : 0;
+ qreal y = (d->pix.height() > height()) ? -yOffset : 0;
+ targetRect = QRectF(x + xOffset, y + yOffset, w, h);
+ sourceRect = QRectF(x, y, w, h);
+ break;
+ };
+
+ QRectF nsrect(sourceRect.x() / d->pix.width(),
+ sourceRect.y() / d->pix.height(),
+ sourceRect.width() / d->pix.width(),
+ sourceRect.height() / d->pix.height());
+
+ if (d->mirror) {
+ qreal oldLeft = nsrect.left();
+ nsrect.setLeft(nsrect.right());
+ nsrect.setRight(oldLeft);
+ }
+
+ node->setHorizontalWrapMode(hWrap);
+ node->setVerticalWrapMode(vWrap);
+ node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
+
+ node->setTargetRect(targetRect);
+ node->setSourceRect(nsrect);
+ node->update();
+
+ return node;
+}
+
+void QQuickImage::pixmapChange()
+{
+ Q_D(QQuickImage);
+ // PreserveAspectFit calculates the implicit size differently so we
+ // don't call our superclass pixmapChange(), since that would
+ // result in the implicit size being set incorrectly, then updated
+ // in updatePaintedGeometry()
+ if (d->fillMode != PreserveAspectFit)
+ QQuickImageBase::pixmapChange();
+ updatePaintedGeometry();
+ d->pixmapChanged = true;
+
+ // When the pixmap changes, such as being deleted, we need to update the textures
+ update();
+}
+
+QQuickImage::VAlignment QQuickImage::verticalAlignment() const
+{
+ Q_D(const QQuickImage);
+ return d->vAlign;
+}
+
+void QQuickImage::setVerticalAlignment(VAlignment align)
+{
+ Q_D(QQuickImage);
+ if (d->vAlign == align)
+ return;
+
+ d->vAlign = align;
+ update();
+ updatePaintedGeometry();
+ emit verticalAlignmentChanged(align);
+}
+
+QQuickImage::HAlignment QQuickImage::horizontalAlignment() const
+{
+ Q_D(const QQuickImage);
+ return d->hAlign;
+}
+
+void QQuickImage::setHorizontalAlignment(HAlignment align)
+{
+ Q_D(QQuickImage);
+ if (d->hAlign == align)
+ return;
+
+ d->hAlign = align;
+ update();
+ updatePaintedGeometry();
+ emit horizontalAlignmentChanged(align);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
new file mode 100644
index 0000000000..36b43079b0
--- /dev/null
+++ b/src/quick/items/qquickimage_p.h
@@ -0,0 +1,120 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKIMAGE_P_H
+#define QQUICKIMAGE_P_H
+
+#include "qquickimagebase_p.h"
+#include <QtQuick/private/qsgtextureprovider_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickImagePrivate;
+class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(FillMode)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+
+ Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
+
+public:
+ QQuickImage(QQuickItem *parent=0);
+ ~QQuickImage();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter };
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+
+ enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad };
+
+ FillMode fillMode() const;
+ void setFillMode(FillMode);
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ QRectF boundingRect() const;
+
+ HAlignment horizontalAlignment() const;
+ void setHorizontalAlignment(HAlignment align);
+
+ VAlignment verticalAlignment() const;
+ void setVerticalAlignment(VAlignment align);
+
+ bool isTextureProvider() const { return true; }
+ QSGTextureProvider *textureProvider() const;
+
+Q_SIGNALS:
+ void fillModeChanged();
+ void paintedGeometryChanged();
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+
+protected:
+ QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent);
+ void pixmapChange();
+ void updatePaintedGeometry();
+
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+private:
+ Q_DISABLE_COPY(QQuickImage)
+ Q_DECLARE_PRIVATE(QQuickImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QQuickImage)
+QT_END_HEADER
+
+#endif // QQUICKIMAGE_P_H
diff --git a/src/declarative/items/qquickimage_p_p.h b/src/quick/items/qquickimage_p_p.h
index 2077dfb0b3..2077dfb0b3 100644
--- a/src/declarative/items/qquickimage_p_p.h
+++ b/src/quick/items/qquickimage_p_p.h
diff --git a/src/declarative/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index d0e495eff5..d0e495eff5 100644
--- a/src/declarative/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
diff --git a/src/declarative/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 51b5f088d4..51b5f088d4 100644
--- a/src/declarative/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
new file mode 100644
index 0000000000..0045562ddc
--- /dev/null
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -0,0 +1,93 @@
+// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKIMAGEBASE_P_P_H
+#define QQUICKIMAGEBASE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickimplicitsizeitem_p_p.h"
+#include "qquickimagebase_p.h"
+
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QQuickImageBasePrivate : public QQuickImplicitSizeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickImageBase)
+
+public:
+ QQuickImageBasePrivate()
+ : status(QQuickImageBase::Null),
+ progress(0.0),
+ explicitSourceSize(false),
+ async(false),
+ cache(true),
+ mirror(false)
+ {
+ }
+
+ QDeclarativePixmap pix;
+ QQuickImageBase::Status status;
+ QUrl url;
+ qreal progress;
+ QSize sourcesize;
+ bool explicitSourceSize : 1;
+ bool async : 1;
+ bool cache : 1;
+ bool mirror: 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKIMAGEBASE_P_P_H
diff --git a/src/declarative/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp
index b0c5826349..b0c5826349 100644
--- a/src/declarative/items/qquickimplicitsizeitem.cpp
+++ b/src/quick/items/qquickimplicitsizeitem.cpp
diff --git a/src/declarative/items/qquickimplicitsizeitem_p.h b/src/quick/items/qquickimplicitsizeitem_p.h
index 9ca98e1d60..9ca98e1d60 100644
--- a/src/declarative/items/qquickimplicitsizeitem_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p.h
diff --git a/src/declarative/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h
index 17c204d7c3..17c204d7c3 100644
--- a/src/declarative/items/qquickimplicitsizeitem_p_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p_p.h
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
new file mode 100644
index 0000000000..a9409ecdf4
--- /dev/null
+++ b/src/quick/items/qquickitem.cpp
@@ -0,0 +1,5238 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickitem.h"
+
+#include "qquickcanvas.h"
+#include <QtDeclarative/qjsengine.h>
+#include "qquickcanvas_p.h"
+
+#include "qquickevents_p_p.h"
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtGui/qpen.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qinputpanel.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qnumeric.h>
+
+#include <private/qdeclarativeengine_p.h>
+#include <QtQuick/private/qdeclarativestategroup_p.h>
+#include <private/qdeclarativeopenmetaobject_p.h>
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qlistmodelinterface_p.h>
+#include <private/qquickitem_p.h>
+
+#include <float.h>
+
+// XXX todo Readd parentNotifier for faster parent bindings
+// XXX todo Check that elements that create items handle memory correctly after visual ownership change
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Transform QQuickTransform
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Transform elements provide a way of building advanced transformations on Items.
+
+ The Transform element is a base type which cannot be instantiated directly.
+ The following concrete Transform types are available:
+
+ \list
+ \o \l Rotation
+ \o \l Scale
+ \o \l Translate
+ \endlist
+
+ The Transform elements let you create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ You can assign any number of Transform elements to an \l Item. Each Transform is applied in order,
+ one at a time.
+*/
+
+/*!
+ \qmlclass Translate QQuickTranslate
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Translate object provides a way to move an Item without changing its x or y properties.
+
+ The Translate object provides independent control over position in addition to the Item's x and y properties.
+
+ The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element
+ to lay the items out as if they had not been transformed:
+ \qml
+ import QtQuick 1.0
+
+ Row {
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Translate { y: 20 }
+ }
+ Rectangle {
+ width: 100; height: 100
+ color: "red"
+ transform: Translate { y: -20 }
+ }
+ }
+ \endqml
+
+ \image translate.png
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Translate::x
+
+ The translation along the X axis.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Translate::y
+
+ The translation along the Y axis.
+*/
+
+/*!
+ \qmlclass Scale QQuickScale
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Scale element provides a way to scale an Item.
+
+ The Scale element gives more control over scaling than using \l Item's \l{Item::scale}{scale} property. Specifically,
+ it allows a different scale for the x and y axes, and allows the scale to be relative to an
+ arbitrary point.
+
+ The following example scales the X axis of the Rectangle, relative to its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
+ }
+ \endqml
+
+ \sa Rotation, Translate
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::origin.x
+ \qmlproperty real QtQuick2::Scale::origin.y
+
+ The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as
+ the rest of the item grows). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::xScale
+
+ The scaling factor for the X axis.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Scale::yScale
+
+ The scaling factor for the Y axis.
+*/
+
+/*!
+ \qmlclass Rotation QQuickRotation
+ \inqmlmodule QtQuick 2
+ \ingroup qml-transform-elements
+ \brief The Rotation object provides a way to rotate an Item.
+
+ The Rotation object gives more control over rotation than using \l Item's \l{Item::rotation}{rotation} property.
+ Specifically, it allows (z axis) rotation to be relative to an arbitrary point.
+
+ The following example rotates a Rectangle around its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
+ }
+ \endqml
+
+ Rotation also provides a way to specify 3D-like rotations for Items. For these types of
+ rotations you must specify the axis to rotate around in addition to the origin point.
+
+ The following example shows various 3D-like rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+
+ \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example}
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::origin.x
+ \qmlproperty real QtQuick2::Rotation::origin.y
+
+ The origin point of the rotation (i.e., the point that stays fixed relative to the parent as
+ the rest of the item rotates). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::axis.x
+ \qmlproperty real QtQuick2::Rotation::axis.y
+ \qmlproperty real QtQuick2::Rotation::axis.z
+
+ The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis,
+ as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }).
+
+ For a typical 3D-like rotation you will usually specify both the origin and the axis.
+
+ \image 3d-rotation-axis.png
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Rotation::angle
+
+ The angle to rotate, in degrees clockwise.
+*/
+
+QQuickTransformPrivate::QQuickTransformPrivate()
+{
+}
+
+QQuickTransform::QQuickTransform(QObject *parent)
+: QObject(*(new QQuickTransformPrivate), parent)
+{
+}
+
+QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
+: QObject(dd, parent)
+{
+}
+
+QQuickTransform::~QQuickTransform()
+{
+ Q_D(QQuickTransform);
+ for (int ii = 0; ii < d->items.count(); ++ii) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
+ p->transforms.removeOne(this);
+ p->dirty(QQuickItemPrivate::Transform);
+ }
+}
+
+void QQuickTransform::update()
+{
+ Q_D(QQuickTransform);
+ for (int ii = 0; ii < d->items.count(); ++ii) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
+ p->dirty(QQuickItemPrivate::Transform);
+ }
+}
+
+QQuickContents::QQuickContents(QQuickItem *item)
+: m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
+{
+}
+
+QQuickContents::~QQuickContents()
+{
+ QList<QQuickItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QQuickItem *child = children.at(i);
+ QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ }
+}
+
+bool QQuickContents::calcHeight(QQuickItem *changed)
+{
+ qreal oldy = m_y;
+ qreal oldheight = m_height;
+
+ if (changed) {
+ qreal top = oldy;
+ qreal bottom = oldy + oldheight;
+ qreal y = changed->y();
+ if (y + changed->height() > bottom)
+ bottom = y + changed->height();
+ if (y < top)
+ top = y;
+ m_y = top;
+ m_height = bottom - top;
+ } else {
+ qreal top = FLT_MAX;
+ qreal bottom = 0;
+ QList<QQuickItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QQuickItem *child = children.at(i);
+ qreal y = child->y();
+ if (y + child->height() > bottom)
+ bottom = y + child->height();
+ if (y < top)
+ top = y;
+ }
+ if (!children.isEmpty())
+ m_y = top;
+ m_height = qMax(bottom - top, qreal(0.0));
+ }
+
+ return (m_height != oldheight || m_y != oldy);
+}
+
+bool QQuickContents::calcWidth(QQuickItem *changed)
+{
+ qreal oldx = m_x;
+ qreal oldwidth = m_width;
+
+ if (changed) {
+ qreal left = oldx;
+ qreal right = oldx + oldwidth;
+ qreal x = changed->x();
+ if (x + changed->width() > right)
+ right = x + changed->width();
+ if (x < left)
+ left = x;
+ m_x = left;
+ m_width = right - left;
+ } else {
+ qreal left = FLT_MAX;
+ qreal right = 0;
+ QList<QQuickItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QQuickItem *child = children.at(i);
+ qreal x = child->x();
+ if (x + child->width() > right)
+ right = x + child->width();
+ if (x < left)
+ left = x;
+ }
+ if (!children.isEmpty())
+ m_x = left;
+ m_width = qMax(right - left, qreal(0.0));
+ }
+
+ return (m_width != oldwidth || m_x != oldx);
+}
+
+void QQuickContents::complete()
+{
+ QQuickItemPrivate::get(m_item)->addItemChangeListener(this, QQuickItemPrivate::Children);
+
+ QList<QQuickItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QQuickItem *child = children.at(i);
+ QQuickItemPrivate::get(child)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ //###what about changes to visibility?
+ }
+ calcGeometry();
+}
+
+void QQuickContents::updateRect()
+{
+ QQuickItemPrivate::get(m_item)->emitChildrenRectChanged(rectF());
+}
+
+void QQuickContents::itemGeometryChanged(QQuickItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_UNUSED(changed)
+ bool wChanged = false;
+ bool hChanged = false;
+ //### we can only pass changed if the left edge has moved left, or the right edge has moved right
+ if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x())
+ wChanged = calcWidth(/*changed*/);
+ if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y())
+ hChanged = calcHeight(/*changed*/);
+ if (wChanged || hChanged)
+ updateRect();
+}
+
+void QQuickContents::itemDestroyed(QQuickItem *item)
+{
+ if (item)
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ calcGeometry();
+}
+
+void QQuickContents::itemChildRemoved(QQuickItem *, QQuickItem *item)
+{
+ if (item)
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ calcGeometry();
+}
+
+void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item)
+{
+ if (item)
+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ calcGeometry(item);
+}
+
+QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
+: m_processPost(false), m_next(0)
+{
+ QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):0;
+ if (p) {
+ m_next = p->keyHandler;
+ p->keyHandler = this;
+ }
+}
+
+QQuickItemKeyFilter::~QQuickItemKeyFilter()
+{
+}
+
+void QQuickItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
+{
+ if (m_next) m_next->keyPressed(event, post);
+}
+
+void QQuickItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
+{
+ if (m_next) m_next->keyReleased(event, post);
+}
+
+void QQuickItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
+{
+ if (m_next)
+ m_next->inputMethodEvent(event, post);
+ else
+ event->ignore();
+}
+
+QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if (m_next) return m_next->inputMethodQuery(query);
+ return QVariant();
+}
+
+void QQuickItemKeyFilter::componentComplete()
+{
+ if (m_next) m_next->componentComplete();
+}
+/*!
+ \qmlclass KeyNavigation QQuickKeyNavigationAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The KeyNavigation attached property supports key navigation by arrow keys.
+
+ Key-based user interfaces commonly allow the use of arrow keys to navigate between
+ focusable items. The KeyNavigation attached property enables this behavior by providing a
+ convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
+
+ The following example provides key navigation for a 2x2 grid of items:
+
+ \snippet doc/src/snippets/declarative/keynavigation.qml 0
+
+ The top-left item initially receives focus by setting \l {Item::}{focus} to
+ \c true. When an arrow key is pressed, the focus will move to the
+ appropriate item, as defined by the value that has been set for
+ the KeyNavigation \l left, \l right, \l up or \l down properties.
+
+ Note that if a KeyNavigation attached property receives the key press and release
+ events for a requested arrow or tab key, the event is accepted and does not
+ propagate any further.
+
+ By default, KeyNavigation receives key events after the item to which it is attached.
+ If the item accepts the key event, the KeyNavigation attached property will not
+ receive an event for that key. Setting the \l priority property to
+ \c KeyNavigation.BeforeItem allows the event to be used for key navigation
+ before the item, rather than after.
+
+ If item to which the focus is switching is not enabled or visible, an attempt will
+ be made to skip this item and focus on the next. This is possible if there are
+ a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
+ or visible, they will also be skipped.
+
+ KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
+ \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
+ item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
+ This means that the above example could have been written, with the same behaviour, without specifing
+ KeyNavigation.right or KeyNavigation.down for any of the items.
+
+ \sa {Keys}{Keys attached property}
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::KeyNavigation::left
+ \qmlproperty Item QtQuick2::KeyNavigation::right
+ \qmlproperty Item QtQuick2::KeyNavigation::up
+ \qmlproperty Item QtQuick2::KeyNavigation::down
+ \qmlproperty Item QtQuick2::KeyNavigation::tab
+ \qmlproperty Item QtQuick2::KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the left, right, up or down cursor keys, or the
+ tab key are pressed.
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::KeyNavigation::tab
+ \qmlproperty Item QtQuick2::KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the Tab key or Shift+Tab key combination (Backtab) are pressed.
+*/
+
+QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
+: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
+ QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
+{
+ m_processPost = true;
+}
+
+QQuickKeyNavigationAttached *
+QQuickKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickKeyNavigationAttached(obj);
+}
+
+QQuickItem *QQuickKeyNavigationAttached::left() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->left;
+}
+
+void QQuickKeyNavigationAttached::setLeft(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->left == i)
+ return;
+ d->left = i;
+ d->leftSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->rightSet){
+ other->d_func()->right = qobject_cast<QQuickItem*>(parent());
+ emit other->rightChanged();
+ }
+ emit leftChanged();
+}
+
+QQuickItem *QQuickKeyNavigationAttached::right() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->right;
+}
+
+void QQuickKeyNavigationAttached::setRight(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->right == i)
+ return;
+ d->right = i;
+ d->rightSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->leftSet){
+ other->d_func()->left = qobject_cast<QQuickItem*>(parent());
+ emit other->leftChanged();
+ }
+ emit rightChanged();
+}
+
+QQuickItem *QQuickKeyNavigationAttached::up() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->up;
+}
+
+void QQuickKeyNavigationAttached::setUp(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->up == i)
+ return;
+ d->up = i;
+ d->upSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->downSet){
+ other->d_func()->down = qobject_cast<QQuickItem*>(parent());
+ emit other->downChanged();
+ }
+ emit upChanged();
+}
+
+QQuickItem *QQuickKeyNavigationAttached::down() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->down;
+}
+
+void QQuickKeyNavigationAttached::setDown(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->down == i)
+ return;
+ d->down = i;
+ d->downSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->upSet) {
+ other->d_func()->up = qobject_cast<QQuickItem*>(parent());
+ emit other->upChanged();
+ }
+ emit downChanged();
+}
+
+QQuickItem *QQuickKeyNavigationAttached::tab() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->tab;
+}
+
+void QQuickKeyNavigationAttached::setTab(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->tab == i)
+ return;
+ d->tab = i;
+ d->tabSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->backtabSet) {
+ other->d_func()->backtab = qobject_cast<QQuickItem*>(parent());
+ emit other->backtabChanged();
+ }
+ emit tabChanged();
+}
+
+QQuickItem *QQuickKeyNavigationAttached::backtab() const
+{
+ Q_D(const QQuickKeyNavigationAttached);
+ return d->backtab;
+}
+
+void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ if (d->backtab == i)
+ return;
+ d->backtab = i;
+ d->backtabSet = true;
+ QQuickKeyNavigationAttached* other =
+ qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
+ if (other && !other->d_func()->tabSet) {
+ other->d_func()->tab = qobject_cast<QQuickItem*>(parent());
+ emit other->tabChanged();
+ }
+ emit backtabChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::KeyNavigation::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o KeyNavigation.BeforeItem - process the key events before normal
+ item key processing. If the event is used for key navigation, it will be accepted and will not
+ be passed on to the item.
+ \o KeyNavigation.AfterItem (default) - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the KeyNavigation attached property handler.
+ \endlist
+*/
+QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
+{
+ return m_processPost ? AfterItem : BeforeItem;
+}
+
+void QQuickKeyNavigationAttached::setPriority(Priority order)
+{
+ bool processPost = order == AfterItem;
+ if (processPost != m_processPost) {
+ m_processPost = processPost;
+ emit priorityChanged();
+ }
+}
+
+void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ event->ignore();
+
+ if (post != m_processPost) {
+ QQuickItemKeyFilter::keyPressed(event, post);
+ return;
+ }
+
+ bool mirror = false;
+ switch (event->key()) {
+ case Qt::Key_Left: {
+ if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
+ mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ QQuickItem* leftItem = mirror ? d->right : d->left;
+ if (leftItem) {
+ setFocusNavigation(leftItem, mirror ? "right" : "left");
+ event->accept();
+ }
+ break;
+ }
+ case Qt::Key_Right: {
+ if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
+ mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ QQuickItem* rightItem = mirror ? d->left : d->right;
+ if (rightItem) {
+ setFocusNavigation(rightItem, mirror ? "left" : "right");
+ event->accept();
+ }
+ break;
+ }
+ case Qt::Key_Up:
+ if (d->up) {
+ setFocusNavigation(d->up, "up");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ setFocusNavigation(d->down, "down");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Tab:
+ if (d->tab) {
+ setFocusNavigation(d->tab, "tab");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Backtab:
+ if (d->backtab) {
+ setFocusNavigation(d->backtab, "backtab");
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
+}
+
+void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
+{
+ Q_D(QQuickKeyNavigationAttached);
+ event->ignore();
+
+ if (post != m_processPost) {
+ QQuickItemKeyFilter::keyReleased(event, post);
+ return;
+ }
+
+ bool mirror = false;
+ switch (event->key()) {
+ case Qt::Key_Left:
+ if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
+ mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ if (mirror ? d->right : d->left)
+ event->accept();
+ break;
+ case Qt::Key_Right:
+ if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
+ mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ if (mirror ? d->left : d->right)
+ event->accept();
+ break;
+ case Qt::Key_Up:
+ if (d->up) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Tab:
+ if (d->tab) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Backtab:
+ if (d->backtab) {
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
+}
+
+void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir)
+{
+ QQuickItem *initialItem = currentItem;
+ bool isNextItem = false;
+ do {
+ isNextItem = false;
+ if (currentItem->isVisible() && currentItem->isEnabled()) {
+ currentItem->setFocus(true);
+ } else {
+ QObject *attached =
+ qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
+ if (attached) {
+ QQuickItem *tempItem = qvariant_cast<QQuickItem*>(attached->property(dir));
+ if (tempItem) {
+ currentItem = tempItem;
+ isNextItem = true;
+ }
+ }
+ }
+ }
+ while (currentItem != initialItem && isNextItem);
+}
+
+const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = {
+ { Qt::Key_Left, "leftPressed" },
+ { Qt::Key_Right, "rightPressed" },
+ { Qt::Key_Up, "upPressed" },
+ { Qt::Key_Down, "downPressed" },
+ { Qt::Key_Tab, "tabPressed" },
+ { Qt::Key_Backtab, "backtabPressed" },
+ { Qt::Key_Asterisk, "asteriskPressed" },
+ { Qt::Key_NumberSign, "numberSignPressed" },
+ { Qt::Key_Escape, "escapePressed" },
+ { Qt::Key_Return, "returnPressed" },
+ { Qt::Key_Enter, "enterPressed" },
+ { Qt::Key_Delete, "deletePressed" },
+ { Qt::Key_Space, "spacePressed" },
+ { Qt::Key_Back, "backPressed" },
+ { Qt::Key_Cancel, "cancelPressed" },
+ { Qt::Key_Select, "selectPressed" },
+ { Qt::Key_Yes, "yesPressed" },
+ { Qt::Key_No, "noPressed" },
+ { Qt::Key_Context1, "context1Pressed" },
+ { Qt::Key_Context2, "context2Pressed" },
+ { Qt::Key_Context3, "context3Pressed" },
+ { Qt::Key_Context4, "context4Pressed" },
+ { Qt::Key_Call, "callPressed" },
+ { Qt::Key_Hangup, "hangupPressed" },
+ { Qt::Key_Flip, "flipPressed" },
+ { Qt::Key_Menu, "menuPressed" },
+ { Qt::Key_VolumeUp, "volumeUpPressed" },
+ { Qt::Key_VolumeDown, "volumeDownPressed" },
+ { 0, 0 }
+};
+
+bool QQuickKeysAttachedPrivate::isConnected(const char *signalName)
+{
+ return isSignalConnected(signalIndex(signalName));
+}
+
+/*!
+ \qmlclass Keys QQuickKeysAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-interaction-elements
+ \brief The Keys attached property provides key handling to Items.
+
+ All visual primitives support key handling via the Keys
+ attached property. Keys can be handled via the onPressed
+ and onReleased signal properties.
+
+ The signal properties have a \l KeyEvent parameter, named
+ \e event which contains details of the event. If a key is
+ handled \e event.accepted should be set to true to prevent the
+ event from propagating up the item hierarchy.
+
+ \section1 Example Usage
+
+ The following example shows how the general onPressed handler can
+ be used to test for a certain key; in this case, the left cursor
+ key:
+
+ \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
+
+ Some keys may alternatively be handled via specific signal properties,
+ for example \e onSelectPressed. These handlers automatically set
+ \e event.accepted to true.
+
+ \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
+
+ See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
+
+ \section1 Key Handling Priorities
+
+ The Keys attached property can be configured to handle key events
+ before or after the item it is attached to. This makes it possible
+ to intercept events in order to override an item's default behavior,
+ or act as a fallback for keys not handled by the item.
+
+ If \l priority is Keys.BeforeItem (default) the order of key event processing is:
+
+ \list 1
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o Item specific key handling, e.g. TextInput key handling
+ \o parent item
+ \endlist
+
+ If priority is Keys.AfterItem the order of key event processing is:
+
+ \list 1
+ \o Item specific key handling, e.g. TextInput key handling
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o parent item
+ \endlist
+
+ If the event is accepted during any of the above steps, key
+ propagation stops.
+
+ \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Keys::enabled
+
+ This flags enables key handling if true (default); otherwise
+ no key handlers will be called.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Keys::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o Keys.BeforeItem (default) - process the key events before normal
+ item key processing. If the event is accepted it will not
+ be passed on to the item.
+ \o Keys.AfterItem - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the Keys attached property handler.
+ \endlist
+*/
+
+/*!
+ \qmlproperty list<Object> QtQuick2::Keys::forwardTo
+
+ This property provides a way to forward key presses, key releases, and keyboard input
+ coming from input methods to other items. This can be useful when you want
+ one item to handle some keys (e.g. the up and down arrow keys), and another item to
+ handle other keys (e.g. the left and right arrow keys). Once an item that has been
+ forwarded keys accepts the event it is no longer forwarded to items later in the
+ list.
+
+ This example forwards key events to two lists:
+ \qml
+ Item {
+ ListView {
+ id: list1
+ // ...
+ }
+ ListView {
+ id: list2
+ // ...
+ }
+ Keys.forwardTo: [list1, list2]
+ focus: true
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onPressed(KeyEvent event)
+
+ This handler is called when a key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onReleased(KeyEvent event)
+
+ This handler is called when a key has been released. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit0Pressed(KeyEvent event)
+
+ This handler is called when the digit '0' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit1Pressed(KeyEvent event)
+
+ This handler is called when the digit '1' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit2Pressed(KeyEvent event)
+
+ This handler is called when the digit '2' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit3Pressed(KeyEvent event)
+
+ This handler is called when the digit '3' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit4Pressed(KeyEvent event)
+
+ This handler is called when the digit '4' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit5Pressed(KeyEvent event)
+
+ This handler is called when the digit '5' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit6Pressed(KeyEvent event)
+
+ This handler is called when the digit '6' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit7Pressed(KeyEvent event)
+
+ This handler is called when the digit '7' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit8Pressed(KeyEvent event)
+
+ This handler is called when the digit '8' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDigit9Pressed(KeyEvent event)
+
+ This handler is called when the digit '9' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onLeftPressed(KeyEvent event)
+
+ This handler is called when the Left arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onRightPressed(KeyEvent event)
+
+ This handler is called when the Right arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onUpPressed(KeyEvent event)
+
+ This handler is called when the Up arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDownPressed(KeyEvent event)
+
+ This handler is called when the Down arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onTabPressed(KeyEvent event)
+
+ This handler is called when the Tab key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onBacktabPressed(KeyEvent event)
+
+ This handler is called when the Shift+Tab key combination (Backtab) has
+ been pressed. The \a event parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onAsteriskPressed(KeyEvent event)
+
+ This handler is called when the Asterisk '*' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onEscapePressed(KeyEvent event)
+
+ This handler is called when the Escape key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onReturnPressed(KeyEvent event)
+
+ This handler is called when the Return key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onEnterPressed(KeyEvent event)
+
+ This handler is called when the Enter key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onDeletePressed(KeyEvent event)
+
+ This handler is called when the Delete key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onSpacePressed(KeyEvent event)
+
+ This handler is called when the Space key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onBackPressed(KeyEvent event)
+
+ This handler is called when the Back key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onCancelPressed(KeyEvent event)
+
+ This handler is called when the Cancel key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onSelectPressed(KeyEvent event)
+
+ This handler is called when the Select key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onYesPressed(KeyEvent event)
+
+ This handler is called when the Yes key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onNoPressed(KeyEvent event)
+
+ This handler is called when the No key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext1Pressed(KeyEvent event)
+
+ This handler is called when the Context1 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext2Pressed(KeyEvent event)
+
+ This handler is called when the Context2 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext3Pressed(KeyEvent event)
+
+ This handler is called when the Context3 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onContext4Pressed(KeyEvent event)
+
+ This handler is called when the Context4 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onCallPressed(KeyEvent event)
+
+ This handler is called when the Call key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onHangupPressed(KeyEvent event)
+
+ This handler is called when the Hangup key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onFlipPressed(KeyEvent event)
+
+ This handler is called when the Flip key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onMenuPressed(KeyEvent event)
+
+ This handler is called when the Menu key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onVolumeUpPressed(KeyEvent event)
+
+ This handler is called when the VolumeUp key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Keys::onVolumeDownPressed(KeyEvent event)
+
+ This handler is called when the VolumeDown key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
+: QObject(*(new QQuickKeysAttachedPrivate), parent),
+ QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
+{
+ Q_D(QQuickKeysAttached);
+ m_processPost = false;
+ d->item = qobject_cast<QQuickItem*>(parent);
+}
+
+QQuickKeysAttached::~QQuickKeysAttached()
+{
+}
+
+QQuickKeysAttached::Priority QQuickKeysAttached::priority() const
+{
+ return m_processPost ? AfterItem : BeforeItem;
+}
+
+void QQuickKeysAttached::setPriority(Priority order)
+{
+ bool processPost = order == AfterItem;
+ if (processPost != m_processPost) {
+ m_processPost = processPost;
+ emit priorityChanged();
+ }
+}
+
+void QQuickKeysAttached::componentComplete()
+{
+ Q_D(QQuickKeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QQuickItem *targetItem = d->targets.at(ii);
+ if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
+ d->item->setFlag(QQuickItem::ItemAcceptsInputMethod);
+ break;
+ }
+ }
+ }
+}
+
+void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
+{
+ Q_D(QQuickKeysAttached);
+ if (post != m_processPost || !d->enabled || d->inPress) {
+ event->ignore();
+ QQuickItemKeyFilter::keyPressed(event, post);
+ return;
+ }
+
+ // first process forwards
+ if (d->item && d->item->canvas()) {
+ d->inPress = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QQuickItem *i = d->targets.at(ii);
+ if (i && i->isVisible()) {
+ d->item->canvas()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inPress = false;
+ return;
+ }
+ }
+ }
+ d->inPress = false;
+ }
+
+ QQuickKeyEvent ke(*event);
+ QByteArray keySignal = keyToSignal(event->key());
+ if (!keySignal.isEmpty()) {
+ keySignal += "(QQuickKeyEvent*)";
+ if (d->isConnected(keySignal)) {
+ // If we specifically handle a key then default to accepted
+ ke.setAccepted(true);
+ int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(keySignal);
+ metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QQuickKeyEvent*, &ke));
+ }
+ }
+ if (!ke.isAccepted())
+ emit pressed(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
+}
+
+void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
+{
+ Q_D(QQuickKeysAttached);
+ if (post != m_processPost || !d->enabled || d->inRelease) {
+ event->ignore();
+ QQuickItemKeyFilter::keyReleased(event, post);
+ return;
+ }
+
+ if (d->item && d->item->canvas()) {
+ d->inRelease = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QQuickItem *i = d->targets.at(ii);
+ if (i && i->isVisible()) {
+ d->item->canvas()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inRelease = false;
+ return;
+ }
+ }
+ }
+ d->inRelease = false;
+ }
+
+ QQuickKeyEvent ke(*event);
+ emit released(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
+}
+
+void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
+{
+ Q_D(QQuickKeysAttached);
+ if (post == m_processPost && d->item && !d->inIM && d->item->canvas()) {
+ d->inIM = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QQuickItem *i = d->targets.at(ii);
+ if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod)) {
+ d->item->canvas()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->imeItem = i;
+ d->inIM = false;
+ return;
+ }
+ }
+ }
+ d->inIM = false;
+ }
+ QQuickItemKeyFilter::inputMethodEvent(event, post);
+}
+
+QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QQuickKeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QQuickItem *i = d->targets.at(ii);
+ if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
+ //### how robust is i == d->imeItem check?
+ QVariant v = i->inputMethodQuery(query);
+ if (v.userType() == QVariant::RectF)
+ v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
+ return v;
+ }
+ }
+ }
+ return QQuickItemKeyFilter::inputMethodQuery(query);
+}
+
+QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickKeysAttached(obj);
+}
+
+/*!
+ \qmlclass LayoutMirroring QQuickLayoutMirroringAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
+ \brief The LayoutMirroring attached property is used to mirror layout behavior.
+
+ The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
+ \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid)
+ and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
+ anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the
+ horizontal layout of child items.
+
+ Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
+ only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
+ behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined
+ for an item, mirroring is not enabled.
+
+ The following example shows mirroring in action. The \l Row below is specified as being anchored
+ to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
+ reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
+ from left to right by default, they are now positioned from right to left instead, as demonstrated
+ by the numbering and opacity of the items:
+
+ \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+
+ \image layoutmirroring.png
+
+ Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
+ layout versions of an application to target different language areas. The \l childrenInherit
+ property allows layout mirroring to be applied without manually setting layout configurations
+ for every item in an application. Keep in mind, however, that mirroring does not affect any
+ positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
+ mirroring enabled, it will often be necessary to apply some layout fixes to support the
+ desired layout direction. Also, it may be necessary to disable the mirroring of individual
+ child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
+ mirroring is not the desired behavior, or if the child item already implements mirroring in
+ some custom way.
+
+ See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
+ other related features to implement right-to-left support for an application.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::LayoutMirroring::enabled
+
+ This property holds whether the item's layout is mirrored horizontally. Setting this to true
+ horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
+ and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements
+ (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView})
+ this also mirrors the horizontal layout direction of the item.
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::LayoutMirroring::childrenInherit
+
+ This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
+ is inherited by its children.
+
+ The default value is false.
+*/
+
+
+QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
+{
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
+ itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->attachedLayoutDirection = this;
+ } else
+ qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
+}
+
+QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickLayoutMirroringAttached(object);
+}
+
+bool QQuickLayoutMirroringAttached::enabled() const
+{
+ return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
+}
+
+void QQuickLayoutMirroringAttached::setEnabled(bool enabled)
+{
+ if (!itemPrivate)
+ return;
+
+ itemPrivate->isMirrorImplicit = false;
+ if (enabled != itemPrivate->effectiveLayoutMirror) {
+ itemPrivate->setLayoutMirror(enabled);
+ if (itemPrivate->inheritMirrorFromItem)
+ itemPrivate->resolveLayoutMirror();
+ }
+}
+
+void QQuickLayoutMirroringAttached::resetEnabled()
+{
+ if (itemPrivate && !itemPrivate->isMirrorImplicit) {
+ itemPrivate->isMirrorImplicit = true;
+ itemPrivate->resolveLayoutMirror();
+ }
+}
+
+bool QQuickLayoutMirroringAttached::childrenInherit() const
+{
+ return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
+}
+
+void QQuickLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
+ if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
+ itemPrivate->inheritMirrorFromItem = childrenInherit;
+ itemPrivate->resolveLayoutMirror();
+ childrenInheritChanged();
+ }
+}
+
+void QQuickItemPrivate::resolveLayoutMirror()
+{
+ Q_Q(QQuickItem);
+ if (QQuickItem *parentItem = q->parentItem()) {
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parentItem);
+ setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
+ } else {
+ setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
+ }
+}
+
+void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
+{
+ inherit = inherit || inheritMirrorFromItem;
+ if (!isMirrorImplicit && inheritMirrorFromItem)
+ mirror = effectiveLayoutMirror;
+ if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
+ return;
+
+ inheritMirrorFromParent = inherit;
+ inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
+
+ if (isMirrorImplicit)
+ setLayoutMirror(inherit ? inheritedLayoutMirror : false);
+ for (int i = 0; i < childItems.count(); ++i) {
+ if (QQuickItem *child = qobject_cast<QQuickItem *>(childItems.at(i))) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
+ childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
+ }
+ }
+}
+
+void QQuickItemPrivate::setLayoutMirror(bool mirror)
+{
+ if (mirror != effectiveLayoutMirror) {
+ effectiveLayoutMirror = mirror;
+ if (_anchors) {
+ QQuickAnchorsPrivate *anchor_d = QQuickAnchorsPrivate::get(_anchors);
+ anchor_d->fillChanged();
+ anchor_d->centerInChanged();
+ anchor_d->updateHorizontalAnchors();
+ emit _anchors->mirroredChanged();
+ }
+ mirrorChange();
+ if (attachedLayoutDirection) {
+ emit attachedLayoutDirection->enabledChanged();
+ }
+ }
+}
+
+/*!
+ \class QQuickItem
+ \brief The QQuickItem class provides the most basic of all visual items in QML.
+
+ \inmodule QtQuick
+
+ All visual items in Qt Declarative inherit from QQuickItem. Although QQuickItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ You can subclass QQuickItem to provide your own custom visual item that inherits
+ these features. Note that, because it does not draw anything, QQuickItem sets the
+ QGraphicsItem::ItemHasNoContents flag. If you subclass QQuickItem to create a visual
+ item, you will need to unset this flag.
+
+*/
+
+/*!
+ \qmlclass Item QQuickItem
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Item is the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from Item. Although Item
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ Item is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ source: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ source: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ fillMode: Image.Tile
+ source: "tile.png"
+ }
+ }
+ \endqml
+
+
+ \section1 Key Handling
+
+ Key handling is available to all Item-based visual elements via the \l {Keys}{Keys}
+ attached property. The \e Keys attached property provides basic handlers such
+ as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased},
+ as well as handlers for specific keys, such as
+ \l {Keys::onCancelPressed}{onCancelPressed}. The example below
+ assigns \l {qmlfocus}{focus} to the item and handles
+ the Left key via the general \e onPressed handler and the Select key via the
+ onSelectPressed handler:
+
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Left) {
+ console.log("move left");
+ event.accepted = true;
+ }
+ }
+ Keys.onSelectPressed: console.log("Selected");
+ }
+ \endqml
+
+ See the \l {Keys}{Keys} attached property for detailed documentation.
+
+ \section1 Layout Mirroring
+
+ Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property.
+
+*/
+
+/*!
+ \fn void QQuickItem::childrenRectChanged(const QRectF &)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::baselineOffsetChanged(qreal)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::stateChanged(const QString &state)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::parentChanged(QQuickItem *)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::smoothChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::clipChanged(bool)
+ \internal
+*/
+
+/*! \fn void QQuickItem::transformOriginChanged(TransformOrigin)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::focusChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QQuickItem::activeFocusChanged(bool)
+ \internal
+*/
+/*!
+ \fn QQuickItem::QQuickItem(QQuickItem *parent)
+
+ Constructs a QQuickItem with the given \a parent.
+*/
+QQuickItem::QQuickItem(QQuickItem* parent)
+: QObject(*(new QQuickItemPrivate), parent)
+{
+ Q_D(QQuickItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
+: QObject(dd, parent)
+{
+ Q_D(QQuickItem);
+ d->init(parent);
+}
+
+#ifndef QT_NO_DEBUG
+static int qt_item_count = 0;
+
+static void qt_print_item_count()
+{
+ qDebug("Number of leaked items: %i", qt_item_count);
+ qt_item_count = -1;
+}
+#endif
+
+/*!
+ Destroys the QQuickItem.
+*/
+QQuickItem::~QQuickItem()
+{
+#ifndef QT_NO_DEBUG
+ --qt_item_count;
+ if (qt_item_count < 0)
+ qDebug("Item destroyed after qt_print_item_count() was called.");
+#endif
+
+ Q_D(QQuickItem);
+
+ if (d->parentItem)
+ setParentItem(0);
+ else if (d->canvas && d->itemNodeInstance)
+ QQuickCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance); // cleanup root
+ // XXX todo - optimize
+ while (!d->childItems.isEmpty())
+ d->childItems.first()->setParentItem(0);
+
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor)
+ anchor->clearItem(this);
+ }
+
+ /*
+ update item anchors that depended on us unless they are our child (and will also be destroyed),
+ or our sibling, and our parent is also being destroyed.
+ */
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
+ anchor->update();
+ }
+
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Destroyed)
+ change.listener->itemDestroyed(this);
+ }
+ d->changeListeners.clear();
+ delete d->_anchorLines; d->_anchorLines = 0;
+ delete d->_anchors; d->_anchors = 0;
+ delete d->_stateGroup; d->_stateGroup = 0;
+ delete d->_contents; d->_contents = 0;
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example rotates an image around its bottom-right corner.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: Item.BottomRight
+ rotation: 45
+ }
+ \endqml
+
+ The default transform origin is \c Item.Center.
+
+ To set an arbitrary transform origin point use the \l Scale or \l Rotation
+ transform elements.
+*/
+
+/*!
+ \qmlproperty Item QtQuick2::Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QQuickItem::parent
+ This property holds the parent of the item.
+*/
+void QQuickItem::setParentItem(QQuickItem *parentItem)
+{
+ Q_D(QQuickItem);
+ if (parentItem == d->parentItem)
+ return;
+
+ d->removeFromDirtyList();
+
+ QQuickItem *oldParentItem = d->parentItem;
+ QQuickItem *scopeFocusedItem = 0;
+
+ if (oldParentItem) {
+ QQuickItemPrivate *op = QQuickItemPrivate::get(oldParentItem);
+
+ QQuickItem *scopeItem = 0;
+
+ if (d->canvas && hasFocus()) {
+ scopeItem = oldParentItem;
+ while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
+ scopeFocusedItem = this;
+ } else if (d->canvas && !isFocusScope() && d->subFocusItem) {
+ scopeItem = oldParentItem;
+ while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
+ scopeFocusedItem = d->subFocusItem;
+ }
+
+ if (scopeFocusedItem)
+ QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
+ QQuickCanvasPrivate::DontChangeFocusProperty);
+
+ op->removeChild(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);
+ }
+
+ d->dirty(QQuickItemPrivate::ParentChanged);
+
+ if (d->parentItem)
+ QQuickItemPrivate::get(d->parentItem)->addChild(this);
+
+ d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+ d->setEffectiveEnableRecur(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 (scopeItem->scopedFocusItem()) {
+ QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
+ emit scopeFocusedItem->focusChanged(false);
+ } else {
+ QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
+ QQuickCanvasPrivate::DontChangeFocusProperty);
+ }
+ }
+
+ d->resolveLayoutMirror();
+
+ d->itemChange(ItemParentHasChanged, d->parentItem);
+
+ emit parentChanged(d->parentItem);
+}
+
+void QQuickItem::stackBefore(const QQuickItem *sibling)
+{
+ Q_D(QQuickItem);
+ if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
+ qWarning("QQuickItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling);
+ return;
+ }
+
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
+
+ int myIndex = parentPrivate->childItems.indexOf(this);
+ int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QQuickItem *>(sibling));
+
+ Q_ASSERT(myIndex != -1 && siblingIndex != -1);
+
+ if (myIndex == siblingIndex - 1)
+ return;
+
+ parentPrivate->childItems.removeAt(myIndex);
+
+ if (myIndex < siblingIndex) --siblingIndex;
+
+ parentPrivate->childItems.insert(siblingIndex, this);
+
+ parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
+ parentPrivate->markSortedChildrenDirty(this);
+
+ for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
+ QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
+}
+
+void QQuickItem::stackAfter(const QQuickItem *sibling)
+{
+ Q_D(QQuickItem);
+ if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
+ qWarning("QQuickItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling);
+ return;
+ }
+
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
+
+ int myIndex = parentPrivate->childItems.indexOf(this);
+ int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QQuickItem *>(sibling));
+
+ Q_ASSERT(myIndex != -1 && siblingIndex != -1);
+
+ if (myIndex == siblingIndex + 1)
+ return;
+
+ parentPrivate->childItems.removeAt(myIndex);
+
+ if (myIndex < siblingIndex) --siblingIndex;
+
+ parentPrivate->childItems.insert(siblingIndex + 1, this);
+
+ parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
+ parentPrivate->markSortedChildrenDirty(this);
+
+ for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
+ QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
+}
+
+/*!
+ Returns the QQuickItem parent of this item.
+*/
+QQuickItem *QQuickItem::parentItem() const
+{
+ Q_D(const QQuickItem);
+ return d->parentItem;
+}
+
+QSGEngine *QQuickItem::sceneGraphEngine() const
+{
+ return canvas()->sceneGraphEngine();
+}
+
+QQuickCanvas *QQuickItem::canvas() const
+{
+ Q_D(const QQuickItem);
+ return d->canvas;
+}
+
+static bool itemZOrder_sort(QQuickItem *lhs, QQuickItem *rhs)
+{
+ return lhs->z() < rhs->z();
+}
+
+QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
+{
+ if (sortedChildItems)
+ return *sortedChildItems;
+
+ // If none of the items have set Z then the paint order list is the same as
+ // the childItems list. This is by far the most common case.
+ bool haveZ = false;
+ for (int i = 0; i < childItems.count(); ++i) {
+ if (QQuickItemPrivate::get(childItems.at(i))->z != 0.) {
+ haveZ = true;
+ break;
+ }
+ }
+ if (haveZ) {
+ sortedChildItems = new QList<QQuickItem*>(childItems);
+ qStableSort(sortedChildItems->begin(), sortedChildItems->end(), itemZOrder_sort);
+ return *sortedChildItems;
+ }
+
+ sortedChildItems = const_cast<QList<QQuickItem*>*>(&childItems);
+
+ return childItems;
+}
+
+void QQuickItemPrivate::addChild(QQuickItem *child)
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(!childItems.contains(child));
+
+ childItems.append(child);
+
+ markSortedChildrenDirty(child);
+ dirty(QQuickItemPrivate::ChildrenChanged);
+
+ itemChange(QQuickItem::ItemChildAddedChange, child);
+
+ emit q->childrenChanged();
+}
+
+void QQuickItemPrivate::removeChild(QQuickItem *child)
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(child);
+ Q_ASSERT(childItems.contains(child));
+ childItems.removeOne(child);
+ Q_ASSERT(!childItems.contains(child));
+
+ markSortedChildrenDirty(child);
+ dirty(QQuickItemPrivate::ChildrenChanged);
+
+ itemChange(QQuickItem::ItemChildRemovedChange, child);
+
+ emit q->childrenChanged();
+}
+
+void QQuickItemPrivate::InitializationState::clear()
+{
+ focusScope = 0;
+}
+
+void QQuickItemPrivate::InitializationState::clear(QQuickItem *fs)
+{
+ focusScope = fs;
+}
+
+QQuickItem *QQuickItemPrivate::InitializationState::getFocusScope(QQuickItem *item)
+{
+ if (!focusScope) {
+ QQuickItem *fs = item->parentItem();
+ while (!fs->isFocusScope())
+ fs = fs->parentItem();
+ focusScope = fs;
+ }
+ return focusScope;
+}
+
+void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
+{
+ Q_Q(QQuickItem);
+
+ 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);
+ }
+
+ canvas = c;
+
+ if (canvas && polishScheduled)
+ QQuickCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
+
+ itemNodeInstance = 0;
+ opacityNode = 0;
+ clipNode = 0;
+ rootNode = 0;
+ groupNode = 0;
+ paintNode = 0;
+ beforePaintNode = 0;
+
+ InitializationState _dummy;
+ InitializationState *childState = state;
+
+ if (c && q->isFocusScope()) {
+ _dummy.clear(q);
+ childState = &_dummy;
+ }
+
+ 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);
+ }
+ }
+
+ dirty(Canvas);
+
+ itemChange(QQuickItem::ItemSceneChange, c);
+}
+
+/*!
+Returns a transform that maps points from canvas space into item space.
+*/
+QTransform QQuickItemPrivate::canvasToItemTransform() const
+{
+ // XXX todo - optimize
+ return itemToCanvasTransform().inverted();
+}
+
+/*!
+Returns a transform that maps points from item space into canvas space.
+*/
+QTransform QQuickItemPrivate::itemToCanvasTransform() const
+{
+ // XXX todo
+ QTransform rv = parentItem?QQuickItemPrivate::get(parentItem)->itemToCanvasTransform():QTransform();
+ itemToParentTransform(rv);
+ return rv;
+}
+
+/*!
+Motifies \a t with this items local transform relative to its parent.
+*/
+void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
+{
+ if (x || y)
+ t.translate(x, y);
+
+ if (!transforms.isEmpty()) {
+ QMatrix4x4 m(t);
+ for (int ii = transforms.count() - 1; ii >= 0; --ii)
+ transforms.at(ii)->applyTo(&m);
+ t = m.toTransform();
+ }
+
+ if (scale != 1. || rotation != 0.) {
+ QPointF tp = computeTransformOrigin();
+ t.translate(tp.x(), tp.y());
+ t.scale(scale, scale);
+ t.rotate(rotation);
+ t.translate(-tp.x(), -tp.y());
+ }
+}
+
+
+/*!
+ \qmlproperty real QtQuick2::Item::childrenRect.x
+ \qmlproperty real QtQuick2::Item::childrenRect.y
+ \qmlproperty real QtQuick2::Item::childrenRect.width
+ \qmlproperty real QtQuick2::Item::childrenRect.height
+
+ The childrenRect properties allow an item access to the geometry of its
+ children. This property is useful if you have an item that needs to be
+ sized to fit its children.
+*/
+
+
+/*!
+ \qmlproperty list<Item> QtQuick2::Item::children
+ \qmlproperty list<Object> QtQuick2::Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desirable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
+bool QQuickItem::isComponentComplete() const
+{
+ Q_D(const QQuickItem);
+ return d->componentComplete;
+}
+
+QQuickItemPrivate::QQuickItemPrivate()
+: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QQuickItem::Center),
+
+ flags(0), widthValid(false), heightValid(false), componentComplete(true),
+ keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(false), 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),
+ inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false),
+
+ canvas(0), parentItem(0), sortedChildItems(&childItems),
+
+ subFocusItem(0),
+
+ x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
+ z(0), scale(1), rotation(0), opacity(1),
+
+ attachedLayoutDirection(0), acceptedMouseButtons(0),
+ imHints(Qt::ImhMultiLine),
+
+ keyHandler(0),
+
+ dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
+
+ itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
+ , beforePaintNode(0), effectRefCount(0), hideRefCount(0)
+{
+}
+
+QQuickItemPrivate::~QQuickItemPrivate()
+{
+ if (sortedChildItems != &childItems)
+ delete sortedChildItems;
+}
+
+void QQuickItemPrivate::init(QQuickItem *parent)
+{
+#ifndef QT_NO_DEBUG
+ ++qt_item_count;
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_print_item_count);
+ atexit_registered = true;
+ }
+#endif
+
+ Q_Q(QQuickItem);
+ baselineOffset.invalidate();
+
+ if (parent) {
+ q->setParentItem(parent);
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
+ setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
+ }
+}
+
+void QQuickItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ if (!o)
+ return;
+
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+
+ // This test is measurably (albeit only slightly) faster than qobject_cast<>()
+ const QMetaObject *mo = o->metaObject();
+ while (mo && mo != &QQuickItem::staticMetaObject) {
+ mo = mo->d.superdata;
+ }
+
+ if (mo) {
+ QQuickItem *item = static_cast<QQuickItem *>(o);
+ item->setParentItem(that);
+ } else {
+ if (o->inherits("QGraphicsItem"))
+ qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
+
+ // XXX todo - do we really want this behavior?
+ o->setParent(that);
+ }
+}
+
+/*!
+ \qmlproperty list<Object> QtQuick2::Item::data
+ \default
+
+ The data property allows you to freely mix visual children and resources
+ in an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rectangle {}
+ Timer {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Timer {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
+int QQuickItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
+{
+ Q_UNUSED(prop);
+ // XXX todo
+ return 0;
+}
+
+QObject *QQuickItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
+{
+ Q_UNUSED(prop);
+ Q_UNUSED(i);
+ // XXX todo
+ return 0;
+}
+
+void QQuickItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
+{
+ Q_UNUSED(prop);
+ // XXX todo
+}
+
+QObject *QQuickItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
+{
+ const QObjectList children = prop->object->children();
+ if (index < children.count())
+ return children.at(index);
+ else
+ return 0;
+}
+
+void QQuickItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ // XXX todo - do we really want this behavior?
+ o->setParent(prop->object);
+}
+
+int QQuickItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
+{
+ return prop->object->children().count();
+}
+
+void QQuickItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
+{
+ // XXX todo - do we really want this behavior?
+ const QObjectList children = prop->object->children();
+ for (int index = 0; index < children.count(); index++)
+ children.at(index)->setParent(0);
+}
+
+QQuickItem *QQuickItemPrivate::children_at(QDeclarativeListProperty<QQuickItem> *prop, int index)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ if (index >= p->childItems.count() || index < 0)
+ return 0;
+ else
+ return p->childItems.at(index);
+}
+
+void QQuickItemPrivate::children_append(QDeclarativeListProperty<QQuickItem> *prop, QQuickItem *o)
+{
+ if (!o)
+ return;
+
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ if (o->parentItem() == that)
+ o->setParentItem(0);
+
+ o->setParentItem(that);
+}
+
+int QQuickItemPrivate::children_count(QDeclarativeListProperty<QQuickItem> *prop)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ return p->childItems.count();
+}
+
+void QQuickItemPrivate::children_clear(QDeclarativeListProperty<QQuickItem> *prop)
+{
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+ while (!p->childItems.isEmpty())
+ p->childItems.at(0)->setParentItem(0);
+}
+
+int QQuickItemPrivate::transform_count(QDeclarativeListProperty<QQuickTransform> *prop)
+{
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ return QQuickItemPrivate::get(that)->transforms.count();
+}
+
+void QQuickTransform::appendToItem(QQuickItem *item)
+{
+ Q_D(QQuickTransform);
+ if (!item)
+ return;
+
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+
+ if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
+ p->transforms.removeOne(this);
+ p->transforms.append(this);
+ } else {
+ p->transforms.append(this);
+ d->items.append(item);
+ }
+
+ p->dirty(QQuickItemPrivate::Transform);
+}
+
+void QQuickTransform::prependToItem(QQuickItem *item)
+{
+ Q_D(QQuickTransform);
+ if (!item)
+ return;
+
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+
+ if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
+ p->transforms.removeOne(this);
+ p->transforms.prepend(this);
+ } else {
+ p->transforms.prepend(this);
+ d->items.append(item);
+ }
+
+ p->dirty(QQuickItemPrivate::Transform);
+}
+
+void QQuickItemPrivate::transform_append(QDeclarativeListProperty<QQuickTransform> *prop, QQuickTransform *transform)
+{
+ if (!transform)
+ return;
+
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ transform->appendToItem(that);
+}
+
+QQuickTransform *QQuickItemPrivate::transform_at(QDeclarativeListProperty<QQuickTransform> *prop, int idx)
+{
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+
+ if (idx < 0 || idx >= p->transforms.count())
+ return 0;
+ else
+ return p->transforms.at(idx);
+}
+
+void QQuickItemPrivate::transform_clear(QDeclarativeListProperty<QQuickTransform> *prop)
+{
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+
+ for (int ii = 0; ii < p->transforms.count(); ++ii) {
+ QQuickTransform *t = p->transforms.at(ii);
+ QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
+ tp->items.removeOne(that);
+ }
+
+ p->transforms.clear();
+
+ p->dirty(QQuickItemPrivate::Transform);
+}
+
+/*!
+ \property QQuickItem::childrenRect
+ \brief The geometry of an item's children.
+
+ This property holds the (collective) position and size of the item's children.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::x
+ \qmlproperty real QtQuick2::Item::y
+ \qmlproperty real QtQuick2::Item::width
+ \qmlproperty real QtQuick2::Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \qmlproperty real QtQuick2::Item::z
+
+ Sets the stacking order of sibling items. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of siblings with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rectangle {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \qmlproperty bool QtQuick2::Item::visible
+
+ This property holds whether the item is visible. By default this is true.
+
+ Setting this property directly affects the \c visible value of child
+ items. When set to \c false, the \c visible values of all child items also
+ become \c false. When set to \c true, the \c visible values of child items
+ are returned to \c true, unless they have explicitly been set to \c false.
+
+ (Because of this flow-on behavior, using the \c visible property may not
+ have the intended effect if a property binding should only respond to
+ explicit property changes. In such cases it may be better to use the
+ \l opacity property instead.)
+
+ Setting this property to \c false automatically causes \l focus to be set
+ to \c false, and this item will longer receive mouse and keyboard events.
+ (In contrast, setting the \l opacity to 0 does not affect the \l focus
+ property and the receiving of key events.)
+
+ \note This property's value is only affected by changes to this property or
+ the parent's \c visible property. It does not change, for example, if this
+ item moves off-screen, or if the \l opacity changes to 0.
+*/
+
+
+/*!
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.top
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.bottom
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.left
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.right
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.verticalCenter
+ \qmlproperty AnchorLine QtQuick2::Item::anchors.baseline
+
+ \qmlproperty Item QtQuick2::Item::anchors.fill
+ \qmlproperty Item QtQuick2::Item::anchors.centerIn
+
+ \qmlproperty real QtQuick2::Item::anchors.margins
+ \qmlproperty real QtQuick2::Item::anchors.topMargin
+ \qmlproperty real QtQuick2::Item::anchors.bottomMargin
+ \qmlproperty real QtQuick2::Item::anchors.leftMargin
+ \qmlproperty real QtQuick2::Item::anchors.rightMargin
+ \qmlproperty real QtQuick2::Item::anchors.horizontalCenterOffset
+ \qmlproperty real QtQuick2::Item::anchors.verticalCenterOffset
+ \qmlproperty real QtQuick2::Item::anchors.baselineOffset
+
+ \qmlproperty bool QtQuick2::Item::anchors.mirrored
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+ The \c anchors.margins property can be used to set all of the various margins at once, to the same value.
+ Note that margins are anchor-specific and are not applied if an item does not
+ use anchors.
+
+ Offsets apply for horizontal center, vertical center, and baseline anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \endtable
+
+ \c anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ To clear an anchor value, set it to \c undefined.
+
+ \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QQuickItem::baselineOffset
+ \brief The position of the item's baseline in local coordinates.
+
+ The baseline of a \l Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of 0 is used.
+*/
+QQuickAnchors *QQuickItemPrivate::anchors() const
+{
+ if (!_anchors) {
+ Q_Q(const QQuickItem);
+ _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
+ if (!componentComplete)
+ _anchors->classBegin();
+ }
+ return _anchors;
+}
+
+QQuickItemPrivate::AnchorLines *QQuickItemPrivate::anchorLines() const
+{
+ Q_Q(const QQuickItem);
+ if (!_anchorLines) _anchorLines =
+ new AnchorLines(const_cast<QQuickItem *>(q));
+ return _anchorLines;
+}
+
+void QQuickItemPrivate::siblingOrderChanged()
+{
+ Q_Q(QQuickItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::SiblingOrder) {
+ change.listener->itemSiblingOrderChanged(q);
+ }
+ }
+}
+
+QDeclarativeListProperty<QObject> QQuickItemPrivate::data()
+{
+ return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
+ QQuickItemPrivate::data_count,
+ QQuickItemPrivate::data_at,
+ QQuickItemPrivate::data_clear);
+}
+
+QRectF QQuickItem::childrenRect()
+{
+ Q_D(QQuickItem);
+ if (!d->_contents) {
+ d->_contents = new QQuickContents(this);
+ if (d->componentComplete)
+ d->_contents->complete();
+ }
+ return d->_contents->rectF();
+}
+
+QList<QQuickItem *> QQuickItem::childItems() const
+{
+ Q_D(const QQuickItem);
+ return d->childItems;
+}
+
+bool QQuickItem::clip() const
+{
+ return flags() & ItemClipsChildrenToShape;
+}
+
+void QQuickItem::setClip(bool c)
+{
+ if (clip() == c)
+ return;
+
+ setFlag(ItemClipsChildrenToShape, c);
+
+ emit clipChanged(c);
+}
+
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
+void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickItem);
+
+ if (d->_anchors)
+ QQuickAnchorsPrivate::get(d->_anchors)->updateMe();
+
+ bool xChange = (newGeometry.x() != oldGeometry.x());
+ bool yChange = (newGeometry.y() != oldGeometry.y());
+ bool widthChange = (newGeometry.width() != oldGeometry.width());
+ bool heightChange = (newGeometry.height() != oldGeometry.height());
+
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Geometry) {
+ if (change.gTypes == QQuickItemPrivate::GeometryChange) {
+ change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
+ } else if ((xChange && (change.gTypes & QQuickItemPrivate::XChange)) ||
+ (yChange && (change.gTypes & QQuickItemPrivate::YChange)) ||
+ (widthChange && (change.gTypes & QQuickItemPrivate::WidthChange)) ||
+ (heightChange && (change.gTypes & QQuickItemPrivate::HeightChange))) {
+ change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
+ }
+ }
+ }
+
+ if (xChange)
+ emit xChanged();
+ if (yChange)
+ emit yChanged();
+ if (widthChange)
+ emit widthChanged();
+ if (heightChange)
+ emit heightChanged();
+}
+
+/*!
+ Called by the rendering thread when it is time to sync the state of the QML objects with the
+ scene graph objects. The function should return the root of the scene graph subtree for
+ this item. \a oldNode is the node that was returned the last time the function was called.
+
+ The main thread is blocked while this function is executed so it is safe to read
+ values from the QQuickItem instance and other objects in the main thread.
+
+ \warning This is the only function in which it is allowed to make use of scene graph
+ objects from the main thread. Use of scene graph objects outside this function will
+ result in race conditions and potential crashes.
+ */
+
+QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ delete oldNode;
+ return 0;
+}
+
+QSGTransformNode *QQuickItemPrivate::createTransformNode()
+{
+ return new QSGTransformNode;
+}
+
+void QQuickItem::updatePolish()
+{
+}
+
+void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
+{
+ ChangeListener change(listener, types);
+ changeListeners.removeOne(change);
+}
+
+void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
+{
+ ChangeListener change(listener, types);
+ int index = changeListeners.find(change);
+ if (index > -1)
+ changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
+ else
+ changeListeners.append(change);
+}
+
+void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
+{
+ ChangeListener change(listener, types);
+ if (types == NoChange) {
+ changeListeners.removeOne(change);
+ } else {
+ int index = changeListeners.find(change);
+ if (index > -1)
+ changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
+ }
+}
+
+void QQuickItem::keyPressEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::keyReleaseEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::focusInEvent(QFocusEvent *)
+{
+}
+
+void QQuickItem::focusOutEvent(QFocusEvent *)
+{
+}
+
+void QQuickItem::mousePressEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::mouseMoveEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ mousePressEvent(event);
+}
+
+void QQuickItem::mouseUngrabEvent()
+{
+ // XXX todo
+}
+
+void QQuickItem::touchUngrabEvent()
+{
+ // XXX todo
+}
+
+void QQuickItem::wheelEvent(QWheelEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::touchEvent(QTouchEvent *event)
+{
+ event->ignore();
+}
+
+void QQuickItem::hoverEnterEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void QQuickItem::hoverMoveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void QQuickItem::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void QQuickItem::dragEnterEvent(QDragEnterEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void QQuickItem::dragMoveEvent(QDragMoveEvent *event)
+{
+
+ Q_UNUSED(event);
+}
+
+void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event)
+{
+
+ Q_UNUSED(event);
+}
+
+void QQuickItem::dropEvent(QDropEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+bool QQuickItem::childMouseEventFilter(QQuickItem *, QEvent *)
+{
+ return false;
+}
+
+void QQuickItem::windowDeactivateEvent()
+{
+ foreach (QQuickItem* item, childItems()) {
+ item->windowDeactivateEvent();
+ }
+}
+
+Qt::InputMethodHints QQuickItem::inputMethodHints() const
+{
+ Q_D(const QQuickItem);
+ return d->imHints;
+}
+
+void QQuickItem::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickItem);
+ d->imHints = hints;
+
+ if (!d->canvas || d->canvas->activeFocusItem() != this)
+ return;
+
+ QInputPanel *p = qApp->inputPanel();
+ if (p->inputItem() == this)
+ qApp->inputPanel()->update(Qt::ImHints);
+}
+
+void QQuickItem::updateMicroFocus()
+{
+ QInputPanel *p = qApp->inputPanel();
+ if (p->inputItem() == this)
+ qApp->inputPanel()->update(Qt::ImQueryInput);
+}
+
+QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QQuickItem);
+ QVariant v;
+
+ switch (query) {
+ case Qt::ImEnabled:
+ v = (bool)(flags() & ItemAcceptsInputMethod);
+ break;
+ case Qt::ImHints:
+ v = (int)inputMethodHints();
+ break;
+ case Qt::ImCursorRectangle:
+ case Qt::ImFont:
+ case Qt::ImCursorPosition:
+ case Qt::ImSurroundingText:
+ case Qt::ImCurrentSelection:
+ case Qt::ImMaximumTextLength:
+ case Qt::ImAnchorPosition:
+ case Qt::ImPreferredLanguage:
+ if (d->keyHandler)
+ v = d->keyHandler->inputMethodQuery(query);
+ default:
+ break;
+ }
+
+ return v;
+}
+
+QQuickAnchorLine QQuickItemPrivate::left() const
+{
+ return anchorLines()->left;
+}
+
+QQuickAnchorLine QQuickItemPrivate::right() const
+{
+ return anchorLines()->right;
+}
+
+QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
+{
+ return anchorLines()->hCenter;
+}
+
+QQuickAnchorLine QQuickItemPrivate::top() const
+{
+ return anchorLines()->top;
+}
+
+QQuickAnchorLine QQuickItemPrivate::bottom() const
+{
+ return anchorLines()->bottom;
+}
+
+QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
+{
+ return anchorLines()->vCenter;
+}
+
+QQuickAnchorLine QQuickItemPrivate::baseline() const
+{
+ return anchorLines()->baseline;
+}
+
+qreal QQuickItem::baselineOffset() const
+{
+ Q_D(const QQuickItem);
+ if (!d->baselineOffset.isValid()) {
+ return 0.0;
+ } else
+ return d->baselineOffset;
+}
+
+void QQuickItem::setBaselineOffset(qreal offset)
+{
+ Q_D(QQuickItem);
+ if (offset == d->baselineOffset)
+ return;
+
+ d->baselineOffset = offset;
+
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Geometry) {
+ QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
+ if (anchor)
+ anchor->updateVerticalAnchors();
+ }
+ }
+ emit baselineOffsetChanged(offset);
+}
+
+void QQuickItem::update()
+{
+ Q_D(QQuickItem);
+ Q_ASSERT(flags() & ItemHasContents);
+ d->dirty(QQuickItemPrivate::Content);
+}
+
+void QQuickItem::polish()
+{
+ Q_D(QQuickItem);
+ if (!d->polishScheduled) {
+ d->polishScheduled = true;
+ if (d->canvas) {
+ QQuickCanvasPrivate *p = QQuickCanvasPrivate::get(d->canvas);
+ bool maybeupdate = p->itemsToPolish.isEmpty();
+ p->itemsToPolish.insert(this);
+ if (maybeupdate) d->canvas->maybeUpdate();
+ }
+ }
+}
+
+void QQuickItem::mapFromItem(QDeclarativeV8Function *args) const
+{
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QQuickItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QQuickItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = mapFromItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
+}
+
+QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
+{
+ Q_D(const QQuickItem);
+
+ // XXX todo - we need to be able to handle common parents better and detect
+ // invalid cases
+ if (ok) *ok = true;
+
+ QTransform t = d->itemToCanvasTransform();
+ if (other) t *= QQuickItemPrivate::get(other)->canvasToItemTransform();
+
+ return t;
+}
+
+void QQuickItem::mapToItem(QDeclarativeV8Function *args) const
+{
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QQuickItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QQuickItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = mapToItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
+}
+
+void QQuickItem::forceActiveFocus()
+{
+ setFocus(true);
+ QQuickItem *parent = parentItem();
+ while (parent) {
+ if (parent->flags() & QQuickItem::ItemIsFocusScope) {
+ parent->setFocus(true);
+ }
+ parent = parent->parentItem();
+ }
+}
+
+QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
+{
+ // XXX todo - should this include transform etc.?
+ const QList<QQuickItem *> children = childItems();
+ for (int i = children.count()-1; i >= 0; --i) {
+ QQuickItem *child = children.at(i);
+ if (child->isVisible() && child->x() <= x
+ && child->x() + child->width() >= x
+ && child->y() <= y
+ && child->y() + child->height() >= y)
+ return child;
+ }
+ return 0;
+}
+
+QDeclarativeListProperty<QObject> QQuickItemPrivate::resources()
+{
+ return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
+ QQuickItemPrivate::resources_count,
+ QQuickItemPrivate::resources_at,
+ QQuickItemPrivate::resources_clear);
+}
+
+QDeclarativeListProperty<QQuickItem> QQuickItemPrivate::children()
+{
+ return QDeclarativeListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
+ QQuickItemPrivate::children_count,
+ QQuickItemPrivate::children_at,
+ QQuickItemPrivate::children_clear);
+
+}
+
+QDeclarativeListProperty<QDeclarativeState> QQuickItemPrivate::states()
+{
+ return _states()->statesProperty();
+}
+
+QDeclarativeListProperty<QDeclarativeTransition> QQuickItemPrivate::transitions()
+{
+ return _states()->transitionsProperty();
+}
+
+QString QQuickItemPrivate::state() const
+{
+ if (!_stateGroup)
+ return QString();
+ else
+ return _stateGroup->state();
+}
+
+void QQuickItemPrivate::setState(const QString &state)
+{
+ _states()->setState(state);
+}
+
+QString QQuickItem::state() const
+{
+ Q_D(const QQuickItem);
+ return d->state();
+}
+
+void QQuickItem::setState(const QString &state)
+{
+ Q_D(QQuickItem);
+ d->setState(state);
+}
+
+QDeclarativeListProperty<QQuickTransform> QQuickItem::transform()
+{
+ return QDeclarativeListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
+ QQuickItemPrivate::transform_count,
+ QQuickItemPrivate::transform_at,
+ QQuickItemPrivate::transform_clear);
+}
+
+void QQuickItem::classBegin()
+{
+ Q_D(QQuickItem);
+ d->componentComplete = false;
+ if (d->_stateGroup)
+ d->_stateGroup->classBegin();
+ if (d->_anchors)
+ d->_anchors->classBegin();
+}
+
+void QQuickItem::componentComplete()
+{
+ Q_D(QQuickItem);
+ d->componentComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if (d->_anchors) {
+ d->_anchors->componentComplete();
+ QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
+ }
+ if (d->keyHandler)
+ d->keyHandler->componentComplete();
+ if (d->_contents)
+ d->_contents->complete();
+}
+
+QDeclarativeStateGroup *QQuickItemPrivate::_states()
+{
+ Q_Q(QQuickItem);
+ if (!_stateGroup) {
+ _stateGroup = new QDeclarativeStateGroup;
+ if (!componentComplete)
+ _stateGroup->classBegin();
+ FAST_CONNECT(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)))
+ }
+
+ return _stateGroup;
+}
+
+QQuickItemPrivate::AnchorLines::AnchorLines(QQuickItem *q)
+{
+ left.item = q;
+ left.anchorLine = QQuickAnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QQuickAnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QQuickAnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QQuickAnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QQuickAnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QQuickAnchorLine::VCenter;
+ baseline.item = q;
+ baseline.anchorLine = QQuickAnchorLine::Baseline;
+}
+
+QPointF QQuickItemPrivate::computeTransformOrigin() const
+{
+ switch (origin) {
+ default:
+ case QQuickItem::TopLeft:
+ return QPointF(0, 0);
+ case QQuickItem::Top:
+ return QPointF(width / 2., 0);
+ case QQuickItem::TopRight:
+ return QPointF(width, 0);
+ case QQuickItem::Left:
+ return QPointF(0, height / 2.);
+ case QQuickItem::Center:
+ return QPointF(width / 2., height / 2.);
+ case QQuickItem::Right:
+ return QPointF(width, height / 2.);
+ case QQuickItem::BottomLeft:
+ return QPointF(0, height);
+ case QQuickItem::Bottom:
+ return QPointF(width / 2., height);
+ case QQuickItem::BottomRight:
+ return QPointF(width, height);
+ }
+}
+
+void QQuickItemPrivate::transformChanged()
+{
+}
+
+void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(e->isAccepted());
+ if (keyHandler) {
+ if (e->type() == QEvent::KeyPress)
+ keyHandler->keyPressed(e, false);
+ else
+ keyHandler->keyReleased(e, false);
+
+ if (e->isAccepted())
+ return;
+ else
+ e->accept();
+ }
+
+ if (e->type() == QEvent::KeyPress)
+ q->keyPressEvent(e);
+ else
+ q->keyReleaseEvent(e);
+
+ if (e->isAccepted())
+ return;
+
+ if (keyHandler) {
+ e->accept();
+
+ if (e->type() == QEvent::KeyPress)
+ keyHandler->keyPressed(e, true);
+ else
+ keyHandler->keyReleased(e, true);
+ }
+}
+
+void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(e->isAccepted());
+ if (keyHandler) {
+ keyHandler->inputMethodEvent(e, false);
+
+ if (e->isAccepted())
+ return;
+ else
+ e->accept();
+ }
+
+ q->inputMethodEvent(e);
+
+ if (e->isAccepted())
+ return;
+
+ if (keyHandler) {
+ e->accept();
+
+ keyHandler->inputMethodEvent(e, true);
+ }
+}
+
+void QQuickItemPrivate::deliverFocusEvent(QFocusEvent *e)
+{
+ Q_Q(QQuickItem);
+
+ if (e->type() == QEvent::FocusIn) {
+ q->focusInEvent(e);
+ } else {
+ q->focusOutEvent(e);
+ }
+}
+
+void QQuickItemPrivate::deliverMouseEvent(QMouseEvent *e)
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(e->isAccepted());
+
+ switch (e->type()) {
+ default:
+ Q_ASSERT(!"Unknown event type");
+ case QEvent::MouseMove:
+ q->mouseMoveEvent(e);
+ break;
+ case QEvent::MouseButtonPress:
+ q->mousePressEvent(e);
+ break;
+ case QEvent::MouseButtonRelease:
+ q->mouseReleaseEvent(e);
+ break;
+ case QEvent::MouseButtonDblClick:
+ q->mouseDoubleClickEvent(e);
+ break;
+ }
+}
+
+void QQuickItemPrivate::deliverWheelEvent(QWheelEvent *e)
+{
+ Q_Q(QQuickItem);
+ q->wheelEvent(e);
+}
+
+void QQuickItemPrivate::deliverTouchEvent(QTouchEvent *e)
+{
+ Q_Q(QQuickItem);
+ q->touchEvent(e);
+}
+
+void QQuickItemPrivate::deliverHoverEvent(QHoverEvent *e)
+{
+ Q_Q(QQuickItem);
+ switch (e->type()) {
+ default:
+ Q_ASSERT(!"Unknown event type");
+ case QEvent::HoverEnter:
+ q->hoverEnterEvent(e);
+ break;
+ case QEvent::HoverLeave:
+ q->hoverLeaveEvent(e);
+ break;
+ case QEvent::HoverMove:
+ q->hoverMoveEvent(e);
+ break;
+ }
+}
+
+void QQuickItemPrivate::deliverDragEvent(QEvent *e)
+{
+ Q_Q(QQuickItem);
+ switch (e->type()) {
+ default:
+ Q_ASSERT(!"Unknown event type");
+ case QEvent::DragEnter:
+ q->dragEnterEvent(static_cast<QDragEnterEvent *>(e));
+ break;
+ case QEvent::DragLeave:
+ q->dragLeaveEvent(static_cast<QDragLeaveEvent *>(e));
+ break;
+ case QEvent::DragMove:
+ q->dragMoveEvent(static_cast<QDragMoveEvent *>(e));
+ break;
+ case QEvent::Drop:
+ q->dropEvent(static_cast<QDropEvent *>(e));
+ break;
+ }
+}
+
+void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ Q_UNUSED(change);
+ Q_UNUSED(value);
+}
+
+/*! \internal */
+// XXX todo - do we want/need this anymore?
+// Note that it's now used for varying clip rect
+QRectF QQuickItem::boundingRect() const
+{
+ Q_D(const QQuickItem);
+ return QRectF(0, 0, d->width, d->height);
+}
+
+QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
+{
+ Q_D(const QQuickItem);
+ return d->origin;
+}
+
+void QQuickItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QQuickItem);
+ if (origin == d->origin)
+ return;
+
+ d->origin = origin;
+ d->dirty(QQuickItemPrivate::TransformOrigin);
+
+ emit transformOriginChanged(d->origin);
+}
+
+QPointF QQuickItem::transformOriginPoint() const
+{
+ Q_D(const QQuickItem);
+ if (!d->transformOriginPoint.isNull())
+ return d->transformOriginPoint;
+ return d->computeTransformOrigin();
+}
+
+void QQuickItem::setTransformOriginPoint(const QPointF &point)
+{
+ Q_D(QQuickItem);
+ if (d->transformOriginPoint == point)
+ return;
+
+ d->transformOriginPoint = point;
+ d->dirty(QQuickItemPrivate::TransformOrigin);
+}
+
+qreal QQuickItem::z() const
+{
+ Q_D(const QQuickItem);
+ return d->z;
+}
+
+void QQuickItem::setZ(qreal v)
+{
+ Q_D(QQuickItem);
+ if (d->z == v)
+ return;
+
+ d->z = v;
+
+ d->dirty(QQuickItemPrivate::ZValue);
+ if (d->parentItem) {
+ QQuickItemPrivate::get(d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
+ QQuickItemPrivate::get(d->parentItem)->markSortedChildrenDirty(this);
+ }
+
+ emit zChanged();
+}
+
+
+/*!
+ \qmlproperty real QtQuick2::Item::rotation
+ This property holds the rotation of the item in degrees clockwise.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Rotation
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Scale
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Item::opacity
+
+ This property holds the opacity of the item. Opacity is specified as a
+ number between 0 (fully transparent) and 1 (fully opaque). The default is 1.
+
+ When this property is set, the specified opacity is also applied
+ individually to child items. In almost all cases this is what you want,
+ but in some cases it may produce undesired results. For example in the
+ second set of rectangles below, the red rectangle has specified an opacity
+ of 0.5, which affects the opacity of its blue child rectangle even though
+ the child has not specified an opacity.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+
+ If an item's opacity is set to 0, the item will no longer receive mouse
+ events, but will continue to receive key events and will retain the keyboard
+ \l focus if it has been set. (In contrast, setting the \l visible property
+ to \c false stops both mouse and keyboard events, and also removes focus
+ from the item.)
+*/
+
+/*!
+ Returns a value indicating whether mouse input should
+ remain with this item exclusively.
+
+ \sa setKeepMouseGrab()
+ */
+
+qreal QQuickItem::rotation() const
+{
+ Q_D(const QQuickItem);
+ return d->rotation;
+}
+
+void QQuickItem::setRotation(qreal r)
+{
+ Q_D(QQuickItem);
+ if (d->rotation == r)
+ return;
+
+ d->rotation = r;
+
+ d->dirty(QQuickItemPrivate::BasicTransform);
+
+ d->itemChange(ItemRotationHasChanged, r);
+
+ emit rotationChanged();
+}
+
+qreal QQuickItem::scale() const
+{
+ Q_D(const QQuickItem);
+ return d->scale;
+}
+
+void QQuickItem::setScale(qreal s)
+{
+ Q_D(QQuickItem);
+ if (d->scale == s)
+ return;
+
+ d->scale = s;
+
+ d->dirty(QQuickItemPrivate::BasicTransform);
+
+ emit scaleChanged();
+}
+
+qreal QQuickItem::opacity() const
+{
+ Q_D(const QQuickItem);
+ return d->opacity;
+}
+
+void QQuickItem::setOpacity(qreal o)
+{
+ Q_D(QQuickItem);
+ if (d->opacity == o)
+ return;
+
+ d->opacity = o;
+
+ d->dirty(QQuickItemPrivate::OpacityValue);
+
+ d->itemChange(ItemOpacityHasChanged, o);
+
+ emit opacityChanged();
+}
+
+bool QQuickItem::isVisible() const
+{
+ Q_D(const QQuickItem);
+ return d->effectiveVisible;
+}
+
+void QQuickItem::setVisible(bool v)
+{
+ Q_D(QQuickItem);
+ if (v == d->explicitVisible)
+ return;
+
+ d->explicitVisible = v;
+
+ d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+}
+
+bool QQuickItem::isEnabled() const
+{
+ Q_D(const QQuickItem);
+ return d->effectiveEnable;
+}
+
+void QQuickItem::setEnabled(bool e)
+{
+ Q_D(QQuickItem);
+ if (e == d->explicitEnable)
+ return;
+
+ d->explicitEnable = e;
+
+ d->setEffectiveEnableRecur(d->calcEffectiveEnable());
+}
+
+bool QQuickItemPrivate::calcEffectiveVisible() const
+{
+ // XXX todo - Should the effective visible of an element with no parent just be the current
+ // effective visible? This would prevent pointless re-processing in the case of an element
+ // moving to/from a no-parent situation, but it is different from what graphics view does.
+ return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
+}
+
+void QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
+{
+ Q_Q(QQuickItem);
+
+ if (newEffectiveVisible && !explicitVisible) {
+ // This item locally overrides visibility
+ return;
+ }
+
+ if (newEffectiveVisible == effectiveVisible) {
+ // No change necessary
+ return;
+ }
+
+ effectiveVisible = newEffectiveVisible;
+ dirty(Visible);
+ if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
+
+ if (canvas) {
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
+ if (canvasPriv->mouseGrabberItem == q)
+ q->ungrabMouse();
+ }
+
+ for (int ii = 0; ii < childItems.count(); ++ii)
+ QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
+
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Visibility)
+ change.listener->itemVisibilityChanged(q);
+ }
+
+ emit q->visibleChanged();
+}
+
+bool QQuickItemPrivate::calcEffectiveEnable() const
+{
+ // XXX todo - Should the effective enable of an element with no parent just be the current
+ // effective enable? This would prevent pointless re-processing in the case of an element
+ // moving to/from a no-parent situation, but it is different from what graphics view does.
+ return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
+}
+
+void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
+{
+ Q_Q(QQuickItem);
+
+ // XXX todo - need to fixup focus
+
+ if (newEffectiveEnable && !explicitEnable) {
+ // This item locally overrides enable
+ return;
+ }
+
+ if (newEffectiveEnable == effectiveEnable) {
+ // No change necessary
+ return;
+ }
+
+ effectiveEnable = newEffectiveEnable;
+
+ if (canvas) {
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
+ if (canvasPriv->mouseGrabberItem == q)
+ q->ungrabMouse();
+ }
+
+ for (int ii = 0; ii < childItems.count(); ++ii)
+ QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
+
+ emit q->enabledChanged();
+}
+
+QString QQuickItemPrivate::dirtyToString() const
+{
+#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
+ if (!rv.isEmpty()) \
+ rv.append(QLatin1String("|")); \
+ rv.append(QLatin1String(#value)); \
+}
+
+// QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
+ QString rv;
+
+ DIRTY_TO_STRING(TransformOrigin);
+ DIRTY_TO_STRING(Transform);
+ DIRTY_TO_STRING(BasicTransform);
+ DIRTY_TO_STRING(Position);
+ DIRTY_TO_STRING(Size);
+ DIRTY_TO_STRING(ZValue);
+ DIRTY_TO_STRING(Content);
+ DIRTY_TO_STRING(Smooth);
+ DIRTY_TO_STRING(OpacityValue);
+ DIRTY_TO_STRING(ChildrenChanged);
+ DIRTY_TO_STRING(ChildrenStackingChanged);
+ DIRTY_TO_STRING(ParentChanged);
+ DIRTY_TO_STRING(Clip);
+ DIRTY_TO_STRING(Canvas);
+ DIRTY_TO_STRING(EffectReference);
+ DIRTY_TO_STRING(Visible);
+ DIRTY_TO_STRING(HideReference);
+
+ return rv;
+}
+
+void QQuickItemPrivate::dirty(DirtyType type)
+{
+ Q_Q(QQuickItem);
+ if (type & (TransformOrigin | Transform | BasicTransform | Position | Size))
+ transformChanged();
+
+ if (!(dirtyAttributes & type) || (canvas && !prevDirtyItem)) {
+ dirtyAttributes |= type;
+ if (canvas) {
+ addToDirtyList();
+ QQuickCanvasPrivate::get(canvas)->dirtyItem(q);
+ }
+ }
+}
+
+void QQuickItemPrivate::addToDirtyList()
+{
+ Q_Q(QQuickItem);
+
+ Q_ASSERT(canvas);
+ if (!prevDirtyItem) {
+ Q_ASSERT(!nextDirtyItem);
+
+ QQuickCanvasPrivate *p = QQuickCanvasPrivate::get(canvas);
+ nextDirtyItem = p->dirtyItemList;
+ if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
+ prevDirtyItem = &p->dirtyItemList;
+ p->dirtyItemList = q;
+ p->dirtyItem(q);
+ }
+ Q_ASSERT(prevDirtyItem);
+}
+
+void QQuickItemPrivate::removeFromDirtyList()
+{
+ if (prevDirtyItem) {
+ if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem;
+ *prevDirtyItem = nextDirtyItem;
+ prevDirtyItem = 0;
+ nextDirtyItem = 0;
+ }
+ Q_ASSERT(!prevDirtyItem);
+ Q_ASSERT(!nextDirtyItem);
+}
+
+void QQuickItemPrivate::refFromEffectItem(bool hide)
+{
+ ++effectRefCount;
+ if (1 == effectRefCount) {
+ dirty(EffectReference);
+ if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
+ }
+ if (hide) {
+ if (++hideRefCount == 1)
+ dirty(HideReference);
+ }
+}
+
+void QQuickItemPrivate::derefFromEffectItem(bool unhide)
+{
+ Q_ASSERT(effectRefCount);
+ --effectRefCount;
+ if (0 == effectRefCount) {
+ dirty(EffectReference);
+ if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
+ }
+ if (unhide) {
+ if (--hideRefCount == 0)
+ dirty(HideReference);
+ }
+}
+
+void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ Q_Q(QQuickItem);
+ switch (change) {
+ case QQuickItem::ItemChildAddedChange:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Children) {
+ change.listener->itemChildAdded(q, data.item);
+ }
+ }
+ break;
+ case QQuickItem::ItemChildRemovedChange:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Children) {
+ change.listener->itemChildRemoved(q, data.item);
+ }
+ }
+ break;
+ case QQuickItem::ItemSceneChange:
+ q->itemChange(change, data);
+ break;
+ case QQuickItem::ItemVisibleHasChanged:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Visibility) {
+ change.listener->itemVisibilityChanged(q);
+ }
+ }
+ break;
+ case QQuickItem::ItemParentHasChanged:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Parent) {
+ change.listener->itemParentChanged(q, data.item);
+ }
+ }
+ break;
+ case QQuickItem::ItemOpacityHasChanged:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Opacity) {
+ change.listener->itemOpacityChanged(q);
+ }
+ }
+ break;
+ case QQuickItem::ItemActiveFocusHasChanged:
+ q->itemChange(change, data);
+ break;
+ case QQuickItem::ItemRotationHasChanged:
+ q->itemChange(change, data);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::Rotation) {
+ change.listener->itemRotationChanged(q);
+ }
+ }
+ break;
+ }
+}
+
+/*!
+ \property QQuickItem::smooth
+ \brief whether the item is smoothly transformed.
+
+ 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.
+
+ By default smooth transformations are off.
+*/
+
+/*!
+ Returns true if the item should be drawn with antialiasing and
+ smooth pixmap filtering, false otherwise.
+
+ The default is false.
+
+ \sa setSmooth()
+*/
+bool QQuickItem::smooth() const
+{
+ Q_D(const QQuickItem);
+ return d->smooth;
+}
+
+/*!
+ Sets whether the item should be drawn with antialiasing and
+ smooth pixmap filtering to \a smooth.
+
+ \sa smooth()
+*/
+void QQuickItem::setSmooth(bool smooth)
+{
+ Q_D(QQuickItem);
+ if (d->smooth == smooth)
+ return;
+
+ d->smooth = smooth;
+ d->dirty(QQuickItemPrivate::Smooth);
+
+ emit smoothChanged(smooth);
+}
+
+QQuickItem::Flags QQuickItem::flags() const
+{
+ Q_D(const QQuickItem);
+ return (QQuickItem::Flags)d->flags;
+}
+
+void QQuickItem::setFlag(Flag flag, bool enabled)
+{
+ Q_D(QQuickItem);
+ if (enabled)
+ setFlags((Flags)(d->flags | (quint32)flag));
+ else
+ setFlags((Flags)(d->flags & ~(quint32)flag));
+}
+
+void QQuickItem::setFlags(Flags flags)
+{
+ Q_D(QQuickItem);
+
+ if ((flags & ItemIsFocusScope) != (d->flags & ItemIsFocusScope)) {
+ if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->canvas) {
+ qWarning("QQuickItem: Cannot set FocusScope once item has children and is in a canvas.");
+ flags &= ~ItemIsFocusScope;
+ } else if (d->flags & ItemIsFocusScope) {
+ qWarning("QQuickItem: Cannot unset FocusScope flag.");
+ flags |= ItemIsFocusScope;
+ }
+ }
+
+ if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape))
+ d->dirty(QQuickItemPrivate::Clip);
+
+ d->flags = flags;
+}
+
+qreal QQuickItem::x() const
+{
+ Q_D(const QQuickItem);
+ return d->x;
+}
+
+qreal QQuickItem::y() const
+{
+ Q_D(const QQuickItem);
+ return d->y;
+}
+
+QPointF QQuickItem::pos() const
+{
+ Q_D(const QQuickItem);
+ return QPointF(d->x, d->y);
+}
+
+void QQuickItem::setX(qreal v)
+{
+ Q_D(QQuickItem);
+ if (d->x == v)
+ return;
+
+ qreal oldx = d->x;
+ d->x = v;
+
+ d->dirty(QQuickItemPrivate::Position);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(oldx, y(), width(), height()));
+}
+
+void QQuickItem::setY(qreal v)
+{
+ Q_D(QQuickItem);
+ if (d->y == v)
+ return;
+
+ qreal oldy = d->y;
+ d->y = v;
+
+ d->dirty(QQuickItemPrivate::Position);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), oldy, width(), height()));
+}
+
+void QQuickItem::setPos(const QPointF &pos)
+{
+ Q_D(QQuickItem);
+ if (QPointF(d->x, d->y) == pos)
+ return;
+
+ qreal oldx = d->x;
+ qreal oldy = d->y;
+
+ d->x = pos.x();
+ d->y = pos.y();
+
+ d->dirty(QQuickItemPrivate::Position);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(oldx, oldy, width(), height()));
+}
+
+qreal QQuickItem::width() const
+{
+ Q_D(const QQuickItem);
+ return d->width;
+}
+
+void QQuickItem::setWidth(qreal w)
+{
+ Q_D(QQuickItem);
+ if (qIsNaN(w))
+ return;
+
+ d->widthValid = true;
+ if (d->width == w)
+ return;
+
+ qreal oldWidth = d->width;
+ d->width = w;
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+void QQuickItem::resetWidth()
+{
+ Q_D(QQuickItem);
+ d->widthValid = false;
+ setImplicitWidth(implicitWidth());
+}
+
+void QQuickItemPrivate::implicitWidthChanged()
+{
+ Q_Q(QQuickItem);
+ emit q->implicitWidthChanged();
+}
+
+qreal QQuickItemPrivate::getImplicitWidth() const
+{
+ return implicitWidth;
+}
+/*!
+ Returns the width of the item that is implied by other properties that determine the content.
+*/
+qreal QQuickItem::implicitWidth() const
+{
+ Q_D(const QQuickItem);
+ return d->getImplicitWidth();
+}
+
+/*!
+ \qmlproperty real QtQuick2::Item::implicitWidth
+ \qmlproperty real QtQuick2::Item::implicitHeight
+
+ Defines the natural width or height of the Item if no \l width or \l height is specified.
+
+ The default implicit size for most items is 0x0, however some elements have an inherent
+ implicit size which cannot be overridden, e.g. Image, Text.
+
+ Setting the implicit size is useful for defining components that have a preferred size
+ based on their content, for example:
+
+ \qml
+ // Label.qml
+ import QtQuick 1.1
+
+ Item {
+ property alias icon: image.source
+ property alias label: text.text
+ implicitWidth: text.implicitWidth + image.implicitWidth
+ implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
+ Image { id: image }
+ Text {
+ id: text
+ wrapMode: Text.Wrap
+ anchors.left: image.right; anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ \endqml
+
+ \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly
+ incurs a performance penalty as the text must be laid out twice.
+*/
+
+/*!
+ Sets the implied width of the item to \a w.
+ This is the width implied by other properties that determine the content.
+*/
+void QQuickItem::setImplicitWidth(qreal w)
+{
+ Q_D(QQuickItem);
+ bool changed = w != d->implicitWidth;
+ d->implicitWidth = w;
+ if (d->width == w || widthValid()) {
+ if (changed)
+ d->implicitWidthChanged();
+ return;
+ }
+
+ qreal oldWidth = d->width;
+ d->width = w;
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+
+ if (changed)
+ d->implicitWidthChanged();
+}
+
+/*!
+ Returns whether the width property has been set explicitly.
+*/
+bool QQuickItem::widthValid() const
+{
+ Q_D(const QQuickItem);
+ return d->widthValid;
+}
+
+qreal QQuickItem::height() const
+{
+ Q_D(const QQuickItem);
+ return d->height;
+}
+
+void QQuickItem::setHeight(qreal h)
+{
+ Q_D(QQuickItem);
+ if (qIsNaN(h))
+ return;
+
+ d->heightValid = true;
+ if (d->height == h)
+ return;
+
+ qreal oldHeight = d->height;
+ d->height = h;
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+void QQuickItem::resetHeight()
+{
+ Q_D(QQuickItem);
+ d->heightValid = false;
+ setImplicitHeight(implicitHeight());
+}
+
+void QQuickItemPrivate::implicitHeightChanged()
+{
+ Q_Q(QQuickItem);
+ emit q->implicitHeightChanged();
+}
+
+qreal QQuickItemPrivate::getImplicitHeight() const
+{
+ return implicitHeight;
+}
+
+/*!
+ Returns the height of the item that is implied by other properties that determine the content.
+*/
+qreal QQuickItem::implicitHeight() const
+{
+ Q_D(const QQuickItem);
+ return d->getImplicitHeight();
+}
+
+
+/*!
+ Sets the implied height of the item to \a h.
+ This is the height implied by other properties that determine the content.
+*/
+void QQuickItem::setImplicitHeight(qreal h)
+{
+ Q_D(QQuickItem);
+ bool changed = h != d->implicitHeight;
+ d->implicitHeight = h;
+ if (d->height == h || heightValid()) {
+ if (changed)
+ d->implicitHeightChanged();
+ return;
+ }
+
+ qreal oldHeight = d->height;
+ d->height = h;
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+
+ if (changed)
+ d->implicitHeightChanged();
+}
+
+void QQuickItem::setImplicitSize(qreal w, qreal h)
+{
+ Q_D(QQuickItem);
+ bool wChanged = w != d->implicitWidth;
+ bool hChanged = h != d->implicitHeight;
+
+ d->implicitWidth = w;
+ d->implicitHeight = h;
+
+ bool wDone = false;
+ bool hDone = false;
+ if (d->width == w || widthValid()) {
+ if (wChanged)
+ d->implicitWidthChanged();
+ wDone = true;
+ }
+ if (d->height == h || heightValid()) {
+ if (hChanged)
+ d->implicitHeightChanged();
+ hDone = true;
+ }
+ if (wDone && hDone)
+ return;
+
+ qreal oldWidth = d->width;
+ qreal oldHeight = d->height;
+ if (!wDone)
+ d->width = w;
+ if (!hDone)
+ d->height = h;
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, oldHeight));
+
+ if (!wDone && wChanged)
+ d->implicitWidthChanged();
+ if (!hDone && hChanged)
+ d->implicitHeightChanged();
+}
+
+/*!
+ Returns whether the height property has been set explicitly.
+*/
+bool QQuickItem::heightValid() const
+{
+ Q_D(const QQuickItem);
+ return d->heightValid;
+}
+
+void QQuickItem::setSize(const QSizeF &size)
+{
+ Q_D(QQuickItem);
+ d->heightValid = true;
+ d->widthValid = true;
+
+ if (QSizeF(d->width, d->height) == size)
+ return;
+
+ qreal oldHeight = d->height;
+ qreal oldWidth = d->width;
+ d->height = size.height();
+ d->width = size.width();
+
+ d->dirty(QQuickItemPrivate::Size);
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, oldHeight));
+}
+
+bool QQuickItem::hasActiveFocus() const
+{
+ Q_D(const QQuickItem);
+ return d->activeFocus;
+}
+
+bool QQuickItem::hasFocus() const
+{
+ Q_D(const QQuickItem);
+ return d->focus;
+}
+
+void QQuickItem::setFocus(bool focus)
+{
+ Q_D(QQuickItem);
+ if (d->focus == focus)
+ return;
+
+ if (d->canvas) {
+ // Need to find our nearest focus scope
+ QQuickItem *scope = parentItem();
+ while (scope && !scope->isFocusScope())
+ scope = scope->parentItem();
+ if (focus)
+ QQuickCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
+ else
+ QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
+ } else {
+ d->focus = focus;
+ emit focusChanged(focus);
+ }
+}
+
+bool QQuickItem::isFocusScope() const
+{
+ return flags() & ItemIsFocusScope;
+}
+
+QQuickItem *QQuickItem::scopedFocusItem() const
+{
+ Q_D(const QQuickItem);
+ if (!isFocusScope())
+ return 0;
+ else
+ return d->subFocusItem;
+}
+
+
+Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
+{
+ Q_D(const QQuickItem);
+ return d->acceptedMouseButtons;
+}
+
+void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
+{
+ Q_D(QQuickItem);
+ d->acceptedMouseButtons = buttons;
+}
+
+bool QQuickItem::filtersChildMouseEvents() const
+{
+ Q_D(const QQuickItem);
+ return d->filtersChildMouseEvents;
+}
+
+void QQuickItem::setFiltersChildMouseEvents(bool filter)
+{
+ Q_D(QQuickItem);
+ d->filtersChildMouseEvents = filter;
+}
+
+bool QQuickItem::isUnderMouse() const
+{
+ Q_D(const QQuickItem);
+ if (!d->canvas)
+ return false;
+
+ QPoint cursorPos = QCursor::pos();
+ if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos))))
+ return true;
+ return false;
+}
+
+bool QQuickItem::acceptHoverEvents() const
+{
+ Q_D(const QQuickItem);
+ return d->hoverEnabled;
+}
+
+void QQuickItem::setAcceptHoverEvents(bool enabled)
+{
+ Q_D(QQuickItem);
+ d->hoverEnabled = enabled;
+}
+
+void QQuickItem::grabMouse()
+{
+ Q_D(QQuickItem);
+ if (!d->canvas)
+ return;
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
+ if (canvasPriv->mouseGrabberItem == this)
+ return;
+
+ QQuickItem *oldGrabber = canvasPriv->mouseGrabberItem;
+ canvasPriv->mouseGrabberItem = this;
+ if (oldGrabber)
+ oldGrabber->mouseUngrabEvent();
+}
+
+void QQuickItem::ungrabMouse()
+{
+ Q_D(QQuickItem);
+ if (!d->canvas)
+ return;
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
+ if (canvasPriv->mouseGrabberItem != this) {
+ qWarning("QQuickItem::ungrabMouse(): Item is not the mouse grabber.");
+ return;
+ }
+
+ canvasPriv->mouseGrabberItem = 0;
+ mouseUngrabEvent();
+}
+
+bool QQuickItem::keepMouseGrab() const
+{
+ Q_D(const QQuickItem);
+ return d->keepMouse;
+}
+
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+
+ This is useful for items that wish to grab and keep mouse
+ interaction following a predefined gesture. For example,
+ an item that is interested in horizontal mouse movement
+ may set keepMouseGrab to true once a threshold has been
+ exceeded. Once keepMouseGrab has been set to true, filtering
+ items will not react to mouse events.
+
+ If the item does not indicate that it wishes to retain mouse grab,
+ a filtering item may steal the grab. For example, Flickable may attempt
+ to steal a mouse grab if it detects that the user has begun to
+ move the viewport.
+
+ \sa keepMouseGrab()
+ */
+void QQuickItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QQuickItem);
+ d->keepMouse = keep;
+}
+
+/*!
+ Grabs the touch points specified by \a ids.
+
+ These touch points will be owned by the item until
+ they are released. Alternatively, the grab can be stolen
+ by a filtering item like Flickable. Use setKeepTouchGrab()
+ to prevent the grab from being stolen.
+
+ \sa ungrabTouchPoints(), setKeepTouchGrab()
+*/
+void QQuickItem::grabTouchPoints(const QList<int> &ids)
+{
+ Q_D(QQuickItem);
+ if (!d->canvas)
+ return;
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
+
+ QSet<QQuickItem*> ungrab;
+ for (int i = 0; i < ids.count(); ++i) {
+ QQuickItem *oldGrabber = canvasPriv->itemForTouchPointId.value(ids.at(i));
+ if (oldGrabber == this)
+ return;
+
+ canvasPriv->itemForTouchPointId[ids.at(i)] = this;
+ if (oldGrabber)
+ ungrab.insert(oldGrabber);
+ }
+ foreach (QQuickItem *oldGrabber, ungrab)
+ oldGrabber->touchUngrabEvent();
+}
+
+/*!
+ Ungrabs the touch points owned by this item.
+
+ \sa grabTouchPoints()
+*/
+void QQuickItem::ungrabTouchPoints()
+{
+ Q_D(QQuickItem);
+ if (!d->canvas)
+ return;
+ QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(d->canvas);
+
+ QMutableHashIterator<int, QQuickItem*> i(canvasPriv->itemForTouchPointId);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value() == this)
+ i.remove();
+ }
+ touchUngrabEvent();
+}
+
+/*!
+ Returns a value indicating whether the touch points grabbed by this item
+ should remain with this item exclusively.
+
+ \sa setKeepTouchGrab(), keepMouseGrab()
+*/
+bool QQuickItem::keepTouchGrab() const
+{
+ Q_D(const QQuickItem);
+ return d->keepTouch;
+}
+
+/*!
+ The flag indicating whether the touch points grabbed
+ by this item should remain with this item is set to \a keep.
+
+ This is useful for items that wish to grab and keep specific touch
+ points following a predefined gesture. For example,
+ an item that is interested in horizontal touch point movement
+ may set setKeepTouchGrab to true once a threshold has been
+ exceeded. Once setKeepTouchGrab has been set to true, filtering
+ items will not react to the relevant touch points.
+
+ If the item does not indicate that it wishes to retain touch point grab,
+ a filtering item may steal the grab. For example, Flickable may attempt
+ to steal a touch point grab if it detects that the user has begun to
+ move the viewport.
+
+ \sa keepTouchGrab(), setKeepMouseGrab()
+ */
+void QQuickItem::setKeepTouchGrab(bool keep)
+{
+ Q_D(QQuickItem);
+ d->keepTouch = keep;
+}
+
+/*!
+ \qmlmethod object QtQuick2::Item::mapFromItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in \a item's coordinate system, to
+ this item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped coordinate.
+
+ If \a item is a \c null value, this maps the point from the coordinate
+ system of the root QML view.
+*/
+/*!
+ \qmlmethod object QtQuick2::Item::mapToItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in this item's coordinate system, to
+ \a item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped coordinate.
+
+ If \a item is a \c null value, this maps \a x and \a y to the coordinate
+ system of the root QML view.
+*/
+QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
+{
+ QPointF p = mapToScene(point);
+ if (item)
+ p = item->mapFromScene(p);
+ return p;
+}
+
+QPointF QQuickItem::mapToScene(const QPointF &point) const
+{
+ Q_D(const QQuickItem);
+ return d->itemToCanvasTransform().map(point);
+}
+
+QRectF QQuickItem::mapRectToItem(const QQuickItem *item, const QRectF &rect) const
+{
+ Q_D(const QQuickItem);
+ QTransform t = d->itemToCanvasTransform();
+ if (item)
+ t *= QQuickItemPrivate::get(item)->canvasToItemTransform();
+ return t.mapRect(rect);
+}
+
+QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
+{
+ Q_D(const QQuickItem);
+ return d->itemToCanvasTransform().mapRect(rect);
+}
+
+QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
+{
+ QPointF p = item?item->mapToScene(point):point;
+ return mapFromScene(p);
+}
+
+QPointF QQuickItem::mapFromScene(const QPointF &point) const
+{
+ Q_D(const QQuickItem);
+ return d->canvasToItemTransform().map(point);
+}
+
+QRectF QQuickItem::mapRectFromItem(const QQuickItem *item, const QRectF &rect) const
+{
+ Q_D(const QQuickItem);
+ QTransform t = item?QQuickItemPrivate::get(item)->itemToCanvasTransform():QTransform();
+ t *= d->canvasToItemTransform();
+ return t.mapRect(rect);
+}
+
+QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
+{
+ Q_D(const QQuickItem);
+ return d->canvasToItemTransform().mapRect(rect);
+}
+
+
+/*!
+ \qmlmethod QtQuick2::Item::forceActiveFocus()
+
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+
+/*!
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+
+/*!
+ \qmlmethod QtQuick2::Item::childAt(real x, real y)
+
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or \c null if there is no such item.
+*/
+
+/*!
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or 0 if there is no such item.
+*/
+
+/*!
+ \qmlproperty list<State> QtQuick2::Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State {
+ // ...
+ },
+ State {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+/*!
+ \qmlproperty list<Transition> QtQuick2::Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition {
+ // ...
+ },
+ Transition {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {QML Animation and Transitions}{Transitions}
+*/
+/*
+ \qmlproperty list<Filter> QtQuick2::Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur {
+ // ...
+ },
+ Reflection {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Item::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QQuickItem::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle. If you set
+ clipping during an item's paint operation, remember to re-set it to
+ prevent clipping the rest of your scene.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \js
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ \endjs
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+
+/*!
+ \qmlproperty list<Transform> QtQuick2::Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*!
+ \enum QQuickItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value Top The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value Left The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value Right The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value Bottom The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+
+/*!
+ \qmlproperty bool QtQuick2::Item::activeFocus
+
+ This property indicates whether the item has active focus.
+
+ An item with active focus will receive keyboard input,
+ or is a FocusScope ancestor of the item that will receive keyboard input.
+
+ Usually, activeFocus is gained by setting focus on an item and its enclosing
+ FocusScopes. In the following example \c input will have activeFocus.
+ \qml
+ Rectangle {
+ FocusScope {
+ focus: true
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ \sa focus, {qmlfocus}{Keyboard Focus}
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Item::focus
+ This property indicates whether the item has focus within the enclosing focus scope. If true, this item
+ will gain active focus when the enclosing focus scope gains active focus.
+ In the following example, \c input will be given active focus when \c scope gains active focus.
+ \qml
+ Rectangle {
+ FocusScope {
+ id: scope
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ For the purposes of this property, the scene as a whole is assumed to act like a focus scope.
+ On a practical level, that means the following QML will give active focus to \c input on startup.
+
+ \qml
+ Rectangle {
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ \endqml
+
+ \sa activeFocus, {qmlfocus}{Keyboard Focus}
+*/
+
+
+/*!
+ \property QQuickItem::anchors
+ \internal
+*/
+
+/*!
+ \property QQuickItem::left
+ \internal
+*/
+
+/*!
+ \property QQuickItem::right
+ \internal
+*/
+
+/*!
+ \property QQuickItem::horizontalCenter
+ \internal
+*/
+
+/*!
+ \property QQuickItem::top
+ \internal
+*/
+
+/*!
+ \property QQuickItem::bottom
+ \internal
+*/
+
+/*!
+ \property QQuickItem::verticalCenter
+ \internal
+*/
+
+/*!
+ \property QQuickItem::focus
+ \internal
+*/
+
+/*!
+ \property QQuickItem::transform
+ \internal
+*/
+
+/*!
+ \property QQuickItem::transformOrigin
+ \internal
+*/
+
+/*!
+ \property QQuickItem::activeFocus
+ \internal
+*/
+
+/*!
+ \property QQuickItem::baseline
+ \internal
+*/
+
+/*!
+ \property QQuickItem::data
+ \internal
+*/
+
+/*!
+ \property QQuickItem::resources
+ \internal
+*/
+
+/*!
+ \property QQuickItem::state
+ \internal
+*/
+
+/*!
+ \property QQuickItem::states
+ \internal
+*/
+
+/*!
+ \property QQuickItem::transformOriginPoint
+ \internal
+*/
+
+/*!
+ \property QQuickItem::transitions
+ \internal
+*/
+
+bool QQuickItem::event(QEvent *ev)
+{
+#if 0
+ if (ev->type() == QEvent::PolishRequest) {
+ Q_D(QQuickItem);
+ d->polishScheduled = false;
+ updatePolish();
+ return true;
+ } else {
+ return QObject::event(ev);
+ }
+#endif
+ if (ev->type() == QEvent::InputMethodQuery) {
+ QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
+ Qt::InputMethodQueries queries = query->queries();
+ for (uint i = 0; i < 32; ++i) {
+ Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
+ if (q) {
+ QVariant v = inputMethodQuery(q);
+ query->setValue(q, v);
+ }
+ }
+ query->accept();
+ return true;
+ } else if (ev->type() == QEvent::InputMethod) {
+ inputMethodEvent(static_cast<QInputMethodEvent *>(ev));
+ return true;
+ }
+ return QObject::event(ev);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, QQuickItem *item)
+{
+ if (!item) {
+ debug << "QQuickItem(0)";
+ return debug;
+ }
+
+ debug << item->metaObject()->className() << "(this =" << ((void*)item)
+ << ", name=" << item->objectName()
+ << ", parent =" << ((void*)item->parentItem())
+ << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height()))
+ << ", z =" << item->z() << ')';
+ return debug;
+}
+#endif
+
+qint64 QQuickItemPrivate::consistentTime = -1;
+void QQuickItemPrivate::setConsistentTime(qint64 t)
+{
+ consistentTime = t;
+}
+
+class QElapsedTimerConsistentTimeHack
+{
+public:
+ void start() {
+ t1 = QQuickItemPrivate::consistentTime;
+ t2 = 0;
+ }
+ qint64 elapsed() {
+ return QQuickItemPrivate::consistentTime - t1;
+ }
+ qint64 restart() {
+ qint64 val = QQuickItemPrivate::consistentTime - t1;
+ t1 = QQuickItemPrivate::consistentTime;
+ t2 = 0;
+ return val;
+ }
+
+private:
+ qint64 t1;
+ qint64 t2;
+};
+
+void QQuickItemPrivate::start(QElapsedTimer &t)
+{
+ if (QQuickItemPrivate::consistentTime == -1)
+ t.start();
+ else
+ ((QElapsedTimerConsistentTimeHack*)&t)->start();
+}
+
+qint64 QQuickItemPrivate::elapsed(QElapsedTimer &t)
+{
+ if (QQuickItemPrivate::consistentTime == -1)
+ return t.elapsed();
+ else
+ return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed();
+}
+
+qint64 QQuickItemPrivate::restart(QElapsedTimer &t)
+{
+ if (QQuickItemPrivate::consistentTime == -1)
+ return t.restart();
+ else
+ return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
+}
+
+/*!
+ \fn bool QQuickItem::isTextureProvider() const
+
+ Returns true if this item is a texture provider. The default
+ implementation returns false.
+
+ This function can be called from any thread.
+ */
+
+/*!
+ \fn QSGTextureProvider *QQuickItem::textureProvider() const
+
+ Returns the texture provider for an item. The default implementation
+ returns 0.
+
+ This function may only be called on the rendering thread.
+ */
+
+QT_END_NAMESPACE
+
+#include <moc_qquickitem.cpp>
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
new file mode 100644
index 0000000000..6e7a909696
--- /dev/null
+++ b/src/quick/items/qquickitem.h
@@ -0,0 +1,420 @@
+// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKITEM_H
+#define QQUICKITEM_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtGui/qevent.h>
+#include <QtGui/qfont.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickTransformPrivate;
+class QQuickTransform : public QObject
+{
+ Q_OBJECT
+public:
+ QQuickTransform(QObject *parent = 0);
+ ~QQuickTransform();
+
+ void appendToItem(QQuickItem *);
+ void prependToItem(QQuickItem *);
+
+ virtual void applyTo(QMatrix4x4 *matrix) const = 0;
+
+protected Q_SLOTS:
+ void update();
+
+protected:
+ QQuickTransform(QQuickTransformPrivate &dd, QObject *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QQuickTransform)
+};
+
+class QDeclarativeV8Function;
+class QDeclarativeState;
+class QQuickAnchorLine;
+class QDeclarativeTransition;
+class QQuickKeyEvent;
+class QQuickAnchors;
+class QQuickItemPrivate;
+class QQuickCanvas;
+class QSGEngine;
+class QTouchEvent;
+class QSGNode;
+class QSGTransformNode;
+class QSGTextureProvider;
+
+class Q_QUICK_EXPORT QQuickItem : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+
+ Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem NOTIFY parentChanged DESIGNABLE false FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QObject> resources READ resources DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
+
+ Q_PROPERTY(QPointF pos READ pos FINAL)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
+ Q_PROPERTY(qreal z READ z WRITE setZ NOTIFY zChanged FINAL)
+ Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
+
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QDeclarativeState> states READ states DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitions DESIGNABLE false)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine left READ left CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine right READ right CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine top READ top CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine bottom READ bottom CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickAnchorLine baseline READ baseline CONSTANT FINAL)
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+
+ Q_PROPERTY(bool clip READ clip WRITE setClip NOTIFY clipChanged)
+
+ Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
+ Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL)
+
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged)
+ Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint) // XXX todo - notify?
+ Q_PROPERTY(QDeclarativeListProperty<QQuickTransform> transform READ transform DESIGNABLE false FINAL)
+
+ Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged)
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged)
+
+ Q_ENUMS(TransformOrigin)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ enum Flag {
+ ItemClipsChildrenToShape = 0x01,
+ ItemAcceptsInputMethod = 0x02,
+ ItemIsFocusScope = 0x04,
+ ItemHasContents = 0x08,
+ ItemAcceptsDrops = 0x10
+ // Remember to increment the size of QQuickItemPrivate::flags
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum ItemChange {
+ ItemChildAddedChange, // value.item
+ ItemChildRemovedChange, // value.item
+ ItemSceneChange, // value.canvas
+ ItemVisibleHasChanged, // value.realValue
+ ItemParentHasChanged, // value.item
+ ItemOpacityHasChanged, // value.realValue
+ ItemActiveFocusHasChanged, // value.boolValue
+ ItemRotationHasChanged // value.realValue
+ };
+
+ union ItemChangeData {
+ ItemChangeData(QQuickItem *v) : item(v) {}
+ ItemChangeData(QQuickCanvas *v) : canvas(v) {}
+ ItemChangeData(qreal v) : realValue(v) {}
+ ItemChangeData(bool v) : boolValue(v) {}
+
+ QQuickItem *item;
+ QQuickCanvas *canvas;
+ qreal realValue;
+ bool boolValue;
+ };
+
+ enum TransformOrigin {
+ TopLeft, Top, TopRight,
+ Left, Center, Right,
+ BottomLeft, Bottom, BottomRight
+ };
+
+ QQuickItem(QQuickItem *parent = 0);
+ virtual ~QQuickItem();
+
+ QSGEngine *sceneGraphEngine() const;
+
+ QQuickCanvas *canvas() const;
+ QQuickItem *parentItem() const;
+ void setParentItem(QQuickItem *parent);
+ void stackBefore(const QQuickItem *);
+ void stackAfter(const QQuickItem *);
+
+ QRectF childrenRect();
+ QList<QQuickItem *> childItems() const;
+
+ bool clip() const;
+ void setClip(bool);
+
+ QString state() const;
+ void setState(const QString &);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QDeclarativeListProperty<QQuickTransform> transform();
+
+ qreal x() const;
+ qreal y() const;
+ QPointF pos() const;
+ void setX(qreal);
+ void setY(qreal);
+ void setPos(const QPointF &);
+
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+ qreal implicitWidth() const;
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+ qreal implicitHeight() const;
+
+ void setSize(const QSizeF &size);
+
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+ QPointF transformOriginPoint() const;
+ void setTransformOriginPoint(const QPointF &);
+
+ qreal z() const;
+ void setZ(qreal);
+
+ qreal rotation() const;
+ void setRotation(qreal);
+ qreal scale() const;
+ void setScale(qreal);
+
+ qreal opacity() const;
+ void setOpacity(qreal);
+
+ bool isVisible() const;
+ void setVisible(bool);
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool smooth() const;
+ void setSmooth(bool);
+
+ Flags flags() const;
+ void setFlag(Flag flag, bool enabled = true);
+ void setFlags(Flags flags);
+
+ virtual QRectF boundingRect() const;
+
+ bool hasActiveFocus() const;
+ bool hasFocus() const;
+ void setFocus(bool);
+ bool isFocusScope() const;
+ QQuickItem *scopedFocusItem() const;
+
+ Qt::MouseButtons acceptedMouseButtons() const;
+ void setAcceptedMouseButtons(Qt::MouseButtons buttons);
+ bool acceptHoverEvents() const;
+ void setAcceptHoverEvents(bool enabled);
+
+ bool isUnderMouse() const;
+ void grabMouse();
+ void ungrabMouse();
+ bool keepMouseGrab() const;
+ void setKeepMouseGrab(bool);
+ bool filtersChildMouseEvents() const;
+ void setFiltersChildMouseEvents(bool filter);
+
+ void grabTouchPoints(const QList<int> &ids);
+ void ungrabTouchPoints();
+ bool keepTouchGrab() const;
+ void setKeepTouchGrab(bool);
+
+ QTransform itemTransform(QQuickItem *, bool *) const;
+ QPointF mapToItem(const QQuickItem *item, const QPointF &point) const;
+ QPointF mapToScene(const QPointF &point) const;
+ QRectF mapRectToItem(const QQuickItem *item, const QRectF &rect) const;
+ QRectF mapRectToScene(const QRectF &rect) const;
+ QPointF mapFromItem(const QQuickItem *item, const QPointF &point) const;
+ QPointF mapFromScene(const QPointF &point) const;
+ QRectF mapRectFromItem(const QQuickItem *item, const QRectF &rect) const;
+ QRectF mapRectFromScene(const QRectF &rect) const;
+
+ void polish();
+
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void forceActiveFocus();
+ Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const;
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ struct UpdatePaintNodeData {
+ QSGTransformNode *transformNode;
+ private:
+ friend class QQuickCanvasPrivate;
+ UpdatePaintNodeData();
+ };
+
+ virtual bool isTextureProvider() const { return false; }
+ virtual QSGTextureProvider *textureProvider() const { return 0; }
+
+public Q_SLOTS:
+ void update();
+ void updateMicroFocus();
+
+Q_SIGNALS:
+ void childrenRectChanged(const QRectF &);
+ void baselineOffsetChanged(qreal);
+ void stateChanged(const QString &);
+ void focusChanged(bool);
+ void activeFocusChanged(bool);
+ void parentChanged(QQuickItem *);
+ void transformOriginChanged(TransformOrigin);
+ void smoothChanged(bool);
+ void clipChanged(bool);
+
+ // XXX todo
+ void childrenChanged();
+ void opacityChanged();
+ void enabledChanged();
+ void visibleChanged();
+ void rotationChanged();
+ void scaleChanged();
+
+ void xChanged();
+ void yChanged();
+ void widthChanged();
+ void heightChanged();
+ void zChanged();
+ void implicitWidthChanged();
+ void implicitHeightChanged();
+
+protected:
+ virtual bool event(QEvent *);
+
+ bool isComponentComplete() const;
+ virtual void itemChange(ItemChange, const ItemChangeData &);
+
+ void setImplicitWidth(qreal);
+ bool widthValid() const; // ### better name?
+ void setImplicitHeight(qreal);
+ bool heightValid() const; // ### better name?
+ void setImplicitSize(qreal, qreal);
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QMouseEvent *event);
+ virtual void mouseUngrabEvent(); // XXX todo - params?
+ virtual void touchUngrabEvent();
+ virtual void wheelEvent(QWheelEvent *event);
+ virtual void touchEvent(QTouchEvent *event);
+ virtual void hoverEnterEvent(QHoverEvent *event);
+ virtual void hoverMoveEvent(QHoverEvent *event);
+ virtual void hoverLeaveEvent(QHoverEvent *event);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragMoveEvent(QDragMoveEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void dropEvent(QDropEvent *);
+ virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
+ virtual void windowDeactivateEvent();
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ virtual void updatePolish();
+
+protected:
+ QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent = 0);
+
+private:
+ friend class QQuickCanvas;
+ friend class QQuickCanvasPrivate;
+ friend class QSGRenderer;
+ Q_DISABLE_COPY(QQuickItem)
+ Q_DECLARE_PRIVATE(QQuickItem)
+};
+
+// XXX todo
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItem::Flags)
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug Q_QUICK_EXPORT operator<<(QDebug debug, QQuickItem *item);
+#endif
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickItem)
+QML_DECLARE_TYPE(QQuickTransform)
+
+QT_END_HEADER
+
+#endif // QQUICKITEM_H
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
new file mode 100644
index 0000000000..a522a19a70
--- /dev/null
+++ b/src/quick/items/qquickitem_p.h
@@ -0,0 +1,752 @@
+// Commit: 5c783d0a9a912816813945387903857a314040b5
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKITEM_P_H
+#define QQUICKITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickitem.h"
+
+#include "qquickanchors_p.h"
+#include "qquickanchors_p_p.h"
+#include "qquickitemchangelistener_p.h"
+
+#include "qquickcanvas_p.h"
+
+#include <QtQuick/qsgnode.h>
+#include "qquickclipnode_p.h"
+
+#include <private/qpodvector_p.h>
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qdeclarativenullablevalue_p_p.h>
+#include <private/qdeclarativenotifier_p.h>
+#include <private/qdeclarativeglobal_p.h>
+
+#include <qdeclarative.h>
+#include <qdeclarativecontext.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qelapsedtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QQuickItemKeyFilter;
+class QQuickLayoutMirroringAttached;
+
+class QQuickContents : public QQuickItemChangeListener
+{
+public:
+ QQuickContents(QQuickItem *item);
+ ~QQuickContents();
+
+ QRectF rectF() const { return QRectF(m_x, m_y, m_width, m_height); }
+
+ inline void calcGeometry(QQuickItem *changed = 0);
+ void complete();
+
+protected:
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemDestroyed(QQuickItem *item);
+ void itemChildAdded(QQuickItem *, QQuickItem *);
+ void itemChildRemoved(QQuickItem *, QQuickItem *);
+ //void itemVisibilityChanged(QQuickItem *item)
+
+private:
+ bool calcHeight(QQuickItem *changed = 0);
+ bool calcWidth(QQuickItem *changed = 0);
+ void updateRect();
+
+ QQuickItem *m_item;
+ qreal m_x;
+ qreal m_y;
+ qreal m_width;
+ qreal m_height;
+};
+
+void QQuickContents::calcGeometry(QQuickItem *changed)
+{
+ bool wChanged = calcWidth(changed);
+ bool hChanged = calcHeight(changed);
+ if (wChanged || hChanged)
+ updateRect();
+}
+
+class QQuickTransformPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickTransform);
+public:
+ static QQuickTransformPrivate* get(QQuickTransform *transform) { return transform->d_func(); }
+
+ QQuickTransformPrivate();
+
+ QList<QQuickItem *> items;
+};
+
+class Q_QUICK_EXPORT QQuickItemPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickItem)
+
+public:
+ static QQuickItemPrivate* get(QQuickItem *item) { return item->d_func(); }
+ static const QQuickItemPrivate* get(const QQuickItem *item) { return item->d_func(); }
+
+ QQuickItemPrivate();
+ ~QQuickItemPrivate();
+ void init(QQuickItem *parent);
+
+ QDeclarativeListProperty<QObject> data();
+ QDeclarativeListProperty<QObject> resources();
+ QDeclarativeListProperty<QQuickItem> children();
+
+ QDeclarativeListProperty<QDeclarativeState> states();
+ QDeclarativeListProperty<QDeclarativeTransition> transitions();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QQuickAnchorLine left() const;
+ QQuickAnchorLine right() const;
+ QQuickAnchorLine horizontalCenter() const;
+ QQuickAnchorLine top() const;
+ QQuickAnchorLine bottom() const;
+ QQuickAnchorLine verticalCenter() const;
+ QQuickAnchorLine baseline() const;
+
+ // data property
+ static void data_append(QDeclarativeListProperty<QObject> *, QObject *);
+ static int data_count(QDeclarativeListProperty<QObject> *);
+ static QObject *data_at(QDeclarativeListProperty<QObject> *, int);
+ static void data_clear(QDeclarativeListProperty<QObject> *);
+
+ // resources property
+ static QObject *resources_at(QDeclarativeListProperty<QObject> *, int);
+ static void resources_append(QDeclarativeListProperty<QObject> *, QObject *);
+ static int resources_count(QDeclarativeListProperty<QObject> *);
+ static void resources_clear(QDeclarativeListProperty<QObject> *);
+
+ // children property
+ static void children_append(QDeclarativeListProperty<QQuickItem> *, QQuickItem *);
+ static int children_count(QDeclarativeListProperty<QQuickItem> *);
+ static QQuickItem *children_at(QDeclarativeListProperty<QQuickItem> *, int);
+ static void children_clear(QDeclarativeListProperty<QQuickItem> *);
+
+ // transform property
+ static int transform_count(QDeclarativeListProperty<QQuickTransform> *list);
+ static void transform_append(QDeclarativeListProperty<QQuickTransform> *list, QQuickTransform *);
+ static QQuickTransform *transform_at(QDeclarativeListProperty<QQuickTransform> *list, int);
+ static void transform_clear(QDeclarativeListProperty<QQuickTransform> *list);
+
+ QQuickAnchors *anchors() const;
+ mutable QQuickAnchors *_anchors;
+ QQuickContents *_contents;
+
+ QDeclarativeNullableValue<qreal> baselineOffset;
+
+ struct AnchorLines {
+ AnchorLines(QQuickItem *);
+ QQuickAnchorLine left;
+ QQuickAnchorLine right;
+ QQuickAnchorLine hCenter;
+ QQuickAnchorLine top;
+ QQuickAnchorLine bottom;
+ QQuickAnchorLine vCenter;
+ QQuickAnchorLine baseline;
+ };
+ mutable AnchorLines *_anchorLines;
+ AnchorLines *anchorLines() const;
+
+ enum ChangeType {
+ Geometry = 0x01,
+ SiblingOrder = 0x02,
+ Visibility = 0x04,
+ Opacity = 0x08,
+ Destroyed = 0x10,
+ Parent = 0x20,
+ Children = 0x40,
+ Rotation = 0x80,
+ };
+
+ Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
+
+ enum GeometryChangeType {
+ NoChange = 0,
+ XChange = 0x01,
+ YChange = 0x02,
+ WidthChange = 0x04,
+ HeightChange = 0x08,
+ SizeChange = WidthChange | HeightChange,
+ GeometryChange = XChange | YChange | SizeChange
+ };
+
+ Q_DECLARE_FLAGS(GeometryChangeTypes, GeometryChangeType)
+
+ struct ChangeListener {
+ ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::ChangeTypes t) : listener(l), types(t), gTypes(GeometryChange) {}
+ ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::GeometryChangeTypes gt) : listener(l), types(Geometry), gTypes(gt) {}
+ QQuickItemChangeListener *listener;
+ QQuickItemPrivate::ChangeTypes types;
+ QQuickItemPrivate::GeometryChangeTypes gTypes; //NOTE: not used for ==
+ bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; }
+ };
+
+ void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types) {
+ changeListeners.append(ChangeListener(listener, types));
+ }
+ void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types);
+ void updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types);
+ void updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types);
+ QPODVector<ChangeListener,4> changeListeners;
+
+ QDeclarativeStateGroup *_states();
+ QDeclarativeStateGroup *_stateGroup;
+
+ QQuickItem::TransformOrigin origin:5;
+ quint32 flags:5;
+ bool widthValid:1;
+ bool heightValid:1;
+ bool componentComplete:1;
+ bool keepMouse:1;
+ bool keepTouch:1;
+ bool hoverEnabled:1;
+ bool smooth:1;
+ bool focus:1;
+ bool activeFocus:1;
+ bool notifiedFocus:1;
+ bool notifiedActiveFocus:1;
+ bool filtersChildMouseEvents:1;
+ bool explicitVisible:1;
+ bool effectiveVisible:1;
+ bool explicitEnable:1;
+ bool effectiveEnable:1;
+ bool polishScheduled:1;
+ bool inheritedLayoutMirror:1;
+ bool effectiveLayoutMirror:1;
+ bool isMirrorImplicit:1;
+ bool inheritMirrorFromParent:1;
+ bool inheritMirrorFromItem:1;
+ bool childrenDoNotOverlap:1;
+
+ QQuickCanvas *canvas;
+ QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QQuickCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
+
+ QQuickItem *parentItem;
+ QList<QQuickItem *> childItems;
+ mutable QList<QQuickItem *> *sortedChildItems;
+ QList<QQuickItem *> paintOrderChildItems() const;
+ void addChild(QQuickItem *);
+ void removeChild(QQuickItem *);
+ void siblingOrderChanged();
+
+ inline void markSortedChildrenDirty(QQuickItem *child) {
+ // If sortedChildItems == &childItems then all in childItems have z == 0
+ // and we don't need to invalidate if the changed item also has z == 0.
+ if (child->z() != 0. || sortedChildItems != &childItems) {
+ if (sortedChildItems != &childItems)
+ delete sortedChildItems;
+ sortedChildItems = 0;
+ }
+ }
+
+ class InitializationState {
+ public:
+ QQuickItem *getFocusScope(QQuickItem *item);
+ void clear();
+ void clear(QQuickItem *focusScope);
+ private:
+ QQuickItem *focusScope;
+ };
+ void initCanvas(InitializationState *, QQuickCanvas *);
+
+ QQuickItem *subFocusItem;
+
+ QTransform canvasToItemTransform() const;
+ QTransform itemToCanvasTransform() const;
+ void itemToParentTransform(QTransform &) const;
+
+ qreal x;
+ qreal y;
+ qreal width;
+ qreal height;
+ qreal implicitWidth;
+ qreal implicitHeight;
+
+ qreal z;
+ qreal scale;
+ qreal rotation;
+ qreal opacity;
+
+ QQuickLayoutMirroringAttached* attachedLayoutDirection;
+
+ Qt::MouseButtons acceptedMouseButtons;
+ Qt::InputMethodHints imHints;
+
+ QPointF transformOriginPoint;
+
+ virtual qreal getImplicitWidth() const;
+ virtual qreal getImplicitHeight() const;
+ virtual void implicitWidthChanged();
+ virtual void implicitHeightChanged();
+
+ void resolveLayoutMirror();
+ void setImplicitLayoutMirror(bool mirror, bool inherit);
+ void setLayoutMirror(bool mirror);
+ bool isMirrored() const {
+ return effectiveLayoutMirror;
+ }
+
+ void emitChildrenRectChanged(const QRectF &rect) {
+ Q_Q(QQuickItem);
+ emit q->childrenRectChanged(rect);
+ }
+
+ QPointF computeTransformOrigin() const;
+ QList<QQuickTransform *> transforms;
+ virtual void transformChanged();
+
+ QQuickItemKeyFilter *keyHandler;
+ void deliverKeyEvent(QKeyEvent *);
+ void deliverInputMethodEvent(QInputMethodEvent *);
+ void deliverFocusEvent(QFocusEvent *);
+ void deliverMouseEvent(QMouseEvent *);
+ void deliverWheelEvent(QWheelEvent *);
+ void deliverTouchEvent(QTouchEvent *);
+ void deliverHoverEvent(QHoverEvent *);
+ void deliverDragEvent(QEvent *);
+
+ bool calcEffectiveVisible() const;
+ void setEffectiveVisibleRecur(bool);
+ bool calcEffectiveEnable() const;
+ void setEffectiveEnableRecur(bool);
+
+ // XXX todo
+ enum DirtyType {
+ TransformOrigin = 0x00000001,
+ Transform = 0x00000002,
+ BasicTransform = 0x00000004,
+ Position = 0x00000008,
+ Size = 0x00000010,
+
+ ZValue = 0x00000020,
+ Content = 0x00000040,
+ Smooth = 0x00000080,
+ OpacityValue = 0x00000100,
+ ChildrenChanged = 0x00000200,
+ ChildrenStackingChanged = 0x00000400,
+ ParentChanged = 0x00000800,
+
+ Clip = 0x00001000,
+ Canvas = 0x00002000,
+
+ EffectReference = 0x00008000,
+ Visible = 0x00010000,
+ HideReference = 0x00020000,
+ // When you add an attribute here, don't forget to update
+ // dirtyToString()
+
+ TransformUpdateMask = TransformOrigin | Transform | BasicTransform | Position | Size | Canvas,
+ ComplexTransformUpdateMask = Transform | Canvas,
+ ContentUpdateMask = Size | Content | Smooth | Canvas,
+ ChildrenUpdateMask = ChildrenChanged | ChildrenStackingChanged | EffectReference | Canvas,
+
+ };
+ quint32 dirtyAttributes;
+ QString dirtyToString() const;
+ void dirty(DirtyType);
+ void addToDirtyList();
+ void removeFromDirtyList();
+ QQuickItem *nextDirtyItem;
+ QQuickItem**prevDirtyItem;
+
+ inline QSGTransformNode *itemNode();
+ inline QSGNode *childContainerNode();
+
+ /*
+ QSGNode order is:
+ - itemNode
+ - (opacityNode)
+ - (clipNode)
+ - (effectNode)
+ - groupNode
+ */
+
+ QSGTransformNode *itemNodeInstance;
+ QSGOpacityNode *opacityNode;
+ QQuickDefaultClipNode *clipNode;
+ QSGRootNode *rootNode;
+ QSGNode *groupNode;
+ QSGNode *paintNode;
+ QSGNode *beforePaintNode;
+
+ virtual QSGTransformNode *createTransformNode();
+
+ // A reference from an effect item means that this item is used by the effect, so
+ // it should insert a root node.
+ void refFromEffectItem(bool hide);
+ void derefFromEffectItem(bool unhide);
+ int effectRefCount;
+ int hideRefCount;
+
+ void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &);
+
+ virtual void mirrorChange() {}
+
+ static qint64 consistentTime;
+ static void setConsistentTime(qint64 t);
+ static void start(QElapsedTimer &);
+ static qint64 elapsed(QElapsedTimer &);
+ static qint64 restart(QElapsedTimer &);
+};
+
+/*
+ Key filters can be installed on a QQuickItem, but not removed. Currently they
+ are only used by attached objects (which are only destroyed on Item
+ destruction), so this isn't a problem. If in future this becomes any form
+ of public API, they will have to support removal too.
+*/
+class QQuickItemKeyFilter
+{
+public:
+ QQuickItemKeyFilter(QQuickItem * = 0);
+ virtual ~QQuickItemKeyFilter();
+
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ virtual void inputMethodEvent(QInputMethodEvent *event, bool post);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ virtual void componentComplete();
+
+ bool m_processPost;
+
+private:
+ QQuickItemKeyFilter *m_next;
+};
+
+class QQuickKeyNavigationAttachedPrivate : public QObjectPrivate
+{
+public:
+ QQuickKeyNavigationAttachedPrivate()
+ : QObjectPrivate(),
+ left(0), right(0), up(0), down(0), tab(0), backtab(0),
+ leftSet(false), rightSet(false), upSet(false), downSet(false),
+ tabSet(false), backtabSet(false) {}
+
+ QQuickItem *left;
+ QQuickItem *right;
+ QQuickItem *up;
+ QQuickItem *down;
+ QQuickItem *tab;
+ QQuickItem *backtab;
+ bool leftSet : 1;
+ bool rightSet : 1;
+ bool upSet : 1;
+ bool downSet : 1;
+ bool tabSet : 1;
+ bool backtabSet : 1;
+};
+
+class QQuickKeyNavigationAttached : public QObject, public QQuickItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickKeyNavigationAttached)
+
+ Q_PROPERTY(QQuickItem *left READ left WRITE setLeft NOTIFY leftChanged)
+ Q_PROPERTY(QQuickItem *right READ right WRITE setRight NOTIFY rightChanged)
+ Q_PROPERTY(QQuickItem *up READ up WRITE setUp NOTIFY upChanged)
+ Q_PROPERTY(QQuickItem *down READ down WRITE setDown NOTIFY downChanged)
+ Q_PROPERTY(QQuickItem *tab READ tab WRITE setTab NOTIFY tabChanged)
+ Q_PROPERTY(QQuickItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+
+ Q_ENUMS(Priority)
+
+public:
+ QQuickKeyNavigationAttached(QObject * = 0);
+
+ QQuickItem *left() const;
+ void setLeft(QQuickItem *);
+ QQuickItem *right() const;
+ void setRight(QQuickItem *);
+ QQuickItem *up() const;
+ void setUp(QQuickItem *);
+ QQuickItem *down() const;
+ void setDown(QQuickItem *);
+ QQuickItem *tab() const;
+ void setTab(QQuickItem *);
+ QQuickItem *backtab() const;
+ void setBacktab(QQuickItem *);
+
+ enum Priority { BeforeItem, AfterItem };
+ Priority priority() const;
+ void setPriority(Priority);
+
+ static QQuickKeyNavigationAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void upChanged();
+ void downChanged();
+ void tabChanged();
+ void backtabChanged();
+ void priorityChanged();
+
+private:
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ void setFocusNavigation(QQuickItem *currentItem, const char *dir);
+};
+
+class QQuickLayoutMirroringAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled RESET resetEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged)
+
+public:
+ explicit QQuickLayoutMirroringAttached(QObject *parent = 0);
+
+ bool enabled() const;
+ void setEnabled(bool);
+ void resetEnabled();
+
+ bool childrenInherit() const;
+ void setChildrenInherit(bool);
+
+ static QQuickLayoutMirroringAttached *qmlAttachedProperties(QObject *);
+Q_SIGNALS:
+ void enabledChanged();
+ void childrenInheritChanged();
+private:
+ friend class QQuickItemPrivate;
+ QQuickItemPrivate *itemPrivate;
+};
+
+class QQuickKeysAttachedPrivate : public QObjectPrivate
+{
+public:
+ QQuickKeysAttachedPrivate()
+ : QObjectPrivate(), inPress(false), inRelease(false)
+ , inIM(false), enabled(true), imeItem(0), item(0)
+ {}
+
+ bool isConnected(const char *signalName);
+
+ //loop detection
+ bool inPress:1;
+ bool inRelease:1;
+ bool inIM:1;
+
+ bool enabled : 1;
+
+ QQuickItem *imeItem;
+ QList<QQuickItem *> targets;
+ QQuickItem *item;
+};
+
+class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickKeysAttached)
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickItem> forwardTo READ forwardTo)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+
+ Q_ENUMS(Priority)
+
+public:
+ QQuickKeysAttached(QObject *parent=0);
+ ~QQuickKeysAttached();
+
+ bool enabled() const { Q_D(const QQuickKeysAttached); return d->enabled; }
+ void setEnabled(bool enabled) {
+ Q_D(QQuickKeysAttached);
+ if (enabled != d->enabled) {
+ d->enabled = enabled;
+ emit enabledChanged();
+ }
+ }
+
+ enum Priority { BeforeItem, AfterItem};
+ Priority priority() const;
+ void setPriority(Priority);
+
+ QDeclarativeListProperty<QQuickItem> forwardTo() {
+ Q_D(QQuickKeysAttached);
+ return QDeclarativeListProperty<QQuickItem>(this, d->targets);
+ }
+
+ virtual void componentComplete();
+
+ static QQuickKeysAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void enabledChanged();
+ void priorityChanged();
+ void pressed(QQuickKeyEvent *event);
+ void released(QQuickKeyEvent *event);
+ void digit0Pressed(QQuickKeyEvent *event);
+ void digit1Pressed(QQuickKeyEvent *event);
+ void digit2Pressed(QQuickKeyEvent *event);
+ void digit3Pressed(QQuickKeyEvent *event);
+ void digit4Pressed(QQuickKeyEvent *event);
+ void digit5Pressed(QQuickKeyEvent *event);
+ void digit6Pressed(QQuickKeyEvent *event);
+ void digit7Pressed(QQuickKeyEvent *event);
+ void digit8Pressed(QQuickKeyEvent *event);
+ void digit9Pressed(QQuickKeyEvent *event);
+
+ void leftPressed(QQuickKeyEvent *event);
+ void rightPressed(QQuickKeyEvent *event);
+ void upPressed(QQuickKeyEvent *event);
+ void downPressed(QQuickKeyEvent *event);
+ void tabPressed(QQuickKeyEvent *event);
+ void backtabPressed(QQuickKeyEvent *event);
+
+ void asteriskPressed(QQuickKeyEvent *event);
+ void numberSignPressed(QQuickKeyEvent *event);
+ void escapePressed(QQuickKeyEvent *event);
+ void returnPressed(QQuickKeyEvent *event);
+ void enterPressed(QQuickKeyEvent *event);
+ void deletePressed(QQuickKeyEvent *event);
+ void spacePressed(QQuickKeyEvent *event);
+ void backPressed(QQuickKeyEvent *event);
+ void cancelPressed(QQuickKeyEvent *event);
+ void selectPressed(QQuickKeyEvent *event);
+ void yesPressed(QQuickKeyEvent *event);
+ void noPressed(QQuickKeyEvent *event);
+ void context1Pressed(QQuickKeyEvent *event);
+ void context2Pressed(QQuickKeyEvent *event);
+ void context3Pressed(QQuickKeyEvent *event);
+ void context4Pressed(QQuickKeyEvent *event);
+ void callPressed(QQuickKeyEvent *event);
+ void hangupPressed(QQuickKeyEvent *event);
+ void flipPressed(QQuickKeyEvent *event);
+ void menuPressed(QQuickKeyEvent *event);
+ void volumeUpPressed(QQuickKeyEvent *event);
+ void volumeDownPressed(QQuickKeyEvent *event);
+
+private:
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ virtual void inputMethodEvent(QInputMethodEvent *, bool post);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ const QByteArray keyToSignal(int key) {
+ QByteArray keySignal;
+ if (key >= Qt::Key_0 && key <= Qt::Key_9) {
+ keySignal = "digit0Pressed";
+ keySignal[5] = '0' + (key - Qt::Key_0);
+ } else {
+ int i = 0;
+ while (sigMap[i].key && sigMap[i].key != key)
+ ++i;
+ keySignal = sigMap[i].sig;
+ }
+ return keySignal;
+ }
+
+ struct SigMap {
+ int key;
+ const char *sig;
+ };
+
+ static const SigMap sigMap[];
+};
+
+QSGTransformNode *QQuickItemPrivate::itemNode()
+{
+ if (!itemNodeInstance) {
+ itemNodeInstance = createTransformNode();
+ itemNodeInstance->setFlag(QSGNode::OwnedByParent, false);
+#ifdef QML_RUNTIME_TESTING
+ Q_Q(QQuickItem);
+ itemNodeInstance->description = QString::fromLatin1("QQuickItem(%1)").arg(QString::fromLatin1(q->metaObject()->className()));
+#endif
+ }
+ return itemNodeInstance;
+}
+
+QSGNode *QQuickItemPrivate::childContainerNode()
+{
+ if (!groupNode) {
+ groupNode = new QSGNode();
+ if (rootNode)
+ rootNode->appendChildNode(groupNode);
+ else if (clipNode)
+ clipNode->appendChildNode(groupNode);
+ else if (opacityNode)
+ opacityNode->appendChildNode(groupNode);
+ else
+ itemNode()->appendChildNode(groupNode);
+ groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, childrenDoNotOverlap);
+#ifdef QML_RUNTIME_TESTING
+ groupNode->description = QLatin1String("group");
+#endif
+ }
+ return groupNode;
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItemPrivate::ChangeTypes);
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickKeysAttached)
+QML_DECLARE_TYPEINFO(QQuickKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickKeyNavigationAttached)
+QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickLayoutMirroringAttached)
+QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKITEM_P_H
diff --git a/src/declarative/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h
index a021658f9e..a021658f9e 100644
--- a/src/declarative/items/qquickitemchangelistener_p.h
+++ b/src/quick/items/qquickitemchangelistener_p.h
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
new file mode 100644
index 0000000000..a9d8a193f0
--- /dev/null
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickitemsmodule_p.h"
+
+#include "qquickitem.h"
+#include "qquickitem_p.h"
+#include "qquickevents_p_p.h"
+#include "qquickrectangle_p.h"
+#include "qquickfocusscope_p.h"
+#include "qquicktext_p.h"
+#include "qquicktextinput_p.h"
+#include "qquicktextedit_p.h"
+#include "qquickimage_p.h"
+#include "qquickborderimage_p.h"
+#include "qquickscalegrid_p_p.h"
+#include "qquickmousearea_p.h"
+#include "qquickpincharea_p.h"
+#include "qquickflickable_p.h"
+#include "qquickflickable_p_p.h"
+#include "qquicklistview_p.h"
+#include "qquickvisualitemmodel_p.h"
+#include "qquickvisualdatamodel_p.h"
+#include "qquickgridview_p.h"
+#include "qquickpathview_p.h"
+#include <private/qdeclarativepath_p.h>
+#include <private/qdeclarativepathinterpolator_p.h>
+#include "qquickpositioners_p.h"
+#include "qquickrepeater_p.h"
+#include "qquickloader_p.h"
+#include "qquickanimatedimage_p.h"
+#include "qquickflipable_p.h"
+#include "qquicktranslate_p.h"
+#include "qquickstateoperations_p.h"
+#include "qquickanimation_p.h"
+#include <private/qquickshadereffect_p.h>
+#include <QtQuick/private/qquickshadereffectsource_p.h>
+//#include <private/qquickpincharea_p.h>
+#include <QtQuick/private/qquickcanvasitem_p.h>
+#include <QtQuick/private/qquickcontext2d_p.h>
+#include "qquicksprite_p.h"
+#include "qquickspriteimage_p.h"
+#include "qquickdrag_p.h"
+#include "qquickdroparea_p.h"
+#include "qquickmultipointtoucharea_p.h"
+#include <private/qdeclarativemetatype_p.h>
+
+static QDeclarativePrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject *parent)
+{
+ QQuickItem *item = qobject_cast<QQuickItem *>(obj);
+ if (!item)
+ return QDeclarativePrivate::IncompatibleObject;
+
+ QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent);
+ if (!parentItem)
+ return QDeclarativePrivate::IncompatibleParent;
+
+ item->setParentItem(parentItem);
+ return QDeclarativePrivate::Parented;
+}
+
+static bool compareQQuickAnchorLines(const void *p1, const void *p2)
+{
+ const QQuickAnchorLine &l1 = *static_cast<const QQuickAnchorLine*>(p1);
+ const QQuickAnchorLine &l2 = *static_cast<const QQuickAnchorLine*>(p2);
+ return l1 == l2;
+}
+
+static void qt_quickitems_defineModule(const char *uri, int major, int minor)
+{
+ QDeclarativePrivate::RegisterAutoParent autoparent = { 0, &qquickitem_autoParent };
+ QDeclarativePrivate::qmlregister(QDeclarativePrivate::AutoParentRegistration, &autoparent);
+
+#ifdef QT_NO_MOVIE
+ qmlRegisterTypeNotAvailable(uri,major,minor,"AnimatedImage", qApp->translate("QQuickAnimatedImage","Qt was built without support for QMovie"));
+#else
+ qmlRegisterType<QQuickAnimatedImage>(uri,major,minor,"AnimatedImage");
+#endif
+ qmlRegisterType<QQuickBorderImage>(uri,major,minor,"BorderImage");
+ qmlRegisterType<QQuickColumn>(uri,major,minor,"Column");
+ qmlRegisterType<QQuickFlickable>(uri,major,minor,"Flickable");
+ qmlRegisterType<QQuickFlipable>(uri,major,minor,"Flipable");
+ qmlRegisterType<QQuickFlow>(uri,major,minor,"Flow");
+// qmlRegisterType<QDeclarativeFocusPanel>(uri,major,minor,"FocusPanel");
+ qmlRegisterType<QQuickFocusScope>(uri,major,minor,"FocusScope");
+ qmlRegisterType<QQuickGradient>(uri,major,minor,"Gradient");
+ qmlRegisterType<QQuickGradientStop>(uri,major,minor,"GradientStop");
+ qmlRegisterType<QQuickGrid>(uri,major,minor,"Grid");
+ qmlRegisterType<QQuickGridView>(uri,major,minor,"GridView");
+ qmlRegisterType<QQuickImage>(uri,major,minor,"Image");
+ qmlRegisterType<QQuickItem>(uri,major,minor,"Item");
+ qmlRegisterType<QQuickListView>(uri,major,minor,"ListView");
+ qmlRegisterType<QQuickLoader>(uri,major,minor,"Loader");
+ qmlRegisterType<QQuickMouseArea>(uri,major,minor,"MouseArea");
+ qmlRegisterType<QDeclarativePath>(uri,major,minor,"Path");
+ qmlRegisterType<QDeclarativePathAttribute>(uri,major,minor,"PathAttribute");
+ qmlRegisterType<QDeclarativePathCubic>(uri,major,minor,"PathCubic");
+ qmlRegisterType<QDeclarativePathLine>(uri,major,minor,"PathLine");
+ qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
+ qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
+ qmlRegisterType<QDeclarativePathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
+ qmlRegisterType<QDeclarativePathArc>("QtQuick",2,0,"PathArc");
+ qmlRegisterType<QDeclarativePathSvg>("QtQuick",2,0,"PathSvg");
+ qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
+ qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner",
+ QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QIntValidator>(uri,major,minor,"IntValidator");
+ qmlRegisterType<QDoubleValidator>(uri,major,minor,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator");
+#endif
+ qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle");
+ qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater");
+ qmlRegisterType<QQuickRow>(uri,major,minor,"Row");
+ qmlRegisterType<QQuickTranslate>(uri,major,minor,"Translate");
+ qmlRegisterType<QQuickRotation>(uri,major,minor,"Rotation");
+ qmlRegisterType<QQuickScale>(uri,major,minor,"Scale");
+ qmlRegisterType<QQuickText>(uri,major,minor,"Text");
+ qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
+ qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
+ qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
+ qmlRegisterType<QQuickVisualDataModel>(uri,major,minor,"VisualDataModel");
+ qmlRegisterType<QQuickVisualDataGroup>(uri,major,minor,"VisualDataGroup");
+ qmlRegisterType<QQuickVisualItemModel>(uri,major,minor,"VisualItemModel");
+
+ qmlRegisterType<QQuickAnchors>();
+ qmlRegisterType<QQuickKeyEvent>();
+ qmlRegisterType<QQuickMouseEvent>();
+ qmlRegisterType<QQuickTransform>();
+ qmlRegisterType<QDeclarativePathElement>();
+ qmlRegisterType<QDeclarativeCurve>();
+ qmlRegisterType<QQuickScaleGrid>();
+ qmlRegisterType<QQuickTextLine>();
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QValidator>();
+#endif
+ qmlRegisterType<QQuickVisualModel>();
+ qmlRegisterType<QQuickPen>();
+ qmlRegisterType<QQuickFlickableVisibleArea>();
+ qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
+ QDeclarativeMetaType::setQQuickAnchorLineCompareFunction(compareQQuickAnchorLines);
+
+ qmlRegisterUncreatableType<QQuickKeyNavigationAttached>(uri,major,minor,"KeyNavigation",QQuickKeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
+ qmlRegisterUncreatableType<QQuickKeysAttached>(uri,major,minor,"Keys",QQuickKeysAttached::tr("Keys is only available via attached properties"));
+ qmlRegisterUncreatableType<QQuickLayoutMirroringAttached>(uri,major,minor,"LayoutMirroring", QQuickLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
+
+ qmlRegisterType<QQuickPinchArea>(uri,major,minor,"PinchArea");
+ qmlRegisterType<QQuickPinch>(uri,major,minor,"Pinch");
+ qmlRegisterType<QQuickPinchEvent>();
+
+ qmlRegisterType<QQuickShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
+ qmlRegisterType<QQuickShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
+ qmlRegisterUncreatableType<QQuickShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QQuickShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
+ qmlRegisterType<QQuickGridMesh>("QtQuick", 2, 0, "GridMesh");
+
+ qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
+
+ qmlRegisterType<QQuickCanvasItem>("QtQuick", 2, 0, "Canvas");
+
+ qmlRegisterType<QQuickSprite>("QtQuick", 2, 0, "Sprite");
+ qmlRegisterType<QQuickSpriteImage>("QtQuick", 2, 0, "SpriteImage");
+
+ qmlRegisterType<QQuickParentChange>(uri, major, minor,"ParentChange");
+ qmlRegisterType<QQuickAnchorChanges>(uri, major, minor,"AnchorChanges");
+ qmlRegisterType<QQuickAnchorSet>();
+ qmlRegisterType<QQuickAnchorAnimation>(uri, major, minor,"AnchorAnimation");
+ qmlRegisterType<QQuickParentAnimation>(uri, major, minor,"ParentAnimation");
+ qmlRegisterType<QQuickPathAnimation>("QtQuick",2,0,"PathAnimation");
+ qmlRegisterType<QDeclarativePathInterpolator>("QtQuick",2,0,"PathInterpolator");
+
+ qmlRegisterType<QQuickDropArea>("QtQuick", 2, 0, "DropArea");
+ qmlRegisterType<QQuickDropEvent>();
+ qmlRegisterType<QQuickDropAreaDrag>();
+ qmlRegisterUncreatableType<QQuickDrag>("QtQuick", 2, 0, "Drag", QQuickDragAttached::tr("Drag is only available via attached properties"));
+
+ qmlRegisterType<QQuickMultiPointTouchArea>("QtQuick", 2, 0, "MultiPointTouchArea");
+ qmlRegisterType<QQuickTouchPoint>("QtQuick", 2, 0, "TouchPoint");
+ qmlRegisterType<QQuickGrabGestureEvent>();
+}
+
+void QQuickItemsModule::defineModule()
+{
+ static bool initialized = false;
+ if (initialized)
+ return;
+ initialized = true;
+
+ // XXX todo - Remove before final integration...
+ QByteArray mode = qgetenv("QMLSCENE_IMPORT_NAME");
+ QByteArray name = "QtQuick";
+ int majorVersion = 2;
+ int minorVersion = 0;
+ if (mode == "quick1") {
+ majorVersion = 1;
+ } else if (mode == "qt") {
+ name = "Qt";
+ majorVersion = 4;
+ minorVersion = 7;
+ }
+
+ qt_quickitems_defineModule(name, majorVersion, minorVersion);
+}
+
diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h
new file mode 100644
index 0000000000..025a5fa0be
--- /dev/null
+++ b/src/quick/items/qquickitemsmodule_p.h
@@ -0,0 +1,63 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKITEMSMODULE_P_H
+#define QQUICKITEMSMODULE_P_H
+
+#include <qdeclarative.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItemsModule
+{
+public:
+ static void defineModule();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKITEMSMODULE_P_H
+
diff --git a/src/declarative/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index edbe2a5d06..edbe2a5d06 100644
--- a/src/declarative/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
new file mode 100644
index 0000000000..2b0b31ccd5
--- /dev/null
+++ b/src/quick/items/qquickitemview_p.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKITEMVIEW_P_H
+#define QQUICKITEMVIEW_P_H
+
+#include "qquickflickable_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeChangeSet;
+
+class QQuickItemViewPrivate;
+
+class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
+
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
+ Q_PROPERTY(QQuickItem *headerItem READ headerItem NOTIFY headerItemChanged)
+ Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
+ Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(PositionMode)
+
+public:
+ QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent = 0);
+ ~QQuickItemView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int count() const;
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QQuickItem *currentItem() const;
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+ QDeclarativeComponent *footer() const;
+ void setFooter(QDeclarativeComponent *);
+ QQuickItem *footerItem() const;
+
+ QDeclarativeComponent *header() const;
+ void setHeader(QDeclarativeComponent *);
+ QQuickItem *headerItem() const;
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *);
+
+ QQuickItem *highlightItem() const;
+
+ bool highlightFollowsCurrentItem() const;
+ virtual void setHighlightFollowsCurrentItem(bool);
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+ void resetPreferredHighlightBegin();
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+ void resetPreferredHighlightEnd();
+
+ int highlightMoveDuration() const;
+ virtual void setHighlightMoveDuration(int);
+
+ enum PositionMode { Beginning, Center, End, Visible, Contain };
+
+ Q_INVOKABLE void positionViewAtIndex(int index, int mode);
+ Q_INVOKABLE int indexAt(qreal x, qreal y) const;
+ Q_INVOKABLE void positionViewAtBeginning();
+ Q_INVOKABLE void positionViewAtEnd();
+
+ virtual void setContentX(qreal pos);
+ virtual void setContentY(qreal pos);
+ virtual qreal xOrigin() const;
+
+signals:
+ void modelChanged();
+ void delegateChanged();
+ void countChanged();
+ void currentIndexChanged();
+ void currentItemChanged();
+
+ void keyNavigationWrapsChanged();
+ void cacheBufferChanged();
+
+ void layoutDirectionChanged();
+ void effectiveLayoutDirectionChanged();
+
+ void headerChanged();
+ void footerChanged();
+ void headerItemChanged();
+ void footerItemChanged();
+
+ void highlightChanged();
+ void highlightItemChanged();
+ void highlightFollowsCurrentItemChanged();
+ void highlightRangeModeChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightMoveDurationChanged();
+
+protected:
+ virtual void updatePolish();
+ virtual void componentComplete();
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+
+protected slots:
+ virtual void updateSections() {}
+ void destroyRemoved();
+ void createdItem(int index, QQuickItem *item);
+ void initItem(int index, QQuickItem *item);
+ void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+ void destroyingItem(QQuickItem *item);
+ void animStopped();
+ void trackedPositionChanged();
+
+
+
+private:
+ Q_DECLARE_PRIVATE(QQuickItemView)
+};
+
+
+class Q_AUTOTEST_EXPORT QQuickItemViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
+ Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
+ Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
+
+public:
+ QQuickItemViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QQuickItemViewAttached() {}
+
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ QString nextSection() const { return m_nextSection; }
+ void setNextSection(const QString &sect) {
+ if (m_nextSection != sect) {
+ m_nextSection = sect;
+ emit nextSectionChanged();
+ }
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void delayRemoveChanged();
+
+ void add();
+ void remove();
+
+ void sectionChanged();
+ void prevSectionChanged();
+ void nextSectionChanged();
+
+public:
+ bool m_isCurrent : 1;
+ bool m_delayRemove : 1;
+
+ // current only used by list view
+ mutable QString m_section;
+ QString m_prevSection;
+ QString m_nextSection;
+};
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QQUICKITEMVIEW_P_H
+
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
new file mode 100644
index 0000000000..3b2c39bdeb
--- /dev/null
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKITEMVIEW_P_P_H
+#define QQUICKITEMVIEW_P_P_H
+
+#include "qquickitemview_p.h"
+#include "qquickflickable_p_p.h"
+#include "qquickvisualdatamodel_p.h"
+#include <private/qdeclarativechangeset_p.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class FxViewItem
+{
+public:
+ FxViewItem(QQuickItem *, bool own);
+ ~FxViewItem();
+
+ // these are positions and sizes along the current direction of scrolling/flicking
+ virtual qreal position() const = 0;
+ virtual qreal endPosition() const = 0;
+ virtual qreal size() const = 0;
+ virtual qreal sectionSize() const = 0;
+
+ virtual bool contains(qreal x, qreal y) const = 0;
+
+ QQuickItem *item;
+ bool ownItem;
+ int index;
+ QQuickItemViewAttached *attached;
+};
+
+class QQuickItemViewChangeSet
+{
+public:
+ QQuickItemViewChangeSet();
+
+ bool hasPendingChanges() const;
+ void prepare(int currentIndex, int count);
+ void reset();
+
+ void applyChanges(const QDeclarativeChangeSet &changeSet);
+
+ int itemCount;
+ int newCurrentIndex;
+ QDeclarativeChangeSet pendingChanges;
+ QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> removedItems;
+
+ bool active : 1;
+ bool currentChanged : 1;
+ bool currentRemoved : 1;
+};
+
+class QQuickItemViewPrivate : public QQuickFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QQuickItemView)
+public:
+ QQuickItemViewPrivate();
+
+ struct InsertionsResult {
+ QList<FxViewItem *> addedItems;
+ QList<FxViewItem *> movedBackwards;
+ qreal sizeAddedBeforeVisible;
+
+ InsertionsResult() : sizeAddedBeforeVisible(0) {}
+ };
+
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ enum MovementReason { Other, SetIndex, Mouse };
+
+ bool isValid() const;
+ qreal position() const;
+ qreal size() const;
+ qreal startPosition() const;
+ qreal endPosition() const;
+ qreal contentStartPosition() const;
+ int findLastVisibleIndex(int defaultValue = -1) const;
+ FxViewItem *visibleItem(int modelIndex) const;
+ FxViewItem *firstVisibleItem() const;
+ int mapFromModel(int modelIndex) const;
+
+ virtual void init();
+ virtual void clear();
+ virtual void updateViewport();
+
+ void regenerate();
+ void layout();
+ void refill();
+ void refill(qreal from, qreal to, bool doBuffer = false);
+ void mirrorChange();
+
+ FxViewItem *createItem(int modelIndex, bool asynchronous = false);
+ virtual void releaseItem(FxViewItem *item);
+
+ QQuickItem *createHighlightItem();
+ QQuickItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
+
+ void updateCurrent(int modelIndex);
+ void updateTrackedItem();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateVisibleIndex();
+ void positionViewAtIndex(int index, int mode);
+ void applyPendingChanges();
+ bool applyModelChanges();
+
+ void checkVisible() const;
+
+ void markExtentsDirty() {
+ if (layoutOrientation() == Qt::Vertical)
+ vData.markExtentsDirty();
+ else
+ hData.markExtentsDirty();
+ }
+
+ QDeclarativeGuard<QQuickVisualModel> model;
+ QVariant modelVariant;
+ int itemCount;
+ int buffer;
+ int bufferMode;
+ Qt::LayoutDirection layoutDirection;
+
+ MovementReason moveReason;
+
+ QList<FxViewItem *> visibleItems;
+ int visibleIndex;
+ int currentIndex;
+ FxViewItem *currentItem;
+ FxViewItem *trackedItem;
+ QHash<QQuickItem*,int> unrequestedItems;
+ int requestedIndex;
+ FxViewItem *requestedItem;
+ QQuickItemViewChangeSet currentChanges;
+
+ // XXX split into struct
+ QDeclarativeComponent *highlightComponent;
+ FxViewItem *highlight;
+ int highlightRange; // enum value
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ int highlightMoveDuration;
+
+ QDeclarativeComponent *headerComponent;
+ FxViewItem *header;
+ QDeclarativeComponent *footerComponent;
+ FxViewItem *footer;
+
+ mutable qreal minExtent;
+ mutable qreal maxExtent;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool deferredRelease : 1;
+ bool inApplyModelChanges : 1;
+ bool inViewportMoved : 1;
+ bool forceLayout : 1;
+ bool currentIndexCleared : 1;
+ bool haveHighlightRange : 1;
+ bool autoHighlight : 1;
+ bool highlightRangeStartValid : 1;
+ bool highlightRangeEndValid : 1;
+ bool fillCacheBuffer : 1;
+ bool inRequest : 1;
+ bool requestedAsync : 1;
+
+protected:
+ virtual Qt::Orientation layoutOrientation() const = 0;
+ virtual bool isContentFlowReversed() const = 0;
+
+ virtual qreal positionAt(int index) const = 0;
+ virtual qreal endPositionAt(int index) const = 0;
+ virtual qreal originPosition() const = 0;
+ virtual qreal lastPosition() const = 0;
+
+ virtual qreal headerSize() const = 0;
+ virtual qreal footerSize() const = 0;
+ virtual bool showHeaderForIndex(int index) const = 0;
+ virtual bool showFooterForIndex(int index) const = 0;
+ virtual void updateHeader() = 0;
+ virtual void updateFooter() = 0;
+
+ virtual void createHighlight() = 0;
+ virtual void updateHighlight() = 0;
+ virtual void resetHighlightPosition() = 0;
+
+ virtual void setPosition(qreal pos) = 0;
+ virtual void fixupPosition() = 0;
+
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) = 0;
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
+ virtual void visibleItemsChanged() = 0;
+
+ virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0;
+ virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0;
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem) = 0;
+ virtual void resetFirstItemPosition() = 0;
+ virtual void moveItemBy(FxViewItem *item, qreal forwards, qreal backwards) = 0;
+
+ virtual void layoutVisibleItems() = 0;
+ virtual void changedVisibleIndex(int newIndex) = 0;
+ virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, FxViewItem *, InsertionsResult *) = 0;
+ virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; }
+
+ virtual void initializeViewItem(FxViewItem *) {}
+ virtual void initializeCurrentItem() {}
+ virtual void updateSections() {}
+
+ virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKITEMVIEW_P_P_H
diff --git a/src/declarative/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 86af39075a..86af39075a 100644
--- a/src/declarative/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
new file mode 100644
index 0000000000..68746d8215
--- /dev/null
+++ b/src/quick/items/qquicklistview_p.h
@@ -0,0 +1,213 @@
+// Commit: 95814418f9d6adeba365c795462e8afb00138211
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKLISTVIEW_P_H
+#define QQUICKLISTVIEW_P_H
+
+#include "qquickitemview_p.h"
+
+#include <private/qdeclarativeguard_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickListView;
+class QQuickListViewPrivate;
+class Q_AUTOTEST_EXPORT QQuickViewSection : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged)
+ Q_ENUMS(SectionCriteria)
+ Q_ENUMS(LabelPositioning)
+public:
+ QQuickViewSection(QQuickListView *parent=0);
+
+ QString property() const { return m_property; }
+ void setProperty(const QString &);
+
+ enum SectionCriteria { FullString, FirstCharacter };
+ SectionCriteria criteria() const { return m_criteria; }
+ void setCriteria(SectionCriteria);
+
+ QDeclarativeComponent *delegate() const { return m_delegate; }
+ void setDelegate(QDeclarativeComponent *delegate);
+
+ QString sectionString(const QString &value);
+
+ enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 };
+ int labelPositioning() { return m_labelPositioning; }
+ void setLabelPositioning(int pos);
+
+Q_SIGNALS:
+ void propertyChanged();
+ void criteriaChanged();
+ void delegateChanged();
+ void labelPositioningChanged();
+
+private:
+ QString m_property;
+ SectionCriteria m_criteria;
+ QDeclarativeComponent *m_delegate;
+ int m_labelPositioning;
+ QQuickListViewPrivate *m_view;
+};
+
+
+class QQuickVisualModel;
+class QQuickListViewAttached;
+class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickListView)
+
+ // XXX deprecate these two properties (only duration should be necessary)
+ Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
+ Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
+
+ Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
+
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+
+ Q_PROPERTY(QQuickViewSection *section READ sectionCriteria CONSTANT)
+ Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
+
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
+
+ Q_ENUMS(Orientation)
+ Q_ENUMS(SnapMode)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QQuickListView(QQuickItem *parent=0);
+ ~QQuickListView();
+
+ qreal spacing() const;
+ void setSpacing(qreal spacing);
+
+ enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Orientation orientation() const;
+ void setOrientation(Orientation);
+
+ QQuickViewSection *sectionCriteria();
+ QString currentSection() const;
+
+ virtual void setHighlightFollowsCurrentItem(bool);
+
+ qreal highlightMoveSpeed() const;
+ void setHighlightMoveSpeed(qreal);
+
+ qreal highlightResizeSpeed() const;
+ void setHighlightResizeSpeed(qreal);
+
+ int highlightResizeDuration() const;
+ void setHighlightResizeDuration(int);
+
+ virtual void setHighlightMoveDuration(int);
+
+ enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ static QQuickListViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void incrementCurrentIndex();
+ void decrementCurrentIndex();
+
+Q_SIGNALS:
+ void spacingChanged();
+ void orientationChanged();
+ void currentSectionChanged();
+ void highlightMoveSpeedChanged();
+ void highlightResizeSpeedChanged();
+ void highlightResizeDurationChanged();
+ void snapModeChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
+
+protected Q_SLOTS:
+ void updateSections();
+};
+
+class QQuickListViewAttached : public QQuickItemViewAttached
+{
+ Q_OBJECT
+
+public:
+ QQuickListViewAttached(QObject *parent)
+ : QQuickItemViewAttached(parent), m_view(0) {}
+ ~QQuickListViewAttached() {}
+
+ Q_PROPERTY(QQuickListView *view READ view NOTIFY viewChanged)
+ QQuickListView *view() { return m_view; }
+ void setView(QQuickListView *view) {
+ if (view != m_view) {
+ m_view = view;
+ emit viewChanged();
+ }
+ }
+
+Q_SIGNALS:
+ void viewChanged();
+
+public:
+ QDeclarativeGuard<QQuickListView> m_view;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QQuickListView, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickListView)
+QML_DECLARE_TYPE(QQuickViewSection)
+
+QT_END_HEADER
+
+#endif // QQUICKLISTVIEW_P_H
diff --git a/src/declarative/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index f9fd9148ee..f9fd9148ee 100644
--- a/src/declarative/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
new file mode 100644
index 0000000000..0416164932
--- /dev/null
+++ b/src/quick/items/qquickloader_p.h
@@ -0,0 +1,121 @@
+// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKLOADER_P_H
+#define QQUICKLOADER_P_H
+
+#include "qquickimplicitsizeitem_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickLoaderPrivate;
+class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceComponentChanged)
+ Q_PROPERTY(QQuickItem *item READ item NOTIFY itemChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
+
+public:
+ QQuickLoader(QQuickItem *parent = 0);
+ virtual ~QQuickLoader();
+
+ bool active() const;
+ void setActive(bool newVal);
+
+ Q_INVOKABLE void setSource(QDeclarativeV8Function *);
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+ QDeclarativeComponent *sourceComponent() const;
+ void setSourceComponent(QDeclarativeComponent *);
+ void resetSourceComponent();
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ bool asynchronous() const;
+ void setAsynchronous(bool a);
+
+ QQuickItem *item() const;
+
+Q_SIGNALS:
+ void itemChanged();
+ void activeChanged();
+ void sourceChanged();
+ void sourceComponentChanged();
+ void statusChanged();
+ void progressChanged();
+ void loaded();
+ void asynchronousChanged();
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ void componentComplete();
+
+private:
+ void setSource(const QUrl &sourceUrl, bool needsClear);
+ void loadFromSource();
+ void loadFromSourceComponent();
+ Q_DISABLE_COPY(QQuickLoader)
+ Q_DECLARE_PRIVATE(QQuickLoader)
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceLoaded())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickLoader)
+
+QT_END_HEADER
+
+#endif // QQUICKLOADER_P_H
diff --git a/src/declarative/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 63d73e8da2..63d73e8da2 100644
--- a/src/declarative/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
diff --git a/src/declarative/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 8d4f3e86b0..8d4f3e86b0 100644
--- a/src/declarative/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h
new file mode 100644
index 0000000000..58da0468b8
--- /dev/null
+++ b/src/quick/items/qquickmousearea_p.h
@@ -0,0 +1,229 @@
+// Commit: c6e6a35aeb8794d68a3ca0c4e27a3a1181c066b5
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKMOUSEAREA_P_H
+#define QQUICKMOUSEAREA_P_H
+
+#include "qquickitem.h"
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDragAttached;
+class QQuickMouseEvent;
+class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
+ Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
+ //### consider drag and drop
+
+public:
+ QQuickDrag(QObject *parent=0);
+ ~QQuickDrag();
+
+ QQuickItem *target() const;
+ void setTarget(QQuickItem *target);
+ void resetTarget();
+
+ enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
+ Axis axis() const;
+ void setAxis(Axis);
+
+ qreal xmin() const;
+ void setXmin(qreal);
+ qreal xmax() const;
+ void setXmax(qreal);
+ qreal ymin() const;
+ void setYmin(qreal);
+ qreal ymax() const;
+ void setYmax(qreal);
+
+ bool active() const;
+ void setActive(bool);
+
+ bool filterChildren() const;
+ void setFilterChildren(bool);
+
+ static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void targetChanged();
+ void axisChanged();
+ void minimumXChanged();
+ void maximumXChanged();
+ void minimumYChanged();
+ void maximumYChanged();
+ void activeChanged();
+ void filterChildrenChanged();
+
+private:
+ QQuickItem *_target;
+ Axis _axis;
+ qreal _xmin;
+ qreal _xmax;
+ qreal _ymin;
+ qreal _ymax;
+ bool _active : 1;
+ bool _filterChildren: 1;
+ Q_DISABLE_COPY(QQuickDrag)
+};
+
+class QQuickMouseAreaPrivate;
+// used in QtLocation
+class Q_QUICK_EXPORT QQuickMouseArea : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal mouseX READ mouseX NOTIFY mouseXChanged)
+ Q_PROPERTY(qreal mouseY READ mouseY NOTIFY mouseYChanged)
+ Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedChanged)
+ Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
+ Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
+ Q_PROPERTY(QQuickDrag *drag READ drag CONSTANT) //### add flicking to QQuickDrag or add a QDeclarativeFlick ???
+ Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged)
+ Q_PROPERTY(bool propagateComposedEvents READ propagateComposedEvents WRITE setPropagateComposedEvents NOTIFY propagateComposedEventsChanged)
+
+public:
+ QQuickMouseArea(QQuickItem *parent=0);
+ ~QQuickMouseArea();
+
+ qreal mouseX() const;
+ qreal mouseY() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool hovered() const;
+ bool pressed() const;
+
+ Qt::MouseButtons pressedButtons() const;
+
+ Qt::MouseButtons acceptedButtons() const;
+ void setAcceptedButtons(Qt::MouseButtons buttons);
+
+ bool hoverEnabled() const;
+ void setHoverEnabled(bool h);
+
+ QQuickDrag *drag();
+
+ bool preventStealing() const;
+ void setPreventStealing(bool prevent);
+
+ bool propagateComposedEvents() const;
+ void setPropagateComposedEvents(bool propagate);
+
+Q_SIGNALS:
+ void hoveredChanged();
+ void pressedChanged();
+ void enabledChanged();
+ void acceptedButtonsChanged();
+ void hoverEnabledChanged();
+ void positionChanged(QQuickMouseEvent *mouse);
+ void mouseXChanged(QQuickMouseEvent *mouse);
+ void mouseYChanged(QQuickMouseEvent *mouse);
+ void preventStealingChanged();
+ void propagateComposedEventsChanged();
+
+ void pressed(QQuickMouseEvent *mouse);
+ void pressAndHold(QQuickMouseEvent *mouse);
+ void released(QQuickMouseEvent *mouse);
+ void clicked(QQuickMouseEvent *mouse);
+ void doubleClicked(QQuickMouseEvent *mouse);
+ void entered();
+ void exited();
+ void canceled();
+
+protected:
+ void setHovered(bool);
+ bool setPressed(bool);
+ bool sendMouseEvent(QMouseEvent *event);
+
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QMouseEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *event);
+ virtual void mouseUngrabEvent();
+ virtual void hoverEnterEvent(QHoverEvent *event);
+ virtual void hoverMoveEvent(QHoverEvent *event);
+ virtual void hoverLeaveEvent(QHoverEvent *event);
+ virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
+ virtual void timerEvent(QTimerEvent *event);
+ virtual void windowDeactivateEvent();
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void itemChange(ItemChange change, const ItemChangeData& value);
+
+private:
+ void handlePress();
+ void handleRelease();
+ void ungrabMouse();
+
+private:
+ Q_DISABLE_COPY(QQuickMouseArea)
+ Q_DECLARE_PRIVATE(QQuickMouseArea)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickDrag)
+QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickMouseArea)
+
+QT_END_HEADER
+
+#endif // QQUICKMOUSEAREA_P_H
diff --git a/src/declarative/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h
index c1c53c4302..c1c53c4302 100644
--- a/src/declarative/items/qquickmousearea_p_p.h
+++ b/src/quick/items/qquickmousearea_p_p.h
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
new file mode 100644
index 0000000000..c94abc6c9d
--- /dev/null
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -0,0 +1,729 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickmultipointtoucharea_p.h"
+#include <QtQuick/qquickcanvas.h>
+#include <QEvent>
+#include <QMouseEvent>
+#include <math.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass TouchPoint QQuickTouchPoint
+ \inqmlmodule QtQuick 2
+ \ingroup qml-event-elements
+ \brief The TouchPoint element describes a touch point in a MultiPointTouchArea.
+
+ The TouchPoint element contains information about a touch point, such as the current
+ position, pressure, and area.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TouchPoint::pointId
+
+ This property holds the point id of the touch point.
+
+ Each touch point within a MultiPointTouchArea will have a unique id.
+*/
+void QQuickTouchPoint::setPointId(int id)
+{
+ if (_id == id)
+ return;
+ _id = id;
+ emit pointIdChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::x
+ \qmlproperty real QtQuick2::TouchPoint::y
+
+ These properties hold the current position of the touch point.
+*/
+
+void QQuickTouchPoint::setX(qreal x)
+{
+ if (_x == x)
+ return;
+ _x = x;
+ emit xChanged();
+}
+
+void QQuickTouchPoint::setY(qreal y)
+{
+ if (_y == y)
+ return;
+ _y = y;
+ emit yChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::pressure
+ \qmlproperty rectangle QtQuick2::TouchPoint::area
+
+ These properties hold additional information about the current state of the touch point.
+
+ \list
+ \i \c pressure is a value in the range of 0.0 to 1.0.
+ \i \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point.
+ \endlist
+*/
+void QQuickTouchPoint::setPressure(qreal pressure)
+{
+ if (_pressure == pressure)
+ return;
+ _pressure = pressure;
+ emit pressureChanged();
+}
+
+void QQuickTouchPoint::setArea(const QRectF &area)
+{
+ if (_area == area)
+ return;
+ _area = area;
+ emit areaChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TouchPoint::valid
+
+ This property holds whether the touch point is valid.
+
+ An invalid touch point is one that has not yet been pressed,
+ or has already been released.
+*/
+void QQuickTouchPoint::setValid(bool valid)
+{
+ if (_valid == valid)
+ return;
+ _valid = valid;
+ emit validityChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::startX
+ \qmlproperty real QtQuick2::TouchPoint::startY
+
+ These properties hold the starting position of the touch point.
+*/
+
+void QQuickTouchPoint::setStartX(qreal startX)
+{
+ if (_startX == startX)
+ return;
+ _startX = startX;
+ emit startXChanged();
+}
+
+void QQuickTouchPoint::setStartY(qreal startY)
+{
+ if (_startY == startY)
+ return;
+ _startY = startY;
+ emit startYChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::previousX
+ \qmlproperty real QtQuick2::TouchPoint::previousY
+
+ These properties hold the previous position of the touch point.
+*/
+void QQuickTouchPoint::setPreviousX(qreal previousX)
+{
+ if (_previousX == previousX)
+ return;
+ _previousX = previousX;
+ emit previousXChanged();
+}
+
+void QQuickTouchPoint::setPreviousY(qreal previousY)
+{
+ if (_previousY == previousY)
+ return;
+ _previousY = previousY;
+ emit previousYChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::sceneX
+ \qmlproperty real QtQuick2::TouchPoint::sceneY
+
+ These properties hold the current position of the touch point in scene coordinates.
+*/
+
+void QQuickTouchPoint::setSceneX(qreal sceneX)
+{
+ if (_sceneX == sceneX)
+ return;
+ _sceneX = sceneX;
+ emit sceneXChanged();
+}
+
+void QQuickTouchPoint::setSceneY(qreal sceneY)
+{
+ if (_sceneY == sceneY)
+ return;
+ _sceneY = sceneY;
+ emit sceneYChanged();
+}
+
+/*!
+ \qmlclass MultiPointTouchArea QQuickMultiPointTouchArea
+ \inqmlmodule QtQuick 2
+ \brief The MultiPointTouchArea item enables handling of multiple touch points.
+ \inherits Item
+
+ A MultiPointTouchArea is an invisible item that is used to track multiple touch points.
+
+ The \l enabled property is used to enable and disable touch handling. When disabled,
+ the touch area becomes transparent to mouse/touch events.
+
+ MultiPointTouchArea can be used in two ways:
+
+ \list
+ \o setting \c touchPoints to provide touch point objects with properties that can be bound to
+ \o using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers
+ \endlist
+
+ While a MultiPointTouchArea \i can take exclusive ownership of certain touch points, it is also possible to have
+ multiple MultiPointTouchAreas active at the same time, each operating on a different set of touch points.
+
+ \sa TouchPoint
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsPressed(list<TouchPoint> touchPoints)
+
+ This handler is called when new touch points are added. \a touchPoints is a list of these new points.
+
+ If minimumTouchPoints is set to a value greater than one, this handler will not be called until the minimum number
+ of required touch points has been reached. At that point, touchPointsPressed will be called with all the current touch points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsUpdated(list<TouchPoint> touchPoints)
+
+ This handler is called when existing touch points are updated. \a touchPoints is a list of these updated points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsReleased(list<TouchPoint> touchPoints)
+
+ This handler is called when existing touch points are removed. \a touchPoints is a list of these removed points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsCanceled(list<TouchPoint> touchPoints)
+
+ This handler is called when new touch events have been canceled because another element stole the touch event handling.
+
+ This signal is for advanced use: it is useful when there is more than one MultiPointTouchArea
+ that is handling input, or when there is a MultiPointTouchArea inside a \l Flickable. In the latter
+ case, if you execute some logic on the touchPointsPressed signal and then start dragging, the
+ \l Flickable may steal the touch handling from the MultiPointTouchArea. In these cases, to reset
+ the logic when the MultiPointTouchArea has lost the touch handling to the \l Flickable,
+ \c onTouchPointsCanceled should be used in addition to onTouchPointsReleased.
+
+ \a touchPoints is the list of canceled points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::gestureStarted(GestureEvent gesture)
+
+ This handler is called when the global drag threshold has been reached.
+
+ This function is typically used when a MultiPointTouchAreas has been nested in a Flickable or another MultiPointTouchArea.
+ Wnen the threshold has been reached, and the handler called, you can determine whether or not the touch
+ area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
+ gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
+
+ The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchUpdated(list<TouchPoint> touchPoints)
+
+ This handler is called when the touch points handled by the MultiPointTouchArea change. This includes adding new touch points,
+ removing previous touch points, as well as updating current touch point data. \a touchPoints is the list of all current touch
+ points.
+*/
+
+/*!
+ \qmlproperty list<TouchPoint> QtQuick2::MultiPointTouchArea::touchPoints
+
+ This property holds a set of user-defined touch point objects that can be bound to.
+
+ In the following example, we have two small rectangles that follow our touch points.
+
+ \snippet doc/src/snippets/declarative/multipointtoucharea/multipointtoucharea.qml 0
+
+ By default this property holds an empty list.
+
+ \sa TouchPoint
+*/
+
+QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
+ : QQuickItem(parent),
+ _minimumTouchPoints(0),
+ _maximumTouchPoints(INT_MAX),
+ _stealMouse(false)
+{
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFiltersChildMouseEvents(true);
+}
+
+QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
+{
+ clearTouchLists();
+ foreach (QObject *obj, _touchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::MultiPointTouchArea::minimumTouchPoints
+ \qmlproperty int QtQuick2::MultiPointTouchArea::maximumTouchPoints
+
+ These properties hold the range of touch points to be handled by the touch area.
+
+ These are convenience that allow you to, for example, have nested MultiPointTouchAreas,
+ one handling two finger touches, and another handling three finger touches.
+
+ By default, all touch points within the touch area are handled.
+*/
+
+int QQuickMultiPointTouchArea::minimumTouchPoints() const
+{
+ return _minimumTouchPoints;
+}
+
+void QQuickMultiPointTouchArea::setMinimumTouchPoints(int num)
+{
+ if (_minimumTouchPoints == num)
+ return;
+ _minimumTouchPoints = num;
+ emit minimumTouchPointsChanged();
+}
+
+int QQuickMultiPointTouchArea::maximumTouchPoints() const
+{
+ return _maximumTouchPoints;
+}
+
+void QQuickMultiPointTouchArea::setMaximumTouchPoints(int num)
+{
+ if (_maximumTouchPoints == num)
+ return;
+ _maximumTouchPoints = num;
+ emit maximumTouchPointsChanged();
+}
+
+void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ //if e.g. a parent Flickable has the mouse grab, don't process the touch events
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ if (grabber && grabber != this && grabber->keepMouseGrab() && grabber->isEnabled()) {
+ QQuickItem *item = this;
+ while ((item = item->parentItem())) {
+ if (item == grabber)
+ return;
+ }
+ }
+ updateTouchData(event);
+ if (event->type() == QEvent::TouchEnd) {
+ //TODO: move to canvas
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ }
+ break;
+ }
+ default:
+ QQuickItem::touchEvent(event);
+ break;
+ }
+}
+
+void QQuickMultiPointTouchArea::grabGesture()
+{
+ _stealMouse = true;
+
+ grabMouse();
+ setKeepMouseGrab(true);
+
+ grabTouchPoints(_touchPoints.keys());
+ setKeepTouchGrab(true);
+}
+
+void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
+{
+ bool ended = false;
+ bool moved = false;
+ bool started = false;
+
+ clearTouchLists();
+ QTouchEvent *e = static_cast<QTouchEvent*>(event);
+ QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints();
+ int numTouchPoints = touchPoints.count();
+ //always remove released touches, and make sure we handle all releases before adds.
+ foreach (QTouchEvent::TouchPoint p, touchPoints) {
+ Qt::TouchPointState touchPointState = p.state();
+ int id = p.id();
+ if (touchPointState & Qt::TouchPointReleased) {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
+ if (!dtp)
+ continue;
+ _releasedTouchPoints.append(dtp);
+ _touchPoints.remove(id);
+ ended = true;
+ }
+ }
+ if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
+ foreach (QTouchEvent::TouchPoint p, touchPoints) {
+ Qt::TouchPointState touchPointState = p.state();
+ int id = p.id();
+ if (touchPointState & Qt::TouchPointReleased) {
+ //handled above
+ } else if (!_touchPoints.contains(id)) { //could be pressed, moved, or stationary
+ addTouchPoint(&p);
+ started = true;
+ } else if (touchPointState & Qt::TouchPointMoved) {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ Q_ASSERT(dtp);
+ _movedTouchPoints.append(dtp);
+ updateTouchPoint(dtp,&p);
+ moved = true;
+ } else {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ Q_ASSERT(dtp);
+ updateTouchPoint(dtp,&p);
+ }
+ }
+
+ //see if we should be grabbing the gesture
+ if (!_stealMouse /* !ignoring gesture*/) {
+ bool offerGrab = false;
+ const int dragThreshold = qApp->styleHints()->startDragDistance();
+ foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
+ if (p.state() == Qt::TouchPointReleased)
+ continue;
+ const QPointF &currentPos = p.scenePos();
+ const QPointF &startPos = p.startScenePos();
+ if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
+ offerGrab = true;
+ else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
+ offerGrab = true;
+ if (offerGrab)
+ break;
+ }
+
+ if (offerGrab) {
+ QQuickGrabGestureEvent event;
+ event._touchPoints = _touchPoints.values();
+ emit gestureStarted(&event);
+ if (event.wantsGrab())
+ grabGesture();
+ }
+ }
+
+ if (ended) emit(touchPointsReleased(_releasedTouchPoints));
+ if (moved) emit(touchPointsUpdated(_movedTouchPoints));
+ if (started) emit(touchPointsPressed(_pressedTouchPoints));
+ if (!_touchPoints.isEmpty()) emit touchUpdated(_touchPoints.values());
+ }
+}
+
+void QQuickMultiPointTouchArea::clearTouchLists()
+{
+ foreach (QObject *obj, _releasedTouchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ else
+ dtp->setValid(false);
+ }
+ _releasedTouchPoints.clear();
+ _pressedTouchPoints.clear();
+ _movedTouchPoints.clear();
+}
+
+void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
+{
+ QQuickTouchPoint *dtp = 0;
+ foreach (QQuickTouchPoint* tp, _touchPrototypes) {
+ if (!tp->isValid()) {
+ tp->setValid(true);
+ dtp = tp;
+ break;
+ }
+ }
+
+ if (dtp == 0)
+ dtp = new QQuickTouchPoint(false);
+ dtp->setPointId(p->id());
+ updateTouchPoint(dtp,p);
+ _touchPoints.insert(p->id(),dtp);
+ //we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed
+ if (p->state() & Qt::TouchPointPressed || p->state() & Qt::TouchPointMoved || p->state() & Qt::TouchPointStationary)
+ _pressedTouchPoints.append(dtp);
+}
+
+void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
+{
+ int id = _touchPrototypes.count();
+ prototype->setPointId(id);
+ _touchPrototypes.insert(id, prototype);
+}
+
+void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QTouchEvent::TouchPoint *p)
+{
+ //TODO: if !qmlDefined, could bypass setters.
+ // also, should only emit signals after all values have been set
+ dtp->setX(p->pos().x());
+ dtp->setY(p->pos().y());
+ dtp->setPressure(p->pressure());
+ dtp->setArea(p->rect());
+ dtp->setStartX(p->startPos().x());
+ dtp->setStartY(p->startPos().y());
+ dtp->setPreviousX(p->lastPos().x());
+ dtp->setPreviousY(p->lastPos().y());
+ dtp->setSceneX(p->scenePos().x());
+ dtp->setSceneY(p->scenePos().y());
+}
+
+void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
+{
+ if (!isEnabled()) {
+ QQuickItem::mousePressEvent(event);
+ return;
+ }
+
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ event->setAccepted(true);
+}
+
+void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!isEnabled()) {
+ QQuickItem::mouseMoveEvent(event);
+ return;
+ }
+
+ //do nothing
+}
+
+void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
+{
+ _stealMouse = false;
+ if (!isEnabled()) {
+ QQuickItem::mouseReleaseEvent(event);
+ return;
+ }
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+}
+
+void QQuickMultiPointTouchArea::ungrab()
+{
+ if (_touchPoints.count()) {
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this) {
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ }
+ setKeepTouchGrab(false);
+ emit touchPointsCanceled(_touchPoints.values());
+ clearTouchLists();
+ foreach (QObject *obj, _touchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ else
+ dtp->setValid(false);
+ }
+ _touchPoints.clear();
+ }
+}
+
+void QQuickMultiPointTouchArea::mouseUngrabEvent()
+{
+ ungrab();
+}
+
+void QQuickMultiPointTouchArea::touchUngrabEvent()
+{
+ ungrab();
+}
+
+bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
+{
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ bool stealThisEvent = _stealMouse;
+ if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
+ QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ mouseEvent.setAccepted(false);
+
+ switch (mouseEvent.type()) {
+ case QEvent::MouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::MouseButtonPress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = c->mouseGrabberItem();
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return stealThisEvent;
+ }
+ if (event->type() == QEvent::MouseButtonRelease) {
+ _stealMouse = false;
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+ }
+ return false;
+}
+
+bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *i, QEvent *event)
+{
+ if (!isEnabled() || !isVisible())
+ return QQuickItem::childMouseEventFilter(i, event);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ return sendMouseEvent(static_cast<QMouseEvent *>(event));
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ if (!shouldFilter(event))
+ return false;
+ updateTouchData(event);
+ return _stealMouse;
+ case QEvent::TouchEnd: {
+ if (!shouldFilter(event))
+ return false;
+ updateTouchData(event);
+ //TODO: verify this behavior
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ }
+ break;
+ default:
+ break;
+ }
+ return QQuickItem::childMouseEventFilter(i, event);
+}
+
+bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
+{
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ bool disabledItem = grabber && !grabber->isEnabled();
+ bool stealThisEvent = _stealMouse;
+ bool contains = false;
+ if (!stealThisEvent) {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+ contains = myRect.contains(me->windowPos());
+ }
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ QTouchEvent *te = static_cast<QTouchEvent*>(event);
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+ foreach (const QTouchEvent::TouchPoint &point, te->touchPoints()) {
+ if (myRect.contains(point.scenePos())) {
+ contains = true;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if ((stealThisEvent || contains) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
+ return true;
+ }
+ ungrab();
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
new file mode 100644
index 0000000000..aee18a376b
--- /dev/null
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKMULTIPOINTTOUCHAREA_H
+#define QQUICKMULTIPOINTTOUCHAREA_H
+
+#include "qquickitem.h"
+#include "qevent.h"
+
+#include <QMap>
+#include <QList>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qstylehints.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMultiPointTouchArea;
+class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged)
+ Q_PROPERTY(int pointId READ pointId NOTIFY pointIdChanged)
+ Q_PROPERTY(qreal x READ x NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y NOTIFY yChanged)
+ Q_PROPERTY(qreal pressure READ pressure NOTIFY pressureChanged)
+ Q_PROPERTY(QRectF area READ area NOTIFY areaChanged)
+
+ Q_PROPERTY(qreal startX READ startX NOTIFY startXChanged)
+ Q_PROPERTY(qreal startY READ startY NOTIFY startYChanged)
+ Q_PROPERTY(qreal previousX READ previousX NOTIFY previousXChanged)
+ Q_PROPERTY(qreal previousY READ previousY NOTIFY previousYChanged)
+ Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged)
+ Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged)
+
+public:
+ QQuickTouchPoint(bool qmlDefined = true)
+ : _id(0),
+ _x(0.0), _y(0.0),
+ _pressure(0.0),
+ _qmlDefined(qmlDefined),
+ _valid(!qmlDefined),
+ _previousX(0.0), _previousY(0.0),
+ _sceneX(0.0), _sceneY(0.0)
+ {}
+
+ int pointId() const { return _id; }
+ void setPointId(int id);
+
+ qreal x() const { return _x; }
+ void setX(qreal x);
+
+ qreal y() const { return _y; }
+ void setY(qreal y);
+
+ qreal pressure() const { return _pressure; }
+ void setPressure(qreal pressure);
+
+ QRectF area() const { return _area; }
+ void setArea(const QRectF &area);
+
+ bool isQmlDefined() { return _qmlDefined; }
+
+ bool isValid() { return _valid; }
+ void setValid(bool valid);
+
+ qreal startX() const { return _startX; }
+ void setStartX(qreal startX);
+
+ qreal startY() const { return _startY; }
+ void setStartY(qreal startY);
+
+ qreal previousX() const { return _previousX; }
+ void setPreviousX(qreal previousX);
+
+ qreal previousY() const { return _previousY; }
+ void setPreviousY(qreal previousY);
+
+ qreal sceneX() const { return _sceneX; }
+ void setSceneX(qreal sceneX);
+
+ qreal sceneY() const { return _sceneY; }
+ void setSceneY(qreal sceneY);
+
+
+Q_SIGNALS:
+ void pointIdChanged();
+ void xChanged();
+ void yChanged();
+ void pressureChanged();
+ void areaChanged();
+ void validityChanged();
+ void startXChanged();
+ void startYChanged();
+ void previousXChanged();
+ void previousYChanged();
+ void sceneXChanged();
+ void sceneYChanged();
+
+private:
+ friend class QQuickMultiPointTouchArea;
+ int _id;
+ qreal _x;
+ qreal _y;
+ qreal _pressure;
+ QRectF _area;
+ bool _qmlDefined;
+ bool _valid;
+ qreal _startX;
+ qreal _startY;
+ qreal _previousX;
+ qreal _previousY;
+ qreal _sceneX;
+ qreal _sceneY;
+};
+
+class QQuickGrabGestureEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeListProperty<QObject> touchPoints READ touchPoints)
+ Q_PROPERTY(qreal dragThreshold READ dragThreshold)
+public:
+ QQuickGrabGestureEvent() : _grab(false), _dragThreshold(qApp->styleHints()->startDragDistance()) {}
+
+ Q_INVOKABLE void grab() { _grab = true; }
+ bool wantsGrab() const { return _grab; }
+
+ QDeclarativeListProperty<QObject> touchPoints() {
+ return QDeclarativeListProperty<QObject>(this, _touchPoints);
+ }
+ qreal dragThreshold() const { return _dragThreshold; }
+
+private:
+ friend class QQuickMultiPointTouchArea;
+ bool _grab;
+ qreal _dragThreshold;
+ QList<QObject*> _touchPoints;
+};
+
+class Q_AUTOTEST_EXPORT QQuickMultiPointTouchArea : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeListProperty<QQuickTouchPoint> touchPoints READ touchPoints)
+ Q_PROPERTY(int minimumTouchPoints READ minimumTouchPoints WRITE setMinimumTouchPoints NOTIFY minimumTouchPointsChanged)
+ Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints WRITE setMaximumTouchPoints NOTIFY maximumTouchPointsChanged)
+
+public:
+ QQuickMultiPointTouchArea(QQuickItem *parent=0);
+ ~QQuickMultiPointTouchArea();
+
+ int minimumTouchPoints() const;
+ void setMinimumTouchPoints(int num);
+ int maximumTouchPoints() const;
+ void setMaximumTouchPoints(int num);
+
+ QDeclarativeListProperty<QQuickTouchPoint> touchPoints() {
+ return QDeclarativeListProperty<QQuickTouchPoint>(this, 0, QQuickMultiPointTouchArea::touchPoint_append, QQuickMultiPointTouchArea::touchPoint_count, QQuickMultiPointTouchArea::touchPoint_at, 0);
+ }
+
+ static void touchPoint_append(QDeclarativeListProperty<QQuickTouchPoint> *list, QQuickTouchPoint* touch) {
+ QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
+ q->addTouchPrototype(touch);
+ }
+
+ static int touchPoint_count(QDeclarativeListProperty<QQuickTouchPoint> *list) {
+ QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
+ return q->_touchPrototypes.count();
+ }
+
+ static QQuickTouchPoint* touchPoint_at(QDeclarativeListProperty<QQuickTouchPoint> *list, int index) {
+ QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
+ return q->_touchPrototypes[index];
+ }
+
+Q_SIGNALS:
+ void touchPointsPressed(const QList<QObject*> &touchPoints);
+ void touchPointsUpdated(const QList<QObject*> &touchPoints);
+ void touchPointsReleased(const QList<QObject*> &touchPoints);
+ void touchPointsCanceled(const QList<QObject*> &touchPoints);
+ void gestureStarted(QQuickGrabGestureEvent *gesture);
+ void touchUpdated(const QList<QObject*> &touchPoints);
+ void minimumTouchPointsChanged();
+ void maximumTouchPointsChanged();
+
+protected:
+ void touchEvent(QTouchEvent *);
+ bool childMouseEventFilter(QQuickItem *i, QEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseUngrabEvent();
+ void touchUngrabEvent();
+
+ void addTouchPrototype(QQuickTouchPoint* prototype);
+ void addTouchPoint(const QTouchEvent::TouchPoint *p);
+ void clearTouchLists();
+
+ void updateTouchPoint(QQuickTouchPoint*, const QTouchEvent::TouchPoint*);
+ void updateTouchData(QEvent*);
+
+ bool sendMouseEvent(QMouseEvent *event);
+ bool shouldFilter(QEvent *event);
+ void grabGesture();
+
+private:
+ void ungrab();
+ QMap<int,QQuickTouchPoint*> _touchPrototypes; //TouchPoints defined in QML
+ QMap<int,QObject*> _touchPoints; //All current touch points
+ QList<QObject*> _releasedTouchPoints;
+ QList<QObject*> _pressedTouchPoints;
+ QList<QObject*> _movedTouchPoints;
+ int _minimumTouchPoints;
+ int _maximumTouchPoints;
+ bool _stealMouse;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTouchPoint)
+QML_DECLARE_TYPE(QQuickGrabGestureEvent)
+QML_DECLARE_TYPE(QQuickMultiPointTouchArea)
+
+QT_END_HEADER
+
+#endif // QQUICKMULTIPOINTTOUCHAREA_H
diff --git a/src/declarative/items/qquickninepatchnode.cpp b/src/quick/items/qquickninepatchnode.cpp
index 2974725348..2974725348 100644
--- a/src/declarative/items/qquickninepatchnode.cpp
+++ b/src/quick/items/qquickninepatchnode.cpp
diff --git a/src/quick/items/qquickninepatchnode_p.h b/src/quick/items/qquickninepatchnode_p.h
new file mode 100644
index 0000000000..0cb1c87d54
--- /dev/null
+++ b/src/quick/items/qquickninepatchnode_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKNINEPATCHNODE_H
+#define QQUICKNINEPATCHNODE_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgtexturematerial.h>
+#include "qquickborderimage_p.h"
+
+class TextureReference;
+
+class QQuickNinePatchNode : public QSGGeometryNode
+{
+public:
+ QQuickNinePatchNode();
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const;
+
+ void setRect(const QRectF &rect);
+ QRectF rect() const { return m_targetRect; }
+
+ void setInnerRect(const QRectF &rect);
+ QRectF innerRect() const { return m_innerRect; }
+
+ void setFiltering(QSGTexture::Filtering filtering);
+ QSGTexture::Filtering filtering() const;
+
+ void setHorzontalTileMode(QQuickBorderImage::TileMode mode);
+ QQuickBorderImage::TileMode horizontalTileMode() const {
+ return (QQuickBorderImage::TileMode) m_horizontalTileMode;
+ }
+
+ void setVerticalTileMode(QQuickBorderImage::TileMode mode);
+ QQuickBorderImage::TileMode verticalTileMode() const {
+ return (QQuickBorderImage::TileMode) m_verticalTileMode;
+ }
+
+ void setMirror(bool m);
+ bool mirror() const { return m_mirror; }
+
+ void update();
+
+private:
+ void fillRow(QSGGeometry::TexturedPoint2D *&v, float y, float ty, int xChunkCount, float xChunkSize, const QRectF &tsr, const QSize &ts);
+ QRectF m_targetRect;
+ QRectF m_innerRect;
+ QSGOpaqueTextureMaterial m_material;
+ QSGTextureMaterial m_materialO;
+ QSGGeometry m_geometry;
+
+ uint m_horizontalTileMode : 2;
+ uint m_verticalTileMode : 2;
+
+ uint m_dirtyGeometry : 1;
+ uint m_mirror : 1;
+};
+
+#endif // QQUICKNINEPATCHNODE_H
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
new file mode 100644
index 0000000000..23ba777528
--- /dev/null
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -0,0 +1,528 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickpainteditem.h"
+#include <private/qquickpainteditem_p.h>
+
+#include <QtQuick/private/qsgpainternode_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickPaintedItem
+ \brief The QQuickPaintedItem class provides a way to use the QPainter API in the
+ QML Scene Graph.
+
+ \inmodule QtQuick
+
+ The QQuickPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
+ It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
+ onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
+ When the render target is a QImage, QPainter first renders into the image then
+ the content is uploaded to the texture.
+ When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
+ Call update() to trigger a repaint.
+
+ To enable QPainter to do anti-aliased rendering, use setAntialiasing().
+
+ QQuickPaintedItem is meant to make it easier to port old code that is using the
+ QPainter API to the QML Scene Graph API and it should be used only for that purpose.
+
+ To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
+ start by implementing its only pure virtual public function: paint(), which implements
+ the actual painting. To get the size of the area painted by the item, use
+ contentsBoundingRect().
+*/
+
+/*!
+ \enum QQuickPaintedItem::RenderTarget
+
+ This enum describes QQuickPaintedItem's render targets. The render target is the
+ surface QPainter paints onto before the item is rendered on screen.
+
+ \value Image The default; QPainter paints into a QImage using the raster paint engine.
+ The image's content needs to be uploaded to graphics memory afterward, this operation
+ can potentially be slow if the item is large. This render target allows high quality
+ anti-aliasing and fast item resizing.
+
+ \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
+ paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
+ quality is not as good as if using an image. This render target allows faster rendering
+ in some cases, but you should avoid using it if the item is resized often.
+
+ \value InvertedYFramebufferObject Exactly as for FramebufferObject above, except once
+ the painting is done, prior to rendering the painted image is flipped about the
+ x-axis so that the top-most pixels are now at the bottom. Since this is done with the
+ OpenGL texture coordinates it is a much faster way to achieve this effect than using a
+ painter transform.
+
+ \sa setRenderTarget()
+*/
+
+/*!
+ \enum QQuickPaintedItem::PerformanceHint
+
+ This enum describes flags that you can enable to improve rendering
+ performance in QQuickPaintedItem. By default, none of these flags are set.
+
+ \value FastFBOResizing If your item gets resized often and you are using the
+ QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
+ item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
+ is a costly operation, by enabling this property the Framebuffer Object will use a texture
+ larger than the actual size of the item to avoid as much as possible resizing it.
+*/
+
+/*!
+ \internal
+*/
+QQuickPaintedItemPrivate::QQuickPaintedItemPrivate()
+ : QQuickItemPrivate()
+ , contentsScale(1.0)
+ , fillColor(Qt::transparent)
+ , renderTarget(QQuickPaintedItem::Image)
+ , performanceHints(0)
+ , opaquePainting(false)
+ , antialiasing(false)
+ , mipmap(false)
+{
+}
+
+/*!
+ Constructs a QQuickPaintedItem with the given \a parent item.
+ */
+QQuickPaintedItem::QQuickPaintedItem(QQuickItem *parent)
+ : QQuickItem(*(new QQuickPaintedItemPrivate), parent)
+{
+ setFlag(ItemHasContents);
+}
+
+/*!
+ \internal
+*/
+QQuickPaintedItem::QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent)
+ : QQuickItem(dd, parent)
+{
+ setFlag(ItemHasContents);
+}
+
+/*!
+ Destroys the QQuickPaintedItem.
+*/
+QQuickPaintedItem::~QQuickPaintedItem()
+{
+}
+
+/*!
+ Schedules a redraw of the area covered by \a rect in this item. You can call this function
+ whenever your item needs to be redrawn, such as if it changes appearance or size.
+
+ This function does not cause an immediate paint; instead it schedules a paint request that
+ is processed by the QML Scene Graph when the next frame is rendered. The item will only be
+ redrawn if it is visible.
+
+ Note that calling this function will trigger a repaint of the whole scene.
+
+ \sa paint()
+*/
+void QQuickPaintedItem::update(const QRect &rect)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (rect.isNull() && !d->dirtyRect.isNull())
+ d->dirtyRect = contentsBoundingRect().toAlignedRect();
+ else
+ d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
+ QQuickItem::update();
+}
+
+/*!
+ Returns true if this item is opaque; otherwise, false is returned.
+
+ By default, painted items are not opaque.
+
+ \sa setOpaquePainting()
+*/
+bool QQuickPaintedItem::opaquePainting() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->opaquePainting;
+}
+
+/*!
+ If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
+
+ Opaque items are not blended with the rest of the scene, you should set this to true
+ if the content of the item is opaque to speed up rendering.
+
+ By default, painted items are not opaque.
+
+ \sa opaquePainting()
+*/
+void QQuickPaintedItem::setOpaquePainting(bool opaque)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->opaquePainting == opaque)
+ return;
+
+ d->opaquePainting = opaque;
+ QQuickItem::update();
+}
+
+/*!
+ Returns true if antialiased painting is enabled; otherwise, false is returned.
+
+ By default, antialiasing is not enabled.
+
+ \sa setAntialiasing()
+*/
+bool QQuickPaintedItem::antialiasing() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->antialiasing;
+}
+
+/*!
+ If \a enable is true, antialiased painting is enabled.
+
+ By default, antialiasing is not enabled.
+
+ \sa antialiasing()
+*/
+void QQuickPaintedItem::setAntialiasing(bool enable)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->antialiasing == enable)
+ return;
+
+ d->antialiasing = enable;
+ update();
+}
+
+/*!
+ Returns true if mipmaps are enabled; otherwise, false is returned.
+
+ By default, mipmapping is not enabled.
+
+ \sa setMipmap()
+*/
+bool QQuickPaintedItem::mipmap() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->mipmap;
+}
+
+/*!
+ If \a enable is true, mipmapping is enabled on the associated texture.
+
+ Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
+ scaled down.
+
+ By default, mipmapping is not enabled.
+
+ \sa mipmap()
+*/
+void QQuickPaintedItem::setMipmap(bool enable)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->mipmap == enable)
+ return;
+
+ d->mipmap = enable;
+ update();
+}
+
+/*!
+ Returns the performance hints.
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHint(), setPerformanceHints()
+*/
+QQuickPaintedItem::PerformanceHints QQuickPaintedItem::performanceHints() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->performanceHints;
+}
+
+/*!
+ Sets the given performance \a hint on the item if \a enabled is true;
+ otherwise clears the performance hint.
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHints(), performanceHints()
+*/
+void QQuickPaintedItem::setPerformanceHint(QQuickPaintedItem::PerformanceHint hint, bool enabled)
+{
+ Q_D(QQuickPaintedItem);
+ PerformanceHints oldHints = d->performanceHints;
+ if (enabled)
+ d->performanceHints |= hint;
+ else
+ d->performanceHints &= ~hint;
+ if (oldHints != d->performanceHints)
+ update();
+}
+
+/*!
+ Sets the performance hints to \a hints
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHint(), performanceHints()
+*/
+void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints hints)
+{
+ Q_D(QQuickPaintedItem);
+ if (d->performanceHints == hints)
+ return;
+ d->performanceHints = hints;
+ update();
+}
+
+/*!
+ This function returns the outer bounds of the item as a rectangle; all painting must be
+ restricted to inside an item's bounding rect.
+
+ If the contents size has not been set it reflects the size of the item; otherwise
+ it reflects the contents size scaled by the contents scale.
+
+ Use this function to know the area painted by the item.
+
+ \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
+*/
+QRectF QQuickPaintedItem::contentsBoundingRect() const
+{
+ Q_D(const QQuickPaintedItem);
+
+ qreal w = d->width;
+ QSizeF sz = d->contentsSize * d->contentsScale;
+ if (w < sz.width())
+ w = sz.width();
+ qreal h = d->height;
+ if (h < sz.height())
+ h = sz.height();
+
+ return QRectF(0, 0, w, h);
+}
+
+/*!
+ \property QQuickPaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the paint() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+QSize QQuickPaintedItem::contentsSize() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->contentsSize;
+}
+
+void QQuickPaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->contentsSize == size)
+ return;
+
+ d->contentsSize = size;
+ update();
+}
+
+/*!
+ This convenience function is equivalent to calling setContentsSize(QSize()).
+*/
+void QQuickPaintedItem::resetContentsSize()
+{
+ setContentsSize(QSize());
+}
+
+/*!
+ \property QQuickPaintedItem::contentsScale
+ \brief The scale of the contents
+
+ All painting happening in paint() is scaled by the contents scale. This is distinct
+ from the scale of the item in regards to scale().
+
+ The default value is 1.
+*/
+qreal QQuickPaintedItem::contentsScale() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->contentsScale;
+}
+
+void QQuickPaintedItem::setContentsScale(qreal scale)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->contentsScale == scale)
+ return;
+
+ d->contentsScale = scale;
+ update();
+}
+
+/*!
+ \property QQuickPaintedItem::fillColor
+ \brief The item's background fill color.
+
+ By default, the fill color is set to Qt::transparent.
+*/
+QColor QQuickPaintedItem::fillColor() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->fillColor;
+}
+
+void QQuickPaintedItem::setFillColor(const QColor &c)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->fillColor == c)
+ return;
+
+ d->fillColor = c;
+ update();
+
+ emit fillColorChanged();
+}
+
+/*!
+ \property QQuickPaintedItem::renderTarget
+ \brief The item's render target.
+
+ This property defines which render target the QPainter renders into, it can be either
+ QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject.
+
+ Each has certain benefits, typically performance versus quality. Using a framebuffer
+ object avoids a costly upload of the image contents to the texture in graphics memory,
+ while using an image enables high quality anti-aliasing.
+
+ \warning Resizing a framebuffer object is a costly operation, avoid using
+ the QQuickPaintedItem::FramebufferObject render target if the item gets resized often.
+
+ By default, the render target is QQuickPaintedItem::Image.
+*/
+QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->renderTarget;
+}
+
+void QQuickPaintedItem::setRenderTarget(RenderTarget target)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->renderTarget == target)
+ return;
+
+ d->renderTarget = target;
+ update();
+
+ emit renderTargetChanged();
+}
+
+/*!
+ \fn virtual void QQuickPaintedItem::paint(QPainter *painter) = 0
+
+ This function, which is usually called by the QML Scene Graph, paints the
+ contents of an item in local coordinates.
+
+ The function is called after the item has been filled with the fillColor.
+
+ Reimplement this function in a QQuickPaintedItem subclass to provide the
+ item's painting implementation, using \a painter.
+
+ \note The QML Scene Graph uses two separate threads, the main thread does things such as
+ processing events or updating animations while a second thread does the actual OpenGL rendering.
+ As a consequence, paint() is not called from the main GUI thread but from the GL enabled
+ renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
+ therefore thread-safe.
+*/
+
+/*!
+ This function is called when the Scene Graph node associated to the item needs to
+ be updated.
+*/
+QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ Q_D(QQuickPaintedItem);
+
+ if (width() <= 0 || height() <= 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
+ if (!node)
+ node = new QSGPainterNode(this);
+
+ QRectF br = contentsBoundingRect();
+
+ node->setPreferredRenderTarget(d->renderTarget);
+ node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
+ node->setSize(QSize(qRound(br.width()), qRound(br.height())));
+ node->setSmoothPainting(d->antialiasing);
+ node->setLinearFiltering(d->smooth);
+ node->setMipmapping(d->mipmap);
+ node->setOpaquePainting(d->opaquePainting);
+ node->setFillColor(d->fillColor);
+ node->setContentsScale(d->contentsScale);
+ node->setDirty(d->dirtyRect);
+ node->update();
+
+ d->dirtyRect = QRect();
+
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
new file mode 100644
index 0000000000..939ad6303b
--- /dev/null
+++ b/src/quick/items/qquickpainteditem.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKPAINTEDITEM_P_H
+#define QQUICKPAINTEDITEM_P_H
+
+#include <QtQuick/qquickitem.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPaintedItemPrivate;
+class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_ENUMS(RenderTarget)
+
+ Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
+ Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
+ Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
+public:
+ QQuickPaintedItem(QQuickItem *parent = 0);
+ virtual ~QQuickPaintedItem();
+
+ enum RenderTarget {
+ Image,
+ FramebufferObject,
+ InvertedYFramebufferObject
+ };
+
+ enum PerformanceHint {
+ FastFBOResizing = 0x1
+ };
+ Q_DECLARE_FLAGS(PerformanceHints, PerformanceHint)
+
+ void update(const QRect &rect = QRect());
+
+ bool opaquePainting() const;
+ void setOpaquePainting(bool opaque);
+
+ bool antialiasing() const;
+ void setAntialiasing(bool enable);
+
+ bool mipmap() const;
+ void setMipmap(bool enable);
+
+ PerformanceHints performanceHints() const;
+ void setPerformanceHint(PerformanceHint hint, bool enabled = true);
+ void setPerformanceHints(PerformanceHints hints);
+
+ QRectF contentsBoundingRect() const;
+
+ QSize contentsSize() const;
+ void setContentsSize(const QSize &);
+ void resetContentsSize();
+
+ qreal contentsScale() const;
+ void setContentsScale(qreal);
+
+ QColor fillColor() const;
+ void setFillColor(const QColor&);
+
+ RenderTarget renderTarget() const;
+ void setRenderTarget(RenderTarget target);
+
+ virtual void paint(QPainter *painter) = 0;
+
+Q_SIGNALS:
+ void fillColorChanged();
+ void contentsSizeChanged();
+ void contentsScaleChanged();
+ void renderTargetChanged();
+
+protected:
+ QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+private:
+ Q_DISABLE_COPY(QQuickPaintedItem)
+ Q_DECLARE_PRIVATE(QQuickPaintedItem)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPaintedItem::PerformanceHints)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKPAINTEDITEM_P_H
diff --git a/src/declarative/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index b847b0a4ef..b847b0a4ef 100644
--- a/src/declarative/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
new file mode 100644
index 0000000000..0428dbe9cd
--- /dev/null
+++ b/src/quick/items/qquickpathview.cpp
@@ -0,0 +1,1781 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickpathview_p.h"
+#include "qquickpathview_p_p.h"
+#include "qquickcanvas.h"
+
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qdeclarativeopenmetaobject_p.h>
+#include <private/qlistmodelinterface_p.h>
+#include <private/qdeclarativechangeset_p.h>
+
+#include <QtGui/qevent.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qstylehints.h>
+#include <QtCore/qmath.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+inline qreal qmlMod(qreal x, qreal y)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return fmodf(float(x), float(y));
+ else
+#endif
+ return fmod(x, y);
+}
+
+static QDeclarativeOpenMetaObjectType *qPathViewAttachedType = 0;
+
+QQuickPathViewAttached::QQuickPathViewAttached(QObject *parent)
+: QObject(parent), m_percent(-1), m_view(0), m_onPath(false), m_isCurrent(false)
+{
+ if (qPathViewAttachedType) {
+ m_metaobject = new QDeclarativeOpenMetaObject(this, qPathViewAttachedType);
+ m_metaobject->setCached(true);
+ } else {
+ m_metaobject = new QDeclarativeOpenMetaObject(this);
+ }
+}
+
+QQuickPathViewAttached::~QQuickPathViewAttached()
+{
+}
+
+QVariant QQuickPathViewAttached::value(const QByteArray &name) const
+{
+ return m_metaobject->value(name);
+}
+void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &val)
+{
+ m_metaobject->setValue(name, val);
+}
+
+
+void QQuickPathViewPrivate::init()
+{
+ Q_Q(QQuickPathView);
+ offset = 0;
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QQuickItem::ItemIsFocusScope);
+ q->setFiltersChildMouseEvents(true);
+ FAST_CONNECT(&tl, SIGNAL(updated()), q, SLOT(ticked()))
+ lastPosTime.invalidate();
+ FAST_CONNECT(&tl, SIGNAL(completed()), q, SLOT(movementEnding()))
+}
+
+QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool onPath)
+{
+ Q_Q(QQuickPathView);
+ requestedIndex = modelIndex;
+ requestedOnPath = onPath;
+ requestedZ = z;
+ inRequest = true;
+ QQuickItem *item = model->item(modelIndex, false);
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
+ requestedIndex = -1;
+ qPathViewAttachedType = attType;
+ QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
+ qPathViewAttachedType = 0;
+ if (att)
+ att->setOnPath(onPath);
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ inRequest = false;
+ return item;
+}
+
+void QQuickPathView::createdItem(int index, QQuickItem *item)
+{
+ Q_D(QQuickPathView);
+ if (d->requestedIndex != index) {
+ qPathViewAttachedType = d->attachedType();
+ QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
+ qPathViewAttachedType = 0;
+ if (att) {
+ att->m_view = this;
+ att->setOnPath(false);
+ }
+ item->setParentItem(this);
+ QDeclarative_setParent_noEvent(item, this);
+ d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
+ } else {
+ d->requestedIndex = -1;
+ if (!d->inRequest)
+ refill();
+ }
+}
+
+void QQuickPathView::initItem(int index, QQuickItem *item)
+{
+ Q_D(QQuickPathView);
+ if (d->requestedIndex == index) {
+ item->setParentItem(this);
+ qPathViewAttachedType = d->attachedType();
+ QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item));
+ qPathViewAttachedType = 0;
+ if (att) {
+ att->m_view = this;
+ qreal percent = d->positionOfIndex(index);
+ foreach (const QString &attr, d->path->attributes())
+ att->setValue(attr.toUtf8(), d->path->attributeAt(attr, percent));
+ item->setZ(d->requestedZ);
+ if (att)
+ att->setOnPath(d->requestedOnPath);
+ }
+ }
+}
+
+void QQuickPathViewPrivate::releaseItem(QQuickItem *item)
+{
+ if (!item || !model)
+ return;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ if (model->release(item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ if (QQuickPathViewAttached *att = attached(item))
+ att->setOnPath(false);
+ }
+}
+
+QQuickPathViewAttached *QQuickPathViewPrivate::attached(QQuickItem *item)
+{
+ return static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item, false));
+}
+
+QDeclarativeOpenMetaObjectType *QQuickPathViewPrivate::attachedType()
+{
+ Q_Q(QQuickPathView);
+ if (!attType) {
+ // pre-create one metatype to share with all attached objects
+ attType = new QDeclarativeOpenMetaObjectType(&QQuickPathViewAttached::staticMetaObject, qmlEngine(q));
+ foreach (const QString &attr, path->attributes())
+ attType->createProperty(attr.toUtf8());
+ }
+
+ return attType;
+}
+
+void QQuickPathViewPrivate::clear()
+{
+ if (currentItem) {
+ releaseItem(currentItem);
+ currentItem = 0;
+ }
+ for (int i=0; i<items.count(); i++){
+ QQuickItem *p = items[i];
+ releaseItem(p);
+ }
+ items.clear();
+}
+
+void QQuickPathViewPrivate::updateMappedRange()
+{
+ if (model && pathItems != -1 && pathItems < modelCount)
+ mappedRange = qreal(pathItems)/modelCount;
+ else
+ mappedRange = 1.0;
+}
+
+qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
+{
+ qreal pos = -1.0;
+
+ if (model && index >= 0 && index < modelCount) {
+ qreal start = 0.0;
+ if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange)
+ start = highlightRangeStart;
+ qreal globalPos = index + offset;
+ globalPos = qmlMod(globalPos, qreal(modelCount)) / modelCount;
+ if (pathItems != -1 && pathItems < modelCount) {
+ globalPos += start * mappedRange;
+ globalPos = qmlMod(globalPos, 1.0);
+ if (globalPos < mappedRange)
+ pos = globalPos / mappedRange;
+ } else {
+ pos = qmlMod(globalPos + start, 1.0);
+ }
+ }
+
+ return pos;
+}
+
+void QQuickPathViewPrivate::createHighlight()
+{
+ Q_Q(QQuickPathView);
+ if (!q->isComponentComplete())
+ return;
+
+ bool changed = false;
+ if (highlightItem) {
+ highlightItem->setParentItem(0);
+ highlightItem->deleteLater();
+ highlightItem = 0;
+ changed = true;
+ }
+
+ QQuickItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *creationContext = highlightComponent->creationContext();
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(
+ creationContext ? creationContext : qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QQuickItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QQuickItem;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
+ highlightItem = item;
+ changed = true;
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QQuickPathViewPrivate::updateHighlight()
+{
+ Q_Q(QQuickPathView);
+ if (!q->isComponentComplete() || !isValid())
+ return;
+ if (highlightItem) {
+ if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ updateItem(highlightItem, highlightRangeStart);
+ } else {
+ qreal target = currentIndex;
+
+ offsetAdj = 0.0;
+ tl.reset(moveHighlight);
+ moveHighlight.setValue(highlightPosition);
+
+ const int duration = highlightMoveDuration;
+
+ if (target - highlightPosition > modelCount/2) {
+ highlightUp = false;
+ qreal distance = modelCount - target + highlightPosition;
+ tl.move(moveHighlight, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
+ tl.set(moveHighlight, modelCount-0.01);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * (modelCount-target) / distance));
+ } else if (target - highlightPosition <= -modelCount/2) {
+ highlightUp = true;
+ qreal distance = modelCount - highlightPosition + target;
+ tl.move(moveHighlight, modelCount-0.01, QEasingCurve(QEasingCurve::InQuad), int(duration * (modelCount-highlightPosition) / distance));
+ tl.set(moveHighlight, 0.0);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * target / distance));
+ } else {
+ highlightUp = highlightPosition - target < 0;
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ }
+ }
+}
+
+void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
+{
+ if (pos != highlightPosition) {
+ qreal start = 0.0;
+ qreal end = 1.0;
+ if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange) {
+ start = highlightRangeStart;
+ end = highlightRangeEnd;
+ }
+
+ qreal range = qreal(modelCount);
+ // calc normalized position of highlight relative to offset
+ qreal relativeHighlight = qmlMod(pos + offset, range) / range;
+
+ if (!highlightUp && relativeHighlight > end * mappedRange) {
+ qreal diff = 1.0 - relativeHighlight;
+ setOffset(offset + diff * range);
+ } else if (highlightUp && relativeHighlight >= (end - start) * mappedRange) {
+ qreal diff = relativeHighlight - (end - start) * mappedRange;
+ setOffset(offset - diff * range - 0.00001);
+ }
+
+ highlightPosition = pos;
+ qreal pathPos = positionOfIndex(pos);
+ updateItem(highlightItem, pathPos);
+ if (QQuickPathViewAttached *att = attached(highlightItem))
+ att->setOnPath(pathPos != -1.0);
+ }
+}
+
+void QQuickPathView::pathUpdated()
+{
+ Q_D(QQuickPathView);
+ QList<QQuickItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ QQuickItem *item = *it;
+ if (QQuickPathViewAttached *att = d->attached(item))
+ att->m_percent = -1;
+ ++it;
+ }
+ refill();
+}
+
+void QQuickPathViewPrivate::updateItem(QQuickItem *item, qreal percent)
+{
+ if (QQuickPathViewAttached *att = attached(item)) {
+ if (qFuzzyCompare(att->m_percent, percent))
+ return;
+ att->m_percent = percent;
+ foreach (const QString &attr, path->attributes())
+ att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(qRound(pf.x() - item->width()/2));
+ item->setY(qRound(pf.y() - item->height()/2));
+}
+
+void QQuickPathViewPrivate::regenerate()
+{
+ Q_Q(QQuickPathView);
+ if (!q->isComponentComplete())
+ return;
+
+ clear();
+
+ if (!isValid())
+ return;
+
+ firstIndex = -1;
+ updateMappedRange();
+ q->refill();
+}
+
+/*!
+ \qmlclass PathView QQuickPathView
+ \inqmlmodule QtQuick 2
+ \ingroup qml-view-elements
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ A PathView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ The view has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed.
+ The \l delegate is instantiated for each item on the \l path.
+ The items may be flicked to move them along the path.
+
+ For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
+
+ \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
+
+ This data can be represented as a PathView, like this:
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ (Note the above example uses PathAttribute to scale and modify the
+ opacity of the items as they rotate. This additional code can be seen in the
+ PathAttribute documentation.)
+
+ PathView does not automatically handle keyboard navigation. This is because
+ the keys to use for navigation will depend upon the shape of the path. Navigation
+ can be added quite simply by setting \c focus to \c true and calling
+ \l decrementCurrentIndex() or \l incrementCurrentIndex(), for example to navigate
+ using the left and right arrow keys:
+
+ \qml
+ PathView {
+ // ...
+ focus: true
+ Keys.onLeftPressed: decrementCurrentIndex()
+ Keys.onRightPressed: incrementCurrentIndex()
+ }
+ \endqml
+
+ The path view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ PathView attaches a number of properties to the root item of the delegate, for example
+ \c {PathView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c PathView.isCurrentItem, while the child
+ \c nameText object must refer to this property as \c wrapper.PathView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+
+ \bold Note that views do not enable \e clip automatically. If the view
+ is not clipped by another item or the screen, it will be necessary
+ to set \e {clip: true} in order to have the out of view items clipped
+ nicely.
+
+ \sa Path, {declarative/modelviews/pathview}{PathView example}
+*/
+
+QQuickPathView::QQuickPathView(QQuickItem *parent)
+ : QQuickItem(*(new QQuickPathViewPrivate), parent)
+{
+ Q_D(QQuickPathView);
+ d->init();
+}
+
+QQuickPathView::~QQuickPathView()
+{
+ Q_D(QQuickPathView);
+ d->clear();
+ if (d->attType)
+ d->attType->release();
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlattachedproperty PathView QtQuick2::PathView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::PathView::onPath
+ This attached property holds whether the item is currently on the path.
+
+ If a pathItemCount has been set, it is possible that some items may
+ be instantiated, but not considered to be currently on the path.
+ Usually, these items would be set invisible, for example:
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuick2::PathView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+
+/*!
+ \qmlproperty model QtQuick2::PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in QML, using the ListModel element.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QQuickPathView::model() const
+{
+ Q_D(const QQuickPathView);
+ return d->modelVariant;
+}
+
+void QQuickPathView::setModel(const QVariant &model)
+{
+ Q_D(QQuickPathView);
+ if (d->modelVariant == model)
+ return;
+
+ if (d->model) {
+ disconnect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
+ this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
+ disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
+ disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
+ for (int i=0; i<d->items.count(); i++){
+ QQuickItem *p = d->items[i];
+ d->releaseItem(p);
+ }
+ d->items.clear();
+ }
+
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QQuickVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ if (isComponentComplete())
+ static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+ }
+ if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ d->modelCount = 0;
+ if (d->model) {
+ connect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
+ this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
+ connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
+ connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
+ d->modelCount = d->model->count();
+ if (d->model->count())
+ d->offset = qmlMod(d->offset, qreal(d->model->count()));
+ if (d->offset < 0)
+ d->offset = d->model->count() + d->offset;
+}
+ d->regenerate();
+ if (d->currentIndex < d->modelCount)
+ setOffset(qmlMod(d->modelCount - d->currentIndex, d->modelCount));
+ else
+ d->fixOffset();
+ emit countChanged();
+ emit modelChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::PathView::count
+ This property holds the number of items in the model.
+*/
+int QQuickPathView::count() const
+{
+ Q_D(const QQuickPathView);
+ return d->model ? d->modelCount : 0;
+}
+
+/*!
+ \qmlproperty Path QtQuick2::PathView::path
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
+QDeclarativePath *QQuickPathView::path() const
+{
+ Q_D(const QQuickPathView);
+ return d->path;
+}
+
+void QQuickPathView::setPath(QDeclarativePath *path)
+{
+ Q_D(QQuickPathView);
+ if (d->path == path)
+ return;
+ if (d->path)
+ disconnect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ d->path = path;
+ connect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ if (d->isValid() && isComponentComplete()) {
+ d->clear();
+ if (d->attType) {
+ d->attType->release();
+ d->attType = 0;
+ }
+ d->regenerate();
+ }
+ emit pathChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::PathView::currentIndex
+ This property holds the index of the current item.
+*/
+int QQuickPathView::currentIndex() const
+{
+ Q_D(const QQuickPathView);
+ return d->currentIndex;
+}
+
+void QQuickPathView::setCurrentIndex(int idx)
+{
+ Q_D(QQuickPathView);
+ if (d->model && d->modelCount)
+ idx = qAbs(idx % d->modelCount);
+ if (d->model && (idx != d->currentIndex || !d->currentItem)) {
+ if (d->currentItem) {
+ if (QQuickPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(false);
+ d->releaseItem(d->currentItem);
+ }
+ int oldCurrentIdx = d->currentIndex;
+ QQuickItem *oldCurrentItem = d->currentItem;
+ d->currentItem = 0;
+ d->moveReason = QQuickPathViewPrivate::SetIndex;
+ d->currentIndex = idx;
+ if (d->modelCount) {
+ d->createCurrentItem();
+ if (d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
+ d->snapToCurrent();
+ d->currentItemOffset = d->positionOfIndex(d->currentIndex);
+ d->updateHighlight();
+ }
+ if (oldCurrentIdx != d->currentIndex)
+ emit currentIndexChanged();
+ if (oldCurrentItem != d->currentItem)
+ emit currentItemChanged();
+ }
+}
+
+QQuickItem *QQuickPathView::currentItem() const
+{
+ Q_D(const QQuickPathView);
+ return d->currentItem;
+}
+
+/*!
+ \qmlmethod QtQuick2::PathView::incrementCurrentIndex()
+
+ Increments the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QQuickPathView::incrementCurrentIndex()
+{
+ Q_D(QQuickPathView);
+ d->moveDirection = QQuickPathViewPrivate::Positive;
+ setCurrentIndex(currentIndex()+1);
+}
+
+/*!
+ \qmlmethod QtQuick2::PathView::decrementCurrentIndex()
+
+ Decrements the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QQuickPathView::decrementCurrentIndex()
+{
+ Q_D(QQuickPathView);
+ if (d->model && d->modelCount) {
+ int idx = currentIndex()-1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ d->moveDirection = QQuickPathViewPrivate::Negative;
+ setCurrentIndex(idx);
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick2::PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+ This is a real number that ranges from 0.0 to the count of items in the model.
+*/
+qreal QQuickPathView::offset() const
+{
+ Q_D(const QQuickPathView);
+ return d->offset;
+}
+
+void QQuickPathView::setOffset(qreal offset)
+{
+ Q_D(QQuickPathView);
+ d->setOffset(offset);
+ d->updateCurrent();
+}
+
+void QQuickPathViewPrivate::setOffset(qreal o)
+{
+ Q_Q(QQuickPathView);
+ if (offset != o) {
+ if (isValid() && q->isComponentComplete()) {
+ offset = qmlMod(o, qreal(modelCount));
+ if (offset < 0)
+ offset += qreal(modelCount);
+ q->refill();
+ } else {
+ offset = o;
+ }
+ emit q->offsetChanged();
+ }
+}
+
+void QQuickPathViewPrivate::setAdjustedOffset(qreal o)
+{
+ setOffset(o+offsetAdj);
+}
+
+/*!
+ \qmlproperty Component QtQuick2::PathView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item.
+
+ The below example demonstrates how to make a simple highlight. Note the use
+ of the \l{PathView::onPath}{PathView.onPath} attached property to ensure that
+ the highlight is hidden when flicked away from the path.
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ \sa highlightItem, highlightRangeMode
+*/
+
+QDeclarativeComponent *QQuickPathView::highlight() const
+{
+ Q_D(const QQuickPathView);
+ return d->highlightComponent;
+}
+
+void QQuickPathView::setHighlight(QDeclarativeComponent *highlight)
+{
+ Q_D(QQuickPathView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->createHighlight();
+ d->updateHighlight();
+ emit highlightChanged();
+ }
+}
+
+/*!
+ \qmlproperty Item QtQuick2::PathView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ \sa highlight
+*/
+QQuickItem *QQuickPathView::highlightItem()
+{
+ Q_D(const QQuickPathView);
+ return d->highlightItem;
+}
+/*!
+ \qmlproperty real QtQuick2::PathView::preferredHighlightBegin
+ \qmlproperty real QtQuick2::PathView::preferredHighlightEnd
+ \qmlproperty enumeration QtQuick2::PathView::highlightRangeMode
+
+ These properties set the preferred range of the highlight (current item)
+ within the view. The preferred values must be in the range 0.0-1.0.
+
+ If highlightRangeMode is set to \e PathView.NoHighlightRange
+
+ If highlightRangeMode is set to \e PathView.ApplyRange the view will
+ attempt to maintain the highlight within the range, however
+ the highlight can move outside of the range at the ends of the path
+ or due to a mouse interaction.
+
+ If highlightRangeMode is set to \e PathView.StrictlyEnforceRange the highlight will never
+ move outside of the range. This means that the current item will change
+ if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+
+ Note that this is the correct way to influence where the
+ current item ends up when the view moves. For example, if you want the
+ currently selected item to be in the middle of the path, then set the
+ highlight range to be 0.5,0.5 and highlightRangeMode to PathView.StrictlyEnforceRange.
+ Then, when the path scrolls,
+ the currently selected item will be the item at that position. This also applies to
+ when the currently selected item changes - it will scroll to within the preferred
+ highlight range. Furthermore, the behaviour of the current item index will occur
+ whether or not a highlight exists.
+
+ The default value is \e PathView.StrictlyEnforceRange.
+
+ Note that a valid range requires preferredHighlightEnd to be greater
+ than or equal to preferredHighlightBegin.
+*/
+qreal QQuickPathView::preferredHighlightBegin() const
+{
+ Q_D(const QQuickPathView);
+ return d->highlightRangeStart;
+}
+
+void QQuickPathView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QQuickPathView);
+ if (d->highlightRangeStart == start || start < 0 || start > 1.0)
+ return;
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ refill();
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QQuickPathView::preferredHighlightEnd() const
+{
+ Q_D(const QQuickPathView);
+ return d->highlightRangeEnd;
+}
+
+void QQuickPathView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QQuickPathView);
+ if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ refill();
+ emit preferredHighlightEndChanged();
+}
+
+QQuickPathView::HighlightRangeMode QQuickPathView::highlightRangeMode() const
+{
+ Q_D(const QQuickPathView);
+ return d->highlightRangeMode;
+}
+
+void QQuickPathView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QQuickPathView);
+ if (d->highlightRangeMode == mode)
+ return;
+ d->highlightRangeMode = mode;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ if (d->haveHighlightRange) {
+ d->regenerate();
+ d->snapToCurrent();
+ }
+ emit highlightRangeModeChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::PathView::highlightMoveDuration
+ This property holds the move animation duration of the highlight delegate.
+
+ If the highlightRangeMode is StrictlyEnforceRange then this property
+ determines the speed that the items move along the path.
+
+ The default value for the duration is 300ms.
+*/
+int QQuickPathView::highlightMoveDuration() const
+{
+ Q_D(const QQuickPathView);
+ return d->highlightMoveDuration;
+}
+
+void QQuickPathView::setHighlightMoveDuration(int duration)
+{
+ Q_D(QQuickPathView);
+ if (d->highlightMoveDuration == duration)
+ return;
+ d->highlightMoveDuration = duration;
+ emit highlightMoveDurationChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
+qreal QQuickPathView::dragMargin() const
+{
+ Q_D(const QQuickPathView);
+ return d->dragMargin;
+}
+
+void QQuickPathView::setDragMargin(qreal dragMargin)
+{
+ Q_D(QQuickPathView);
+ if (d->dragMargin == dragMargin)
+ return;
+ d->dragMargin = dragMargin;
+ emit dragMarginChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::PathView::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default is 100.
+*/
+qreal QQuickPathView::flickDeceleration() const
+{
+ Q_D(const QQuickPathView);
+ return d->deceleration;
+}
+
+void QQuickPathView::setFlickDeceleration(qreal dec)
+{
+ Q_D(QQuickPathView);
+ if (d->deceleration == dec)
+ return;
+ d->deceleration = dec;
+ emit flickDecelerationChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::PathView::interactive
+
+ A user cannot drag or flick a PathView that is not interactive.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with PathView's children.
+*/
+bool QQuickPathView::isInteractive() const
+{
+ Q_D(const QQuickPathView);
+ return d->interactive;
+}
+
+void QQuickPathView::setInteractive(bool interactive)
+{
+ Q_D(QQuickPathView);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive)
+ d->tl.clear();
+ emit interactiveChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::PathView::moving
+
+ This property holds whether the view is currently moving
+ due to the user either dragging or flicking the view.
+*/
+bool QQuickPathView::isMoving() const
+{
+ Q_D(const QQuickPathView);
+ return d->moving;
+}
+
+/*!
+ \qmlproperty bool QtQuick2::PathView::flicking
+
+ This property holds whether the view is currently moving
+ due to the user flicking the view.
+*/
+bool QQuickPathView::isFlicking() const
+{
+ Q_D(const QQuickPathView);
+ return d->flicking;
+}
+
+/*!
+ \qmlsignal QtQuick2::PathView::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal QtQuick2::PathView::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty Component QtQuick2::PathView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view when pathItemCount is specified. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ Note that the PathView will layout the items based on the size of the root
+ item in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+QDeclarativeComponent *QQuickPathView::delegate() const
+{
+ Q_D(const QQuickPathView);
+ if (d->model) {
+ if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QQuickPathView::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QQuickPathView);
+ if (delegate == this->delegate())
+ return;
+ if (!d->ownModel) {
+ d->model = new QQuickVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
+ int oldCount = dataModel->count();
+ dataModel->setDelegate(delegate);
+ d->modelCount = dataModel->count();
+ d->regenerate();
+ if (oldCount != dataModel->count())
+ emit countChanged();
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time.
+*/
+int QQuickPathView::pathItemCount() const
+{
+ Q_D(const QQuickPathView);
+ return d->pathItems;
+}
+
+void QQuickPathView::setPathItemCount(int i)
+{
+ Q_D(QQuickPathView);
+ if (i == d->pathItems)
+ return;
+ if (i < 1)
+ i = 1;
+ d->pathItems = i;
+ d->updateMappedRange();
+ if (d->isValid() && isComponentComplete()) {
+ d->regenerate();
+ }
+ emit pathItemCountChanged();
+}
+
+QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
+{
+ //XXX maybe do recursively at increasing resolution.
+ qreal mindist = 1e10; // big number
+ QPointF nearPoint = path->pointAt(0);
+ qreal nearPc = 0;
+ for (qreal i=1; i < 1000; i++) {
+ QPointF pt = path->pointAt(i/1000.0);
+ QPointF diff = pt - point;
+ qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
+ if (dist < mindist) {
+ nearPoint = pt;
+ nearPc = i;
+ mindist = dist;
+ }
+ }
+
+ if (nearPercent)
+ *nearPercent = nearPc / 1000.0;
+
+ return nearPoint;
+}
+
+void QQuickPathView::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPathView);
+ if (d->interactive) {
+ d->handleMousePressEvent(event);
+ event->accept();
+ } else {
+ QQuickItem::mousePressEvent(event);
+ }
+}
+
+void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
+{
+ Q_Q(QQuickPathView);
+ if (!interactive || !items.count())
+ return;
+ QPointF scenePoint = q->mapToScene(event->localPos());
+ int idx = 0;
+ for (; idx < items.count(); ++idx) {
+ QRectF rect = items.at(idx)->boundingRect();
+ rect = items.at(idx)->mapRectToScene(rect);
+ if (rect.contains(scenePoint))
+ break;
+ }
+ if (idx == items.count() && dragMargin == 0.) // didn't click on an item
+ return;
+
+ startPoint = pointNear(event->localPos(), &startPc);
+ if (idx == items.count()) {
+ qreal distance = qAbs(event->localPos().x() - startPoint.x()) + qAbs(event->localPos().y() - startPoint.y());
+ if (distance > dragMargin)
+ return;
+ }
+
+ if (tl.isActive() && flicking)
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+
+ lastElapsed = 0;
+ lastDist = 0;
+ QQuickItemPrivate::start(lastPosTime);
+ tl.clear();
+}
+
+void QQuickPathView::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPathView);
+ if (d->interactive) {
+ d->handleMouseMoveEvent(event);
+ if (d->stealMouse)
+ setKeepMouseGrab(true);
+ event->accept();
+ } else {
+ QQuickItem::mouseMoveEvent(event);
+ }
+}
+
+void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
+{
+ Q_Q(QQuickPathView);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+
+ qreal newPc;
+ QPointF pathPoint = pointNear(event->localPos(), &newPc);
+ if (!stealMouse) {
+ QPointF delta = pathPoint - startPoint;
+ if (qAbs(delta.x()) > qApp->styleHints()->startDragDistance() || qAbs(delta.y()) > qApp->styleHints()->startDragDistance()) {
+ stealMouse = true;
+ startPc = newPc;
+ }
+ }
+
+ if (stealMouse) {
+ moveReason = QQuickPathViewPrivate::Mouse;
+ qreal diff = (newPc - startPc)*modelCount*mappedRange;
+ if (diff) {
+ q->setOffset(offset + diff);
+
+ if (diff > modelCount/2)
+ diff -= modelCount;
+ else if (diff < -modelCount/2)
+ diff += modelCount;
+
+ lastElapsed = QQuickItemPrivate::restart(lastPosTime);
+ lastDist = diff;
+ startPc = newPc;
+ }
+ if (!moving) {
+ moving = true;
+ emit q->movingChanged();
+ emit q->movementStarted();
+ }
+ }
+}
+
+void QQuickPathView::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPathView);
+ if (d->interactive) {
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+ ungrabMouse();
+ } else {
+ QQuickItem::mouseReleaseEvent(event);
+ }
+}
+
+void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
+{
+ Q_Q(QQuickPathView);
+ stealMouse = false;
+ q->setKeepMouseGrab(false);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+
+ qreal elapsed = qreal(lastElapsed + QQuickItemPrivate::elapsed(lastPosTime)) / 1000.;
+ qreal velocity = elapsed > 0. ? lastDist / elapsed : 0;
+ if (model && modelCount && qAbs(velocity) > 1.) {
+ qreal count = pathItems == -1 ? modelCount : pathItems;
+ if (qAbs(velocity) > count * 2) // limit velocity
+ velocity = (velocity > 0 ? count : -count) * 2;
+ // Calculate the distance to be travelled
+ qreal v2 = velocity*velocity;
+ qreal accel = deceleration/10;
+ // + 0.25 to encourage moving at least one item in the flick direction
+ qreal dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
+ if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ // round to nearest item.
+ if (velocity > 0.)
+ dist = qRound(dist + offset) - offset;
+ else
+ dist = qRound(dist - offset) + offset;
+ // Calculate accel required to stop on item boundary
+ if (dist <= 0.) {
+ dist = 0.;
+ accel = 0.;
+ } else {
+ accel = v2 / (2.0f * qAbs(dist));
+ }
+ }
+ offsetAdj = 0.0;
+ moveOffset.setValue(offset);
+ tl.accel(moveOffset, velocity, accel, dist);
+ tl.callback(QDeclarativeTimeLineCallback(&moveOffset, fixOffsetCallback, this));
+ if (!flicking) {
+ flicking = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ fixOffset();
+ }
+
+ lastPosTime.invalidate();
+ if (!tl.isActive())
+ q->movementEnding();
+}
+
+bool QQuickPathView::sendMouseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPathView);
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
+ QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ mouseEvent.setAccepted(false);
+
+ switch (mouseEvent.type()) {
+ case QEvent::MouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::MouseButtonPress:
+ d->handleMousePressEvent(&mouseEvent);
+ stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
+ break;
+ case QEvent::MouseButtonRelease:
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = c->mouseGrabberItem();
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return d->stealMouse;
+ } else if (d->lastPosTime.isValid()) {
+ d->lastPosTime.invalidate();
+ d->fixOffset();
+ }
+ if (event->type() == QEvent::MouseButtonRelease)
+ d->stealMouse = false;
+ return false;
+}
+
+bool QQuickPathView::childMouseEventFilter(QQuickItem *i, QEvent *e)
+{
+ Q_D(QQuickPathView);
+ if (!isVisible() || !d->interactive)
+ return QQuickItem::childMouseEventFilter(i, e);
+
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ return sendMouseEvent(static_cast<QMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QQuickItem::childMouseEventFilter(i, e);
+}
+
+void QQuickPathView::mouseUngrabEvent()
+{
+ Q_D(QQuickPathView);
+ if (d->stealMouse) {
+ // if our mouse grab has been removed (probably by a Flickable),
+ // fix our state
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ d->lastPosTime.invalidate();
+ }
+}
+
+void QQuickPathView::updatePolish()
+{
+ QQuickItem::updatePolish();
+ refill();
+}
+
+void QQuickPathView::componentComplete()
+{
+ Q_D(QQuickPathView);
+ if (d->model && d->ownModel)
+ static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
+
+ QQuickItem::componentComplete();
+
+ d->createHighlight();
+ // It is possible that a refill has already happended to to Path
+ // bindings being handled in the componentComplete(). If so
+ // don't do it again.
+ if (d->items.count() == 0 && d->model) {
+ d->modelCount = d->model->count();
+ d->regenerate();
+ }
+ d->updateHighlight();
+
+ if (d->modelCount)
+ emit countChanged();
+}
+
+void QQuickPathView::refill()
+{
+ Q_D(QQuickPathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+
+ d->layoutScheduled = false;
+ bool currentVisible = false;
+
+ // first move existing items and remove items off path
+ int idx = d->firstIndex;
+ QList<QQuickItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ qreal pos = d->positionOfIndex(idx);
+ QQuickItem *item = *it;
+ if (pos >= 0.0) {
+ d->updateItem(item, pos);
+ if (idx == d->currentIndex) {
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ }
+ ++it;
+ } else {
+ // qDebug() << "release";
+ d->updateItem(item, 1.0);
+ d->releaseItem(item);
+ if (it == d->items.begin()) {
+ if (++d->firstIndex >= d->modelCount)
+ d->firstIndex = 0;
+ }
+ it = d->items.erase(it);
+ }
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ }
+ if (!d->items.count())
+ d->firstIndex = -1;
+
+ bool waiting = false;
+ if (d->modelCount) {
+ // add items to beginning and end
+ int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount);
+ if (d->items.count() < count) {
+ int idx = qRound(d->modelCount - d->offset) % d->modelCount;
+ qreal startPos = 0.0;
+ if (d->haveHighlightRange && d->highlightRangeMode != QQuickPathView::NoHighlightRange)
+ startPos = d->highlightRangeStart;
+ if (d->firstIndex >= 0) {
+ startPos = d->positionOfIndex(d->firstIndex);
+ idx = (d->firstIndex + d->items.count()) % d->modelCount;
+ }
+ qreal pos = d->positionOfIndex(idx);
+ while ((pos > startPos || !d->items.count()) && d->items.count() < count) {
+// qDebug() << "append" << idx;
+ QQuickItem *item = d->getItem(idx, idx+1);
+ if (!item) {
+ waiting = true;
+ break;
+ }
+ if (d->currentIndex == idx) {
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ }
+ if (d->items.count() == 0)
+ d->firstIndex = idx;
+ d->items.append(item);
+ d->updateItem(item, pos);
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ pos = d->positionOfIndex(idx);
+ }
+
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ pos = d->positionOfIndex(idx);
+ while (!waiting && (pos >= 0.0 && pos < startPos) && d->items.count() < count) {
+// qDebug() << "prepend" << idx;
+ QQuickItem *item = d->getItem(idx, idx+1);
+ if (!item) {
+ waiting = true;
+ break;
+ }
+ if (d->currentIndex == idx) {
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ }
+ d->items.prepend(item);
+ d->updateItem(item, pos);
+ d->firstIndex = idx;
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ pos = d->positionOfIndex(idx);
+ }
+ }
+ }
+
+ if (!currentVisible) {
+ d->currentItemOffset = 1.0;
+ if (d->currentItem) {
+ if (QQuickPathViewAttached *att = d->attached(d->currentItem))
+ att->setOnPath(false);
+ } else if (!waiting && d->currentIndex >= 0 && d->currentIndex < d->modelCount) {
+ if (d->currentItem = d->getItem(d->currentIndex, d->currentIndex, false)) {
+ d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
+ if (QQuickPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ }
+ }
+ } else if (!waiting && !d->currentItem) {
+ if (d->currentItem = d->getItem(d->currentIndex, d->currentIndex, true)) {
+ d->currentItem->setFocus(true);
+ if (QQuickPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ }
+ }
+
+ if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ d->updateItem(d->highlightItem, d->highlightRangeStart);
+ if (QQuickPathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(true);
+ } else if (d->highlightItem && d->moveReason != QQuickPathViewPrivate::SetIndex) {
+ d->updateItem(d->highlightItem, d->currentItemOffset);
+ if (QQuickPathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(currentVisible);
+ }
+ while (d->itemCache.count())
+ d->releaseItem(d->itemCache.takeLast());
+}
+
+void QQuickPathView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
+{
+ Q_D(QQuickPathView);
+ if (!d->model || !d->model->isValid() || !d->path || !isComponentComplete())
+ return;
+
+ if (reset) {
+ d->modelCount = d->model->count();
+ d->regenerate();
+ emit countChanged();
+ return;
+ }
+
+ if (changeSet.removes().isEmpty() && changeSet.inserts().isEmpty())
+ return;
+
+ const int modelCount = d->modelCount;
+ int moveId = -1;
+ int moveOffset;
+ bool currentChanged = false;
+ bool changedOffset = false;
+ foreach (const QDeclarativeChangeSet::Remove &r, changeSet.removes()) {
+ if (moveId == -1 && d->currentIndex >= r.index + r.count) {
+ d->currentIndex -= r.count;
+ currentChanged = true;
+ } else if (moveId == -1 && d->currentIndex >= r.index && d->currentIndex < r.index + r.count) {
+ // current item has been removed.
+ d->currentIndex = qMin(r.index, d->modelCount - r.count - 1);
+ if (r.isMove()) {
+ moveId = r.moveId;
+ moveOffset = d->currentIndex - r.index;
+ } else if (d->currentItem) {
+ if (QQuickPathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ }
+ currentChanged = true;
+ }
+
+ if (r.index > d->currentIndex) {
+ changedOffset = true;
+ d->offset -= r.count;
+ d->offsetAdj -= r.count;
+ }
+ d->modelCount -= r.count;
+ }
+ foreach (const QDeclarativeChangeSet::Insert &i, changeSet.inserts()) {
+ if (d->modelCount) {
+ if (moveId == -1 && i.index <= d->currentIndex) {
+ d->currentIndex += i.count;
+ currentChanged = true;
+ } else {
+ if (moveId != -1 && moveId == i.moveId) {
+ d->currentIndex = i.index + moveOffset;
+ currentChanged = true;
+ }
+ if (i.index > d->currentIndex) {
+ d->offset += i.count;
+ d->offsetAdj += i.count;
+ changedOffset = true;
+ }
+ }
+ }
+ d->modelCount += i.count;
+ }
+
+ d->offset = qmlMod(d->offset, d->modelCount);
+ if (d->offset < 0)
+ d->offset += d->modelCount;
+
+ d->itemCache += d->items;
+ d->items.clear();
+
+ if (!d->modelCount) {
+ while (d->itemCache.count())
+ d->releaseItem(d->itemCache.takeLast());
+ d->offset = 0;
+ changedOffset = true;
+ d->tl.reset(d->moveOffset);
+ } else {
+ if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
+ changedOffset = true;
+ }
+ d->firstIndex = -1;
+ d->updateMappedRange();
+ d->scheduleLayout();
+ }
+ if (changedOffset)
+ emit offsetChanged();
+ if (currentChanged)
+ emit currentIndexChanged();
+ if (d->modelCount != modelCount)
+ emit countChanged();
+}
+
+void QQuickPathView::destroyingItem(QQuickItem *item)
+{
+ Q_UNUSED(item);
+}
+
+void QQuickPathView::ticked()
+{
+ Q_D(QQuickPathView);
+ d->updateCurrent();
+}
+
+void QQuickPathView::movementEnding()
+{
+ Q_D(QQuickPathView);
+ if (d->flicking) {
+ d->flicking = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ if (d->moving && !d->stealMouse) {
+ d->moving = false;
+ emit movingChanged();
+ emit movementEnded();
+ }
+}
+
+// find the item closest to the snap position
+int QQuickPathViewPrivate::calcCurrentIndex()
+{
+ int current = -1;
+ if (modelCount && model && items.count()) {
+ offset = qmlMod(offset, modelCount);
+ if (offset < 0)
+ offset += modelCount;
+ current = qRound(qAbs(qmlMod(modelCount - offset, modelCount)));
+ current = current % modelCount;
+ }
+
+ return current;
+}
+
+void QQuickPathViewPrivate::createCurrentItem()
+{
+ if (requestedIndex != -1)
+ return;
+ int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
+ if (itemIndex < items.count()) {
+ if (currentItem = getItem(currentIndex, currentIndex, true)) {
+ currentItem->setFocus(true);
+ if (QQuickPathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(true);
+ }
+ } else if (currentIndex >= 0 && currentIndex < modelCount) {
+ if (currentItem = getItem(currentIndex, currentIndex, false)) {
+ updateItem(currentItem, currentIndex < firstIndex ? 0.0 : 1.0);
+ if (QQuickPathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(true);
+ }
+ }
+}
+
+void QQuickPathViewPrivate::updateCurrent()
+{
+ Q_Q(QQuickPathView);
+ if (moveReason != Mouse)
+ return;
+ if (!modelCount || !haveHighlightRange || highlightRangeMode != QQuickPathView::StrictlyEnforceRange)
+ return;
+
+ int idx = calcCurrentIndex();
+ if (model && idx != currentIndex) {
+ if (currentItem) {
+ if (QQuickPathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ }
+ currentIndex = idx;
+ currentItem = 0;
+ createCurrentItem();
+ emit q->currentIndexChanged();
+ }
+}
+
+void QQuickPathViewPrivate::fixOffsetCallback(void *d)
+{
+ ((QQuickPathViewPrivate *)d)->fixOffset();
+}
+
+void QQuickPathViewPrivate::fixOffset()
+{
+ Q_Q(QQuickPathView);
+ if (model && items.count()) {
+ if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
+ }
+}
+
+void QQuickPathViewPrivate::snapToCurrent()
+{
+ if (!model || modelCount <= 0)
+ return;
+
+ qreal targetOffset = qmlMod(modelCount - currentIndex, modelCount);
+
+ if (offset == targetOffset)
+ return;
+
+ moveReason = Other;
+ offsetAdj = 0.0;
+ tl.reset(moveOffset);
+ moveOffset.setValue(offset);
+
+ const int duration = highlightMoveDuration;
+
+ if (!duration) {
+ tl.set(moveOffset, targetOffset);
+ } else if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2)) {
+ qreal distance = modelCount - targetOffset + offset;
+ if (targetOffset > moveOffset) {
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
+ tl.set(moveOffset, modelCount);
+ tl.move(moveOffset, targetOffset, QEasingCurve(offset == 0.0 ? QEasingCurve::InOutQuad : QEasingCurve::OutQuad), int(duration * (modelCount-targetOffset) / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2) {
+ qreal distance = modelCount - offset + targetOffset;
+ if (targetOffset < moveOffset) {
+ tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
+ tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * targetOffset / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ moveDirection = Shortest;
+}
+
+QQuickPathViewAttached *QQuickPathView::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickPathViewAttached(obj);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
new file mode 100644
index 0000000000..17195b7f02
--- /dev/null
+++ b/src/quick/items/qquickpathview_p.h
@@ -0,0 +1,257 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKPATHVIEW_P_H
+#define QQUICKPATHVIEW_P_H
+
+#include "qquickitem.h"
+
+#include <private/qdeclarativepath_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeChangeSet;
+
+class QQuickPathViewPrivate;
+class QQuickPathViewAttached;
+class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
+ Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+ Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount NOTIFY pathItemCountChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+
+public:
+ QQuickPathView(QQuickItem *parent=0);
+ virtual ~QQuickPathView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QQuickItem *currentItem() const;
+
+ qreal offset() const;
+ void setOffset(qreal offset);
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *highlight);
+ QQuickItem *highlightItem();
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+
+ int highlightMoveDuration() const;
+ void setHighlightMoveDuration(int);
+
+ qreal dragMargin() const;
+ void setDragMargin(qreal margin);
+
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal dec);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
+ bool isMoving() const;
+ bool isFlicking() const;
+
+ int count() const;
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int pathItemCount() const;
+ void setPathItemCount(int);
+
+ static QQuickPathViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void incrementCurrentIndex();
+ void decrementCurrentIndex();
+
+Q_SIGNALS:
+ void currentIndexChanged();
+ void currentItemChanged();
+ void offsetChanged();
+ void modelChanged();
+ void countChanged();
+ void pathChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightRangeModeChanged();
+ void dragMarginChanged();
+ void snapPositionChanged();
+ void delegateChanged();
+ void pathItemCountChanged();
+ void flickDecelerationChanged();
+ void interactiveChanged();
+ void movingChanged();
+ void flickingChanged();
+ void highlightChanged();
+ void highlightItemChanged();
+ void highlightMoveDurationChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+
+protected:
+ virtual void updatePolish();
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *);
+ bool sendMouseEvent(QMouseEvent *event);
+ bool childMouseEventFilter(QQuickItem *, QEvent *);
+ void mouseUngrabEvent();
+ void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void ticked();
+ void movementEnding();
+ void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+ void createdItem(int index, QQuickItem *item);
+ void initItem(int index, QQuickItem *item);
+ void destroyingItem(QQuickItem *item);
+ void pathUpdated();
+
+private:
+ friend class QQuickPathViewAttached;
+ Q_DISABLE_COPY(QQuickPathView)
+ Q_DECLARE_PRIVATE(QQuickPathView)
+};
+
+class QDeclarativeOpenMetaObject;
+class QQuickPathViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQuickPathView *view READ view CONSTANT)
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ Q_PROPERTY(bool onPath READ isOnPath NOTIFY pathChanged)
+
+public:
+ QQuickPathViewAttached(QObject *parent);
+ ~QQuickPathViewAttached();
+
+ QQuickPathView *view() { return m_view; }
+
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ QVariant value(const QByteArray &name) const;
+ void setValue(const QByteArray &name, const QVariant &val);
+
+ bool isOnPath() const { return m_onPath; }
+ void setOnPath(bool on) {
+ if (on != m_onPath) {
+ m_onPath = on;
+ emit pathChanged();
+ }
+ }
+ qreal m_percent;
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void pathChanged();
+
+private:
+ friend class QQuickPathViewPrivate;
+ friend class QQuickPathView;
+ QQuickPathView *m_view;
+ QDeclarativeOpenMetaObject *m_metaobject;
+ bool m_onPath : 1;
+ bool m_isCurrent : 1;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickPathView)
+QML_DECLARE_TYPEINFO(QQuickPathView, QML_HAS_ATTACHED_PROPERTIES)
+QT_END_HEADER
+
+#endif // QQUICKPATHVIEW_P_H
diff --git a/src/declarative/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index 9bf329dab5..9bf329dab5 100644
--- a/src/declarative/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
diff --git a/src/declarative/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index beacbe32bf..beacbe32bf 100644
--- a/src/declarative/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
new file mode 100644
index 0000000000..0f3eda0f98
--- /dev/null
+++ b/src/quick/items/qquickpincharea_p.h
@@ -0,0 +1,313 @@
+// Commit: f707672eb4c51ea82fbd98e1da16ece61a74c690
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtSG 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 QQUICKPINCHAREA_H
+#define QQUICKPINCHAREA_H
+
+#include "qquickitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget RESET resetTarget)
+ Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged)
+ Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged)
+ Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged)
+ Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged)
+ Q_PROPERTY(Axis dragAxis READ axis WRITE setAxis NOTIFY dragAxisChanged)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+
+public:
+ QQuickPinch();
+
+ QQuickItem *target() const { return m_target; }
+ void setTarget(QQuickItem *target) {
+ if (target == m_target)
+ return;
+ m_target = target;
+ emit targetChanged();
+ }
+ void resetTarget() {
+ if (!m_target)
+ return;
+ m_target = 0;
+ emit targetChanged();
+ }
+
+ qreal minimumScale() const { return m_minScale; }
+ void setMinimumScale(qreal s) {
+ if (s == m_minScale)
+ return;
+ m_minScale = s;
+ emit minimumScaleChanged();
+ }
+ qreal maximumScale() const { return m_maxScale; }
+ void setMaximumScale(qreal s) {
+ if (s == m_maxScale)
+ return;
+ m_maxScale = s;
+ emit maximumScaleChanged();
+ }
+
+ qreal minimumRotation() const { return m_minRotation; }
+ void setMinimumRotation(qreal r) {
+ if (r == m_minRotation)
+ return;
+ m_minRotation = r;
+ emit minimumRotationChanged();
+ }
+ qreal maximumRotation() const { return m_maxRotation; }
+ void setMaximumRotation(qreal r) {
+ if (r == m_maxRotation)
+ return;
+ m_maxRotation = r;
+ emit maximumRotationChanged();
+ }
+
+ enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
+ Axis axis() const { return m_axis; }
+ void setAxis(Axis a) {
+ if (a == m_axis)
+ return;
+ m_axis = a;
+ emit dragAxisChanged();
+ }
+
+ qreal xmin() const { return m_xmin; }
+ void setXmin(qreal x) {
+ if (x == m_xmin)
+ return;
+ m_xmin = x;
+ emit minimumXChanged();
+ }
+ qreal xmax() const { return m_xmax; }
+ void setXmax(qreal x) {
+ if (x == m_xmax)
+ return;
+ m_xmax = x;
+ emit maximumXChanged();
+ }
+ qreal ymin() const { return m_ymin; }
+ void setYmin(qreal y) {
+ if (y == m_ymin)
+ return;
+ m_ymin = y;
+ emit minimumYChanged();
+ }
+ qreal ymax() const { return m_ymax; }
+ void setYmax(qreal y) {
+ if (y == m_ymax)
+ return;
+ m_ymax = y;
+ emit maximumYChanged();
+ }
+
+ bool active() const { return m_active; }
+ void setActive(bool a) {
+ if (a == m_active)
+ return;
+ m_active = a;
+ emit activeChanged();
+ }
+
+signals:
+ void targetChanged();
+ void minimumScaleChanged();
+ void maximumScaleChanged();
+ void minimumRotationChanged();
+ void maximumRotationChanged();
+ void dragAxisChanged();
+ void minimumXChanged();
+ void maximumXChanged();
+ void minimumYChanged();
+ void maximumYChanged();
+ void activeChanged();
+
+private:
+ QQuickItem *m_target;
+ qreal m_minScale;
+ qreal m_maxScale;
+ qreal m_minRotation;
+ qreal m_maxRotation;
+ Axis m_axis;
+ qreal m_xmin;
+ qreal m_xmax;
+ qreal m_ymin;
+ qreal m_ymax;
+ bool m_active;
+};
+
+class Q_AUTOTEST_EXPORT QQuickPinchEvent : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPointF center READ center)
+ Q_PROPERTY(QPointF startCenter READ startCenter)
+ Q_PROPERTY(QPointF previousCenter READ previousCenter)
+ Q_PROPERTY(qreal scale READ scale)
+ Q_PROPERTY(qreal previousScale READ previousScale)
+ Q_PROPERTY(qreal angle READ angle)
+ Q_PROPERTY(qreal previousAngle READ previousAngle)
+ Q_PROPERTY(qreal rotation READ rotation)
+ Q_PROPERTY(QPointF point1 READ point1)
+ Q_PROPERTY(QPointF startPoint1 READ startPoint1)
+ Q_PROPERTY(QPointF point2 READ point2)
+ Q_PROPERTY(QPointF startPoint2 READ startPoint2)
+ Q_PROPERTY(int pointCount READ pointCount)
+ Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
+
+public:
+ QQuickPinchEvent(QPointF c, qreal s, qreal a, qreal r)
+ : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r)
+ , m_pointCount(0), m_accepted(true) {}
+
+ QPointF center() const { return m_center; }
+ QPointF startCenter() const { return m_startCenter; }
+ void setStartCenter(QPointF c) { m_startCenter = c; }
+ QPointF previousCenter() const { return m_lastCenter; }
+ void setPreviousCenter(QPointF c) { m_lastCenter = c; }
+ qreal scale() const { return m_scale; }
+ qreal previousScale() const { return m_lastScale; }
+ void setPreviousScale(qreal s) { m_lastScale = s; }
+ qreal angle() const { return m_angle; }
+ qreal previousAngle() const { return m_lastAngle; }
+ void setPreviousAngle(qreal a) { m_lastAngle = a; }
+ qreal rotation() const { return m_rotation; }
+ QPointF point1() const { return m_point1; }
+ void setPoint1(QPointF p) { m_point1 = p; }
+ QPointF startPoint1() const { return m_startPoint1; }
+ void setStartPoint1(QPointF p) { m_startPoint1 = p; }
+ QPointF point2() const { return m_point2; }
+ void setPoint2(QPointF p) { m_point2 = p; }
+ QPointF startPoint2() const { return m_startPoint2; }
+ void setStartPoint2(QPointF p) { m_startPoint2 = p; }
+ int pointCount() const { return m_pointCount; }
+ void setPointCount(int count) { m_pointCount = count; }
+
+ bool accepted() const { return m_accepted; }
+ void setAccepted(bool a) { m_accepted = a; }
+
+private:
+ QPointF m_center;
+ QPointF m_startCenter;
+ QPointF m_lastCenter;
+ qreal m_scale;
+ qreal m_lastScale;
+ qreal m_angle;
+ qreal m_lastAngle;
+ qreal m_rotation;
+ QPointF m_point1;
+ QPointF m_point2;
+ QPointF m_startPoint1;
+ QPointF m_startPoint2;
+ int m_pointCount;
+ bool m_accepted;
+};
+
+
+class QQuickMouseEvent;
+class QQuickPinchAreaPrivate;
+class Q_AUTOTEST_EXPORT QQuickPinchArea : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QQuickPinch *pinch READ pinch CONSTANT)
+
+public:
+ QQuickPinchArea(QQuickItem *parent=0);
+ ~QQuickPinchArea();
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ QQuickPinch *pinch();
+
+Q_SIGNALS:
+ void enabledChanged();
+ void pinchStarted(QQuickPinchEvent *pinch);
+ void pinchUpdated(QQuickPinchEvent *pinch);
+ void pinchFinished(QQuickPinchEvent *pinch);
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *event);
+ virtual void mouseUngrabEvent();
+ virtual bool sendMouseEvent(QMouseEvent *event);
+ virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
+ virtual void touchEvent(QTouchEvent *event);
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void itemChange(ItemChange change, const ItemChangeData& value);
+
+private:
+ void updatePinch();
+ void handlePress();
+ void handleRelease();
+
+private:
+ Q_DISABLE_COPY(QQuickPinchArea)
+ Q_DECLARE_PRIVATE(QQuickPinchArea)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickPinch)
+QML_DECLARE_TYPE(QQuickPinchEvent)
+QML_DECLARE_TYPE(QQuickPinchArea)
+
+QT_END_HEADER
+
+#endif // QQUICKPINCHAREA_H
+
diff --git a/src/declarative/items/qquickpincharea_p_p.h b/src/quick/items/qquickpincharea_p_p.h
index 1c9d5c5ba4..1c9d5c5ba4 100644
--- a/src/declarative/items/qquickpincharea_p_p.h
+++ b/src/quick/items/qquickpincharea_p_p.h
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
new file mode 100644
index 0000000000..2643baa804
--- /dev/null
+++ b/src/quick/items/qquickpositioners.cpp
@@ -0,0 +1,1532 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickpositioners_p.h"
+#include "qquickpositioners_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <QtQuick/private/qdeclarativestategroup_p.h>
+#include <private/qdeclarativestateoperations_p.h>
+#include <QtQuick/private/qdeclarativetransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const QQuickItemPrivate::ChangeTypes watchedChanges
+ = QQuickItemPrivate::Geometry
+ | QQuickItemPrivate::SiblingOrder
+ | QQuickItemPrivate::Visibility
+ | QQuickItemPrivate::Destroyed;
+
+void QQuickBasePositionerPrivate::watchChanges(QQuickItem *other)
+{
+ QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other);
+ otherPrivate->addItemChangeListener(this, watchedChanges);
+}
+
+void QQuickBasePositionerPrivate::unwatchChanges(QQuickItem* other)
+{
+ QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other);
+ otherPrivate->removeItemChangeListener(this, watchedChanges);
+}
+
+QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent)
+ : QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent)
+{
+ Q_D(QQuickBasePositioner);
+ d->init(at);
+}
+/*!
+ \internal
+ \class QQuickBasePositioner
+ \brief The QQuickBasePositioner class provides a base for QQuickGraphics layouts.
+
+ To create a QQuickGraphics Positioner, simply subclass QQuickBasePositioner and implement
+ doLayout(), which is automatically called when the layout might need
+ updating. In doLayout() use the setX and setY functions from QQuickBasePositioner, and the
+ base class will apply the positions along with the appropriate transitions. The items to
+ position are provided in order as the protected member positionedItems.
+
+ You also need to set a PositionerType, to declare whether you are positioning the x, y or both
+ for the child items. Depending on the chosen type, only x or y changes will be applied.
+
+ Note that the subclass is responsible for adding the spacing in between items.
+
+ Positioning is usually delayed until before a frame is rendered, to batch multiple repositioning
+ changes into one calculation.
+*/
+
+QQuickBasePositioner::QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent)
+ : QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickBasePositioner);
+ d->init(at);
+}
+
+QQuickBasePositioner::~QQuickBasePositioner()
+{
+ Q_D(QQuickBasePositioner);
+ for (int i = 0; i < positionedItems.count(); ++i)
+ d->unwatchChanges(positionedItems.at(i).item);
+ positionedItems.clear();
+}
+
+void QQuickBasePositioner::updatePolish()
+{
+ Q_D(QQuickBasePositioner);
+ if (d->positioningDirty)
+ prePositioning();
+}
+
+int QQuickBasePositioner::spacing() const
+{
+ Q_D(const QQuickBasePositioner);
+ return d->spacing;
+}
+
+void QQuickBasePositioner::setSpacing(int s)
+{
+ Q_D(QQuickBasePositioner);
+ if (s==d->spacing)
+ return;
+ d->spacing = s;
+ d->setPositioningDirty();
+ emit spacingChanged();
+}
+
+QDeclarativeTransition *QQuickBasePositioner::move() const
+{
+ Q_D(const QQuickBasePositioner);
+ return d->moveTransition;
+}
+
+void QQuickBasePositioner::setMove(QDeclarativeTransition *mt)
+{
+ Q_D(QQuickBasePositioner);
+ if (mt == d->moveTransition)
+ return;
+ d->moveTransition = mt;
+ emit moveChanged();
+}
+
+QDeclarativeTransition *QQuickBasePositioner::add() const
+{
+ Q_D(const QQuickBasePositioner);
+ return d->addTransition;
+}
+
+void QQuickBasePositioner::setAdd(QDeclarativeTransition *add)
+{
+ Q_D(QQuickBasePositioner);
+ if (add == d->addTransition)
+ return;
+
+ d->addTransition = add;
+ emit addChanged();
+}
+
+void QQuickBasePositioner::componentComplete()
+{
+ QQuickItem::componentComplete();
+ positionedItems.reserve(childItems().count());
+ prePositioning();
+ reportConflictingAnchors();
+}
+
+void QQuickBasePositioner::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ Q_D(QQuickBasePositioner);
+ if (change == ItemChildAddedChange){
+ d->setPositioningDirty();
+ } else if (change == ItemChildRemovedChange) {
+ QQuickItem *child = value.item;
+ QQuickBasePositioner::PositionedItem posItem(child);
+ int idx = positionedItems.find(posItem);
+ if (idx >= 0) {
+ d->unwatchChanges(child);
+ positionedItems.remove(idx);
+ }
+ d->setPositioningDirty();
+ }
+
+ QQuickItem::itemChange(change, value);
+}
+
+void QQuickBasePositioner::prePositioning()
+{
+ Q_D(QQuickBasePositioner);
+ if (!isComponentComplete())
+ return;
+
+ if (d->doingPositioning)
+ return;
+
+ d->positioningDirty = false;
+ d->doingPositioning = true;
+ //Need to order children by creation order modified by stacking order
+ QList<QQuickItem *> children = childItems();
+
+ QPODVector<PositionedItem,8> oldItems;
+ positionedItems.copyAndClear(oldItems);
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QQuickItem *child = children.at(ii);
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
+ PositionedItem *item = 0;
+ PositionedItem posItem(child);
+ int wIdx = oldItems.find(posItem);
+ if (wIdx < 0) {
+ d->watchChanges(child);
+ positionedItems.append(posItem);
+ item = &positionedItems[positionedItems.count()-1];
+ item->isNew = true;
+ if (!childPrivate->explicitVisible || !child->width() || !child->height())
+ item->isVisible = false;
+ } else {
+ item = &oldItems[wIdx];
+ // Items are only omitted from positioning if they are explicitly hidden
+ // i.e. their positioning is not affected if an ancestor is hidden.
+ if (!childPrivate->explicitVisible || !child->width() || !child->height()) {
+ item->isVisible = false;
+ } else if (!item->isVisible) {
+ item->isVisible = true;
+ item->isNew = true;
+ } else {
+ item->isNew = false;
+ }
+ positionedItems.append(*item);
+ }
+ }
+ QSizeF contentSize(0,0);
+ doPositioning(&contentSize);
+ updateAttachedProperties();
+ if (!d->addActions.isEmpty() || !d->moveActions.isEmpty())
+ finishApplyTransitions();
+ d->doingPositioning = false;
+ //Set implicit size to the size of its children
+ setImplicitSize(contentSize.width(), contentSize.height());
+}
+
+void QQuickBasePositioner::positionX(int x, const PositionedItem &target)
+{
+ Q_D(QQuickBasePositioner);
+ if (d->type == Horizontal || d->type == Both) {
+ if (target.isNew) {
+ if (!d->addTransition || !d->addTransition->enabled())
+ target.item->setX(x);
+ else
+ d->addActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
+ } else if (x != target.item->x()) {
+ if (!d->moveTransition || !d->moveTransition->enabled())
+ target.item->setX(x);
+ else
+ d->moveActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
+ }
+ }
+}
+
+void QQuickBasePositioner::positionY(int y, const PositionedItem &target)
+{
+ Q_D(QQuickBasePositioner);
+ if (d->type == Vertical || d->type == Both) {
+ if (target.isNew) {
+ if (!d->addTransition || !d->addTransition->enabled())
+ target.item->setY(y);
+ else
+ d->addActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
+ } else if (y != target.item->y()) {
+ if (!d->moveTransition || !d->moveTransition->enabled())
+ target.item->setY(y);
+ else
+ d->moveActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
+ }
+ }
+}
+
+void QQuickBasePositioner::finishApplyTransitions()
+{
+ Q_D(QQuickBasePositioner);
+ // Note that if a transition is not set the transition manager will
+ // apply the changes directly, in the case add/move aren't set
+ d->addTransitionManager.transition(d->addActions, d->addTransition);
+ d->moveTransitionManager.transition(d->moveActions, d->moveTransition);
+ d->addActions.clear();
+ d->moveActions.clear();
+}
+
+QQuickPositionerAttached *QQuickBasePositioner::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickPositionerAttached(obj);
+}
+
+void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *specificProperty, QQuickItem *specificPropertyOwner) const
+{
+ // If this function is deemed too expensive or shows up in profiles, it could
+ // be changed to run only when there are attached properties present. This
+ // could be a flag in the positioner that is set by the attached property
+ // constructor.
+ QQuickPositionerAttached *prevLastProperty = 0;
+ QQuickPositionerAttached *lastProperty = 0;
+
+ int visibleItemIndex = 0;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item)
+ continue;
+
+ QQuickPositionerAttached *property = 0;
+
+ if (specificProperty) {
+ if (specificPropertyOwner == child.item) {
+ property = specificProperty;
+ }
+ } else {
+ property = static_cast<QQuickPositionerAttached *>(qmlAttachedPropertiesObject<QQuickBasePositioner>(child.item, false));
+ }
+
+ if (child.isVisible) {
+ if (property) {
+ property->setIndex(visibleItemIndex);
+ property->setIsFirstItem(visibleItemIndex == 0);
+
+ if (property->isLastItem())
+ prevLastProperty = property;
+ }
+
+ lastProperty = property;
+ ++visibleItemIndex;
+ } else if (property) {
+ property->setIndex(-1);
+ property->setIsFirstItem(false);
+ property->setIsLastItem(false);
+ }
+ }
+
+ if (prevLastProperty && prevLastProperty != lastProperty)
+ prevLastProperty->setIsLastItem(false);
+ if (lastProperty)
+ lastProperty->setIsLastItem(true);
+}
+
+/*!
+ \qmlclass Positioner QQuickPositionerAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Positioner type provides attached properties that contain details on where an item exists in a positioner.
+
+ Positioner items (such as Column, Row, Flow and Grid) provide automatic layout
+ for child items. Attaching this property allows a child item to determine
+ where it exists within the positioner.
+*/
+
+QQuickPositionerAttached::QQuickPositionerAttached(QObject *parent) : QObject(parent), m_index(-1), m_isFirstItem(false), m_isLastItem(false)
+{
+ QQuickItem *attachedItem = qobject_cast<QQuickItem *>(parent);
+ if (attachedItem) {
+ QQuickBasePositioner *positioner = qobject_cast<QQuickBasePositioner *>(attachedItem->parent());
+ if (positioner) {
+ positioner->updateAttachedProperties(this, attachedItem);
+ }
+ }
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::index
+
+ This property allows the item to determine
+ its index within the positioner.
+*/
+void QQuickPositionerAttached::setIndex(int index)
+{
+ if (m_index == index)
+ return;
+ m_index = index;
+ emit indexChanged();
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::isFirstItem
+ \qmlattachedproperty Item QtQuick2::Positioner::isLastItem
+
+ These properties allow the item to determine if it
+ is the first or last item in the positioner, respectively.
+*/
+void QQuickPositionerAttached::setIsFirstItem(bool isFirstItem)
+{
+ if (m_isFirstItem == isFirstItem)
+ return;
+ m_isFirstItem = isFirstItem;
+ emit isFirstItemChanged();
+}
+
+void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
+{
+ if (m_isLastItem == isLastItem)
+ return;
+ m_isLastItem = isLastItem;
+ emit isLastItemChanged();
+}
+
+/*!
+ \qmlclass Column QQuickColumn
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Column item arranges its children vertically.
+ \inherits Item
+
+ The Column item positions its child items so that they are vertically
+ aligned and not overlapping.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions differently shaped rectangles using a Column
+ item.
+
+ \image verticalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Column item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Column item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \image verticalpositioner_transition.gif
+
+ \qml
+ Column {
+ spacing: 2
+ add: Transition {
+ // Define an animation for adding a new item...
+ }
+ move: Transition {
+ // Define an animation for moving items within the column...
+ }
+ // ...
+ }
+ \endqml
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ height of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Column.
+
+ Items with a width or height of 0 will not be positioned.
+
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
+ \sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Column::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Column::move
+
+ This property holds the transition to apply when moving an item
+ within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \image positioner-move.gif
+
+ \qml
+ Column {
+ move: Transition {
+ NumberAnimation {
+ properties: "y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Column::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
+QQuickColumn::QQuickColumn(QQuickItem *parent)
+: QQuickBasePositioner(Vertical, parent)
+{
+}
+
+void QQuickColumn::doPositioning(QSizeF *contentSize)
+{
+ int voffset = 0;
+
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ if (child.item->y() != voffset)
+ positionY(voffset, child);
+
+ contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
+
+ voffset += child.item->height();
+ voffset += spacing();
+ }
+
+ if (voffset != 0)//If we positioned any items, undo the spacing from the last item
+ voffset -= spacing();
+ contentSize->setHeight(voffset);
+}
+
+void QQuickColumn::reportConflictingAnchors()
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
+ if (anchors) {
+ QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
+ if (usedAnchors & QQuickAnchors::TopAnchor ||
+ usedAnchors & QQuickAnchors::BottomAnchor ||
+ usedAnchors & QQuickAnchors::VCenterAnchor ||
+ anchors->fill() || anchors->centerIn()) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ }
+ if (d->anchorConflict) {
+ qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
+ }
+}
+/*!
+ \qmlclass Row QQuickRow
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Row item arranges its children horizontally.
+ \inherits Item
+
+ The Row item positions its child items so that they are horizontally
+ aligned and not overlapping.
+
+ Use \l spacing to set the spacing between items in a Row, and use the
+ \l add and \l move properties to set the transitions that should be applied
+ when items are added to, removed from, or re-positioned within the Row.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example lays out differently shaped rectangles using a Row.
+
+ \image horizontalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/row/row.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Row item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Row.
+
+ Items with a width or height of 0 will not be positioned.
+
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
+ \sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Row::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Row::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Row {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Row::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
+
+QQuickRow::QQuickRow(QQuickItem *parent)
+: QQuickBasePositioner(Horizontal, parent)
+{
+}
+/*!
+ \qmlproperty enumeration QtQuick2::Row::layoutDirection
+
+ This property holds the layoutDirection of the row.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set,
+ the left anchor remains to the left of the row.
+ \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set,
+ the right anchor remains to the right of the row.
+ \endlist
+
+ \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+
+Qt::LayoutDirection QQuickRow::layoutDirection() const
+{
+ return QQuickBasePositionerPrivate::getLayoutDirection(this);
+}
+
+void QQuickRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ // For RTL layout the positioning changes when the width changes.
+ if (d->layoutDirection == Qt::RightToLeft)
+ d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
+ else
+ d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+/*!
+ \qmlproperty enumeration QtQuick2::Row::effectiveLayoutDirection
+ This property holds the effective layout direction of the row positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the row positioner will be mirrored. However, the
+ property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QQuickRow::effectiveLayoutDirection() const
+{
+ return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QQuickRow::doPositioning(QSizeF *contentSize)
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
+ int hoffset = 0;
+
+ QList<int> hoffsets;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ if (d->isLeftToRight()) {
+ if (child.item->x() != hoffset)
+ positionX(hoffset, child);
+ } else {
+ hoffsets << hoffset;
+ }
+
+ contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
+
+ hoffset += child.item->width();
+ hoffset += spacing();
+ }
+
+ if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item
+ hoffset -= spacing();
+ contentSize->setWidth(hoffset);
+
+ if (d->isLeftToRight())
+ return;
+
+ //Right to Left layout
+ int end = 0;
+ if (!widthValid())
+ end = contentSize->width();
+ else
+ end = width();
+
+ int acc = 0;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+ hoffset = end - hoffsets[acc++] - child.item->width();
+ if (child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }
+}
+
+void QQuickRow::reportConflictingAnchors()
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
+ if (anchors) {
+ QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
+ if (usedAnchors & QQuickAnchors::LeftAnchor ||
+ usedAnchors & QQuickAnchors::RightAnchor ||
+ usedAnchors & QQuickAnchors::HCenterAnchor ||
+ anchors->fill() || anchors->centerIn()) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row";
+}
+
+/*!
+ \qmlclass Grid QQuickGrid
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Grid item positions its children in a grid.
+ \inherits Item
+
+ The Grid item positions its child items so that they are
+ aligned in a grid and are not overlapping.
+
+ The grid positioner calculates a grid of rectangular cells of sufficient
+ size to hold all items, placing the items in the cells, from left to right
+ and top to bottom. Each item is positioned in the top-left corner of its
+ cell with position (0, 0).
+
+ A Grid defaults to four columns, and as many rows as are necessary to
+ fit all child items. The number of rows and columns can be constrained
+ by setting the \l rows and \l columns properties.
+
+ Spacing can be added between child items by setting the \l spacing
+ property. The amount of spacing applied will be the same in the
+ horizontal and vertical directions.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example demonstrates this.
+
+ \image gridLayout_example.png
+
+ \snippet doc/src/snippets/declarative/grid/grid.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Grid item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Grid.
+
+ Items with a width or height of 0 will not be positioned.
+
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
+ \sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Grid::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Grid::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Grid {
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Grid::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The positioner on the left has the
+ no spacing (the default), and the positioner on the right has
+ a spacing of 6.
+
+ \inlineimage qml-grid-no-spacing.png
+ \inlineimage qml-grid-spacing.png
+
+ \sa rows, columns
+*/
+QQuickGrid::QQuickGrid(QQuickItem *parent) :
+ QQuickBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_rowSpacing(-1), m_columnSpacing(-1), m_flow(LeftToRight)
+{
+}
+
+/*!
+ \qmlproperty int QtQuick2::Grid::columns
+
+ This property holds the number of columns in the grid. The default
+ number of columns is 4.
+
+ If the grid does not have enough items to fill the specified
+ number of columns, some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::Grid::rows
+ This property holds the number of rows in the grid.
+
+ If the grid does not have enough items to fill the specified
+ number of rows, some rows will be of zero width.
+*/
+
+void QQuickGrid::setColumns(const int columns)
+{
+ if (columns == m_columns)
+ return;
+ m_columns = columns;
+ prePositioning();
+ emit columnsChanged();
+}
+
+void QQuickGrid::setRows(const int rows)
+{
+ if (rows == m_rows)
+ return;
+ m_rows = rows;
+ prePositioning();
+ emit rowsChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Grid.LeftToRight (default) - Items are positioned next to
+ each other in the \l layoutDirection, then wrapped to the next line.
+ \o Grid.TopToBottom - Items are positioned next to each
+ other from top to bottom, then wrapped to the next column.
+ \endlist
+*/
+QQuickGrid::Flow QQuickGrid::flow() const
+{
+ return m_flow;
+}
+
+void QQuickGrid::setFlow(Flow flow)
+{
+ if (m_flow != flow) {
+ m_flow = flow;
+ prePositioning();
+ emit flowChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::Grid::rowSpacing
+
+ This property holds the spacing in pixels between rows.
+
+ \sa columnSpacing
+ \since QtQuick2.0
+*/
+void QQuickGrid::setRowSpacing(const int rowSpacing)
+{
+ if (rowSpacing == m_rowSpacing)
+ return;
+ m_rowSpacing = rowSpacing;
+ prePositioning();
+ emit rowSpacingChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::Grid::columnSpacing
+
+ This property holds the spacing in pixels between columns.
+
+ \sa rowSpacing
+ \since QtQuick2.0
+*/
+void QQuickGrid::setColumnSpacing(const int columnSpacing)
+{
+ if (columnSpacing == m_columnSpacing)
+ return;
+ m_columnSpacing = columnSpacing;
+ prePositioning();
+ emit columnSpacingChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::layoutDirection
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Grid::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Grid::flow property.
+ \endlist
+
+ \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+Qt::LayoutDirection QQuickGrid::layoutDirection() const
+{
+ return QQuickBasePositionerPrivate::getLayoutDirection(this);
+}
+
+void QQuickGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ // For RTL layout the positioning changes when the width changes.
+ if (d->layoutDirection == Qt::RightToLeft)
+ d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
+ else
+ d->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Grid::effectiveLayoutDirection
+ This property holds the effective layout direction of the grid positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const
+{
+ return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QQuickGrid::doPositioning(QSizeF *contentSize)
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
+ int c = m_columns;
+ int r = m_rows;
+ //Is allocating the extra QPODVector too much overhead?
+ QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items
+ visibleItems.reserve(positionedItems.count());
+ for (int i=0; i<positionedItems.count(); i++)
+ if (positionedItems[i].item && positionedItems[i].isVisible)
+ visibleItems.append(positionedItems[i]);
+
+ int numVisible = visibleItems.count();
+ if (m_columns <= 0 && m_rows <= 0){
+ c = 4;
+ r = (numVisible+3)/4;
+ } else if (m_rows <= 0){
+ r = (numVisible+(m_columns-1))/m_columns;
+ } else if (m_columns <= 0){
+ c = (numVisible+(m_rows-1))/m_rows;
+ }
+
+ if (r==0 || c==0)
+ return; //Nothing to do
+
+ QList<int> maxColWidth;
+ QList<int> maxRowHeight;
+ int childIndex =0;
+ if (m_flow == LeftToRight) {
+ for (int i=0; i < r; i++){
+ for (int j=0; j < c; j++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+
+ if (childIndex == visibleItems.count())
+ break;
+
+ const PositionedItem &child = visibleItems.at(childIndex++);
+ if (child.item->width() > maxColWidth[j])
+ maxColWidth[j] = child.item->width();
+ if (child.item->height() > maxRowHeight[i])
+ maxRowHeight[i] = child.item->height();
+ }
+ }
+ } else {
+ for (int j=0; j < c; j++){
+ for (int i=0; i < r; i++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+
+ if (childIndex == visibleItems.count())
+ break;
+
+ const PositionedItem &child = visibleItems.at(childIndex++);
+ if (child.item->width() > maxColWidth[j])
+ maxColWidth[j] = child.item->width();
+ if (child.item->height() > maxRowHeight[i])
+ maxRowHeight[i] = child.item->height();
+ }
+ }
+ }
+
+ int columnSpacing = m_columnSpacing;
+ if (columnSpacing == -1)
+ columnSpacing = spacing();
+
+ int rowSpacing = m_rowSpacing;
+ if (rowSpacing == -1)
+ rowSpacing = spacing();
+
+ int widthSum = 0;
+ for (int j=0; j < maxColWidth.size(); j++){
+ if (j)
+ widthSum += columnSpacing;
+ widthSum += maxColWidth[j];
+ }
+
+ int heightSum = 0;
+ for (int i=0; i < maxRowHeight.size(); i++){
+ if (i)
+ heightSum += rowSpacing;
+ heightSum += maxRowHeight[i];
+ }
+
+ contentSize->setHeight(heightSum);
+ contentSize->setWidth(widthSum);
+
+ int end = 0;
+ if (widthValid())
+ end = width();
+ else
+ end = widthSum;
+
+ int xoffset=0;
+ if (!d->isLeftToRight())
+ xoffset = end;
+ int yoffset=0;
+ int curRow =0;
+ int curCol =0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ const PositionedItem &child = visibleItems.at(i);
+ int childXOffset = xoffset;
+ if (!d->isLeftToRight())
+ childXOffset -= child.item->width();
+ if ((child.item->x() != childXOffset) || (child.item->y() != yoffset)){
+ positionX(childXOffset, child);
+ positionY(yoffset, child);
+ }
+
+ if (m_flow == LeftToRight) {
+ if (d->isLeftToRight())
+ xoffset += maxColWidth[curCol]+columnSpacing;
+ else
+ xoffset -= maxColWidth[curCol]+columnSpacing;
+ curCol++;
+ curCol%=c;
+ if (!curCol){
+ yoffset += maxRowHeight[curRow]+rowSpacing;
+ if (d->isLeftToRight())
+ xoffset = 0;
+ else
+ xoffset = end;
+ curRow++;
+ if (curRow>=r)
+ break;
+ }
+ } else {
+ yoffset+=maxRowHeight[curRow]+rowSpacing;
+ curRow++;
+ curRow%=r;
+ if (!curRow){
+ if (d->isLeftToRight())
+ xoffset += maxColWidth[curCol]+columnSpacing;
+ else
+ xoffset -= maxColWidth[curCol]+columnSpacing;
+ yoffset=0;
+ curCol++;
+ if (curCol>=c)
+ break;
+ }
+ }
+ }
+}
+
+void QQuickGrid::reportConflictingAnchors()
+{
+ QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
+ if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify anchors for items inside Grid";
+}
+
+/*!
+ \qmlclass Flow QQuickFlow
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Flow item arranges its children side by side, wrapping as necessary.
+ \inherits Item
+
+ The Flow item positions its child items like words on a page, wrapping them
+ to create rows or columns of items that do not overlap.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions \l Text items within a parent item using
+ a Flow item.
+
+ \image qml-flow-snippet.png
+
+ \snippet doc/src/snippets/declarative/flow.qml flow item
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Flow item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Flow item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Flow.
+
+ Items with a width or height of 0 will not be positioned.
+
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
+ \sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Flow::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition QtQuick2::Flow::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Flow {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int QtQuick2::Flow::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ \sa Grid::spacing
+*/
+
+class QQuickFlowPrivate : public QQuickBasePositionerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickFlow)
+
+public:
+ QQuickFlowPrivate()
+ : QQuickBasePositionerPrivate(), flow(QQuickFlow::LeftToRight)
+ {}
+
+ QQuickFlow::Flow flow;
+};
+
+QQuickFlow::QQuickFlow(QQuickItem *parent)
+: QQuickBasePositioner(*(new QQuickFlowPrivate), Both, parent)
+{
+ Q_D(QQuickFlow);
+ // Flow layout requires relayout if its own size changes too.
+ d->addItemChangeListener(d, QQuickItemPrivate::Geometry);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Flow.LeftToRight (default) - Items are positioned next to
+ to each other according to the \l layoutDirection until the width of the Flow
+ is exceeded, then wrapped to the next line.
+ \o Flow.TopToBottom - Items are positioned next to each
+ other from top to bottom until the height of the Flow is exceeded,
+ then wrapped to the next column.
+ \endlist
+*/
+QQuickFlow::Flow QQuickFlow::flow() const
+{
+ Q_D(const QQuickFlow);
+ return d->flow;
+}
+
+void QQuickFlow::setFlow(Flow flow)
+{
+ Q_D(QQuickFlow);
+ if (d->flow != flow) {
+ d->flow = flow;
+ prePositioning();
+ emit flowChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::layoutDirection
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Flow::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Flow::flow property.
+ \endlist
+
+ \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+
+Qt::LayoutDirection QQuickFlow::layoutDirection() const
+{
+ Q_D(const QQuickFlow);
+ return d->layoutDirection;
+}
+
+void QQuickFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ Q_D(QQuickFlow);
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Flow::effectiveLayoutDirection
+ This property holds the effective layout direction of the flow positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QQuickFlow::effectiveLayoutDirection() const
+{
+ return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QQuickFlow::doPositioning(QSizeF *contentSize)
+{
+ Q_D(QQuickFlow);
+
+ int hoffset = 0;
+ int voffset = 0;
+ int linemax = 0;
+ QList<int> hoffsets;
+
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ if (d->flow == LeftToRight) {
+ if (widthValid() && hoffset && hoffset + child.item->width() > width()) {
+ hoffset = 0;
+ voffset += linemax + spacing();
+ linemax = 0;
+ }
+ } else {
+ if (heightValid() && voffset && voffset + child.item->height() > height()) {
+ voffset = 0;
+ hoffset += linemax + spacing();
+ linemax = 0;
+ }
+ }
+
+ if (d->isLeftToRight()) {
+ if (child.item->x() != hoffset)
+ positionX(hoffset, child);
+ } else {
+ hoffsets << hoffset;
+ }
+ if (child.item->y() != voffset)
+ positionY(voffset, child);
+
+ contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width()));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height()));
+
+ if (d->flow == LeftToRight) {
+ hoffset += child.item->width();
+ hoffset += spacing();
+ linemax = qMax(linemax, qCeil(child.item->height()));
+ } else {
+ voffset += child.item->height();
+ voffset += spacing();
+ linemax = qMax(linemax, qCeil(child.item->width()));
+ }
+ }
+ if (d->isLeftToRight())
+ return;
+
+ int end;
+ if (widthValid())
+ end = width();
+ else
+ end = contentSize->width();
+ int acc = 0;
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || !child.isVisible)
+ continue;
+ hoffset = end - hoffsets[acc++] - child.item->width();
+ if (child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }
+}
+
+void QQuickFlow::reportConflictingAnchors()
+{
+ Q_D(QQuickFlow);
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors;
+ if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify anchors for items inside Flow";
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
new file mode 100644
index 0000000000..72c87a94b7
--- /dev/null
+++ b/src/quick/items/qquickpositioners_p.h
@@ -0,0 +1,293 @@
+// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKPOSITIONERS_P_H
+#define QQUICKPOSITIONERS_P_H
+
+#include "qquickimplicitsizeitem_p.h"
+
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qpodvector_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickBasePositionerPrivate;
+
+class QQuickPositionerAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickPositionerAttached(QObject *parent);
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ Q_PROPERTY(bool isFirstItem READ isFirstItem NOTIFY isFirstItemChanged)
+ Q_PROPERTY(bool isLastItem READ isLastItem NOTIFY isLastItemChanged)
+
+ int index() const { return m_index; }
+ void setIndex(int index);
+
+ bool isFirstItem() const { return m_isFirstItem; }
+ void setIsFirstItem(bool isFirstItem);
+
+ bool isLastItem() const { return m_isLastItem; }
+ void setIsLastItem(bool isLastItem);
+
+Q_SIGNALS:
+ void indexChanged();
+ void isFirstItemChanged();
+ void isLastItemChanged();
+
+private:
+ int m_index;
+ bool m_isFirstItem;
+ bool m_isLastItem;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(QDeclarativeTransition *move READ move WRITE setMove NOTIFY moveChanged)
+ Q_PROPERTY(QDeclarativeTransition *add READ add WRITE setAdd NOTIFY addChanged)
+public:
+ enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
+ QQuickBasePositioner(PositionerType, QQuickItem *parent);
+ ~QQuickBasePositioner();
+
+ int spacing() const;
+ void setSpacing(int);
+
+ QDeclarativeTransition *move() const;
+ void setMove(QDeclarativeTransition *);
+
+ QDeclarativeTransition *add() const;
+ void setAdd(QDeclarativeTransition *);
+
+ static QQuickPositionerAttached *qmlAttachedProperties(QObject *obj);
+
+ void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const;
+
+protected:
+ QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent);
+ virtual void componentComplete();
+ virtual void itemChange(ItemChange, const ItemChangeData &);
+ void finishApplyTransitions();
+
+ virtual void updatePolish();
+
+Q_SIGNALS:
+ void spacingChanged();
+ void moveChanged();
+ void addChanged();
+
+protected Q_SLOTS:
+ void prePositioning();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize)=0;
+ virtual void reportConflictingAnchors()=0;
+ class PositionedItem {
+ public :
+ PositionedItem(QQuickItem *i) : item(i), isNew(false), isVisible(true) {}
+ bool operator==(const PositionedItem &other) const { return other.item == item; }
+ QQuickItem *item;
+ bool isNew;
+ bool isVisible;
+ };
+
+ QPODVector<PositionedItem,8> positionedItems;
+ void positionX(int,const PositionedItem &target);
+ void positionY(int,const PositionedItem &target);
+
+private:
+ Q_DISABLE_COPY(QQuickBasePositioner)
+ Q_DECLARE_PRIVATE(QQuickBasePositioner)
+};
+
+class Q_AUTOTEST_EXPORT QQuickColumn : public QQuickBasePositioner
+{
+ Q_OBJECT
+public:
+ QQuickColumn(QQuickItem *parent=0);
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+private:
+ Q_DISABLE_COPY(QQuickColumn)
+};
+
+class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+public:
+ QQuickRow(QQuickItem *parent=0);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+Q_SIGNALS:
+ void layoutDirectionChanged();
+ void effectiveLayoutDirectionChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+private:
+ Q_DISABLE_COPY(QQuickRow)
+};
+
+class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
+ Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
+ Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
+ Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+
+public:
+ QQuickGrid(QQuickItem *parent=0);
+
+ int rows() const {return m_rows;}
+ void setRows(const int rows);
+
+ int columns() const {return m_columns;}
+ void setColumns(const int columns);
+
+ int rowSpacing() const { return m_rowSpacing; }
+ void setRowSpacing(int);
+
+ int columnSpacing() const { return m_columnSpacing; }
+ void setColumnSpacing(int);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+Q_SIGNALS:
+ void rowsChanged();
+ void columnsChanged();
+ void flowChanged();
+ void layoutDirectionChanged();
+ void effectiveLayoutDirectionChanged();
+ void rowSpacingChanged();
+ void columnSpacingChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+
+private:
+ int m_rows;
+ int m_columns;
+ int m_rowSpacing;
+ int m_columnSpacing;
+ Flow m_flow;
+ Q_DISABLE_COPY(QQuickGrid)
+};
+
+class QQuickFlowPrivate;
+class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+public:
+ QQuickFlow(QQuickItem *parent=0);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+Q_SIGNALS:
+ void flowChanged();
+ void layoutDirectionChanged();
+ void effectiveLayoutDirectionChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+protected:
+ QQuickFlow(QQuickFlowPrivate &dd, QQuickItem *parent);
+private:
+ Q_DISABLE_COPY(QQuickFlow)
+ Q_DECLARE_PRIVATE(QQuickFlow)
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickColumn)
+QML_DECLARE_TYPE(QQuickRow)
+QML_DECLARE_TYPE(QQuickGrid)
+QML_DECLARE_TYPE(QQuickFlow)
+
+QML_DECLARE_TYPE(QQuickBasePositioner)
+QML_DECLARE_TYPEINFO(QQuickBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QQUICKPOSITIONERS_P_H
diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h
new file mode 100644
index 0000000000..e7a5f8b473
--- /dev/null
+++ b/src/quick/items/qquickpositioners_p_p.h
@@ -0,0 +1,164 @@
+// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKPOSITIONERS_P_P_H
+#define QQUICKPOSITIONERS_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickpositioners_p.h"
+#include "qquickimplicitsizeitem_p_p.h"
+
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qdeclarativetransitionmanager_p_p.h>
+#include <private/qdeclarativestateoperations_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickBasePositioner)
+
+public:
+ QQuickBasePositionerPrivate()
+ : spacing(0), type(QQuickBasePositioner::None)
+ , moveTransition(0), addTransition(0), positioningDirty(false)
+ , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
+ {
+ }
+
+ void init(QQuickBasePositioner::PositionerType at)
+ {
+ type = at;
+ childrenDoNotOverlap = true;
+ }
+
+ int spacing;
+
+ QQuickBasePositioner::PositionerType type;
+ QDeclarativeTransition *moveTransition;
+ QDeclarativeTransition *addTransition;
+ QDeclarativeStateOperation::ActionList addActions;
+ QDeclarativeStateOperation::ActionList moveActions;
+ QDeclarativeTransitionManager addTransitionManager;
+ QDeclarativeTransitionManager moveTransitionManager;
+
+ void watchChanges(QQuickItem *other);
+ void unwatchChanges(QQuickItem* other);
+ void setPositioningDirty() {
+ Q_Q(QQuickBasePositioner);
+ if (!positioningDirty) {
+ positioningDirty = true;
+ q->polish();
+ }
+ }
+
+ bool positioningDirty : 1;
+ bool doingPositioning : 1;
+ bool anchorConflict : 1;
+
+ Qt::LayoutDirection layoutDirection;
+
+ void mirrorChange() {
+ if (type != QQuickBasePositioner::Vertical)
+ setPositioningDirty();
+ }
+ bool isLeftToRight() const {
+ if (type == QQuickBasePositioner::Vertical)
+ return true;
+ else
+ return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight;
+ }
+
+ virtual void itemSiblingOrderChanged(QQuickItem* other)
+ {
+ Q_UNUSED(other);
+ setPositioningDirty();
+ }
+
+ void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+ {
+ if (newGeometry.size() != oldGeometry.size())
+ setPositioningDirty();
+ }
+
+ virtual void itemVisibilityChanged(QQuickItem *)
+ {
+ setPositioningDirty();
+ }
+
+ void itemDestroyed(QQuickItem *item)
+ {
+ Q_Q(QQuickBasePositioner);
+ q->positionedItems.removeOne(QQuickBasePositioner::PositionedItem(item));
+ }
+
+ static Qt::LayoutDirection getLayoutDirection(const QQuickBasePositioner *positioner)
+ {
+ return positioner->d_func()->layoutDirection;
+ }
+
+ static Qt::LayoutDirection getEffectiveLayoutDirection(const QQuickBasePositioner *positioner)
+ {
+ if (positioner->d_func()->effectiveLayoutMirror)
+ return positioner->d_func()->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+ else
+ return positioner->d_func()->layoutDirection;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOSITIONERS_P_P_H
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
new file mode 100644
index 0000000000..388815941a
--- /dev/null
+++ b/src/quick/items/qquickrectangle.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickrectangle_p.h"
+#include "qquickrectangle_p_p.h"
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+#include <QtGui/qpixmapcache.h>
+#include <QtCore/qstringbuilder.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+// XXX todo - should we change rectangle to draw entirely within its width/height?
+/*!
+ \internal
+ \class QQuickPen
+ \brief The QQuickPen class provides a pen used for drawing rectangle borders on a QQuickView.
+
+ By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
+ width is 1) or a width (then the default color is black).
+
+ A width of 1 indicates is a single-pixel line on the border of the item being painted.
+
+ Example:
+ \qml
+ Rectangle {
+ border.width: 2
+ border.color: "red"
+ }
+ \endqml
+*/
+
+QQuickPen::QQuickPen(QObject *parent)
+ : QObject(parent)
+ , m_width(1)
+ , m_color("#000000")
+ , m_aligned(true)
+ , m_valid(false)
+{
+}
+
+qreal QQuickPen::width() const
+{
+ return m_width;
+}
+
+void QQuickPen::setWidth(qreal w)
+{
+ if (m_width == w && m_valid)
+ return;
+
+ m_width = w;
+ m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ emit penChanged();
+}
+
+QColor QQuickPen::color() const
+{
+ return m_color;
+}
+
+void QQuickPen::setColor(const QColor &c)
+{
+ m_color = c;
+ m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ emit penChanged();
+}
+
+bool QQuickPen::aligned() const
+{
+ return m_aligned;
+}
+
+void QQuickPen::setAligned(bool aligned)
+{
+ if (aligned == m_aligned)
+ return;
+ m_aligned = aligned;
+ m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
+ emit penChanged();
+}
+
+bool QQuickPen::isValid() const
+{
+ return m_valid;
+}
+
+/*!
+ \qmlclass GradientStop QQuickGradientStop
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The GradientStop item defines the color at a position in a Gradient.
+
+ \sa Gradient
+*/
+
+/*!
+ \qmlproperty real QtQuick2::GradientStop::position
+ \qmlproperty color QtQuick2::GradientStop::color
+
+ The position and color properties describe the color used at a given
+ position in a gradient, as represented by a gradient stop.
+
+ The default position is 0.0; the default color is black.
+
+ \sa Gradient
+*/
+QQuickGradientStop::QQuickGradientStop(QObject *parent)
+ : QObject(parent)
+{
+}
+
+qreal QQuickGradientStop::position() const
+{
+ return m_position;
+}
+
+void QQuickGradientStop::setPosition(qreal position)
+{
+ m_position = position; updateGradient();
+}
+
+QColor QQuickGradientStop::color() const
+{
+ return m_color;
+}
+
+void QQuickGradientStop::setColor(const QColor &color)
+{
+ m_color = color; updateGradient();
+}
+
+void QQuickGradientStop::updateGradient()
+{
+ if (QQuickGradient *grad = qobject_cast<QQuickGradient*>(parent()))
+ grad->doUpdate();
+}
+
+/*!
+ \qmlclass Gradient QQuickGradient
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Gradient item defines a gradient fill.
+
+ A gradient is defined by two or more colors, which will be blended seamlessly.
+
+ The colors are specified as a set of GradientStop child items, each of
+ which defines a position on the gradient from 0.0 to 1.0 and a color.
+ The position of each GradientStop is defined by setting its
+ \l{GradientStop::}{position} property; its color is defined using its
+ \l{GradientStop::}{color} property.
+
+ A gradient without any gradient stops is rendered as a solid white fill.
+
+ Note that this item is not a visual representation of a gradient. To display a
+ gradient, use a visual element (like \l Rectangle) which supports the use
+ of gradients.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage qml-gradient.png
+ \enddiv
+
+ The following example declares a \l Rectangle item with a gradient starting
+ with red, blending to yellow at one third of the height of the rectangle,
+ and ending with green:
+
+ \snippet doc/src/snippets/declarative/gradient.qml code
+
+ \clearfloat
+ \section1 Performance and Limitations
+
+ Calculating gradients can be computationally expensive compared to the use
+ of solid color fills or images. Consider using gradients for static items
+ in a user interface.
+
+ In Qt 4.7, only vertical, linear gradients can be applied to items. If you
+ need to apply different orientations of gradients, a combination of rotation
+ and clipping will need to be applied to the relevant items. This can
+ introduce additional performance requirements for your application.
+
+ The use of animations involving gradient stops may not give the desired
+ result. An alternative way to animate gradients is to use pre-generated
+ images or SVG drawings containing gradients.
+
+ \sa GradientStop
+*/
+
+/*!
+ \qmlproperty list<GradientStop> QtQuick2::Gradient::stops
+ \default
+
+ This property holds the gradient stops describing the gradient.
+
+ By default, this property contains an empty list.
+
+ To set the gradient stops, define them as children of the Gradient element.
+*/
+QQuickGradient::QQuickGradient(QObject *parent)
+: QObject(parent), m_gradient(0)
+{
+}
+
+QQuickGradient::~QQuickGradient()
+{
+ delete m_gradient;
+}
+
+QDeclarativeListProperty<QQuickGradientStop> QQuickGradient::stops()
+{
+ return QDeclarativeListProperty<QQuickGradientStop>(this, m_stops);
+}
+
+const QGradient *QQuickGradient::gradient() const
+{
+ if (!m_gradient && !m_stops.isEmpty()) {
+ m_gradient = new QLinearGradient(0,0,0,1.0);
+ for (int i = 0; i < m_stops.count(); ++i) {
+ const QQuickGradientStop *stop = m_stops.at(i);
+ m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_gradient->setColorAt(stop->position(), stop->color());
+ }
+ }
+
+ return m_gradient;
+}
+
+void QQuickGradient::doUpdate()
+{
+ delete m_gradient;
+ m_gradient = 0;
+ emit updated();
+}
+
+int QQuickRectanglePrivate::doUpdateSlotIdx = -1;
+
+/*!
+ \qmlclass Rectangle QQuickRectangle
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Rectangle item provides a filled rectangle with an optional border.
+ \inherits Item
+
+ Rectangle items are used to fill areas with solid color or gradients, and are
+ often used to hold other items.
+
+ \section1 Appearance
+
+ Each Rectangle item is painted using either a solid fill color, specified using
+ the \l color property, or a gradient, defined using a Gradient element and set
+ using the \l gradient property. If both a color and a gradient are specified,
+ the gradient is used.
+
+ You can add an optional border to a rectangle with its own color and thickness
+ by setting the \l border.color and \l border.width properties.
+
+ You can also create rounded rectangles using the \l radius property. Since this
+ introduces curved edges to the corners of a rectangle, it may be appropriate to
+ set the \l smooth property to improve its appearance.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage declarative-rect.png
+ \enddiv
+
+ The following example shows the effects of some of the common properties on a
+ Rectangle item, which in this case is used to create a square:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle.qml document
+
+ \clearfloat
+ \section1 Performance
+
+ Using the \l smooth property improves the appearance of a rounded rectangle at
+ the cost of rendering performance. You should consider unsetting this property
+ for rectangles in motion, and only set it when they are stationary.
+
+ \sa Image
+*/
+
+QQuickRectangle::QQuickRectangle(QQuickItem *parent)
+: QQuickItem(*(new QQuickRectanglePrivate), parent)
+{
+ setFlag(ItemHasContents);
+}
+
+void QQuickRectangle::doUpdate()
+{
+ Q_D(QQuickRectangle);
+ qreal penMargin = 0;
+ qreal penOffset = 0;
+ if (d->pen && d->pen->isValid()) {
+ if (d->pen->aligned()) {
+ const int pw = qRound(d->pen->width());
+ penMargin = qreal(0.5) * pw;
+ penOffset = (pw & 1) * qreal(0.5);
+ } else {
+ penMargin = qreal(0.5) * d->pen->width();
+ }
+ }
+ if (penMargin != d->penMargin || penOffset != d->penOffset) {
+ d->penMargin = penMargin;
+ d->penOffset = penOffset;
+ d->dirty(QQuickItemPrivate::Size); // update clip
+ }
+ update();
+}
+
+/*!
+ \qmlproperty int QtQuick2::Rectangle::border.width
+ \qmlproperty color QtQuick2::Rectangle::border.color
+
+ The width and color used to draw the border of the rectangle.
+
+ A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
+
+ \note The width of the rectangle's border does not affect the geometry of the
+ rectangle itself or its position relative to other items if anchors are used.
+
+ If \c border.width is an odd number, the rectangle is painted at a half-pixel offset to retain
+ border smoothness. Also, the border is rendered evenly on either side of the
+ rectangle's boundaries, and the spare pixel is rendered to the right and below the
+ rectangle (as documented for QRect rendering). This can cause unintended effects if
+ \c border.width is 1 and the rectangle is \l{Item::clip}{clipped} by a parent item:
+
+ \div {class="float-right"}
+ \inlineimage rect-border-width.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0
+
+ \clearfloat
+ Here, the innermost rectangle's border is clipped on the bottom and right edges by its
+ parent. To avoid this, the border width can be set to two instead of one.
+*/
+QQuickPen *QQuickRectangle::border()
+{
+ Q_D(QQuickRectangle);
+ return d->getPen();
+}
+
+/*!
+ \qmlproperty Gradient QtQuick2::Rectangle::gradient
+
+ The gradient to use to fill the rectangle.
+
+ This property allows for the construction of simple vertical gradients.
+ Other gradients may by formed by adding rotation to the rectangle.
+
+ \div {class="float-left"}
+ \inlineimage declarative-rect_gradient.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles
+ \clearfloat
+
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa Gradient, color
+*/
+QQuickGradient *QQuickRectangle::gradient() const
+{
+ Q_D(const QQuickRectangle);
+ return d->gradient;
+}
+
+void QQuickRectangle::setGradient(QQuickGradient *gradient)
+{
+ Q_D(QQuickRectangle);
+ if (d->gradient == gradient)
+ return;
+ static int updatedSignalIdx = -1;
+ if (updatedSignalIdx < 0)
+ updatedSignalIdx = QQuickGradient::staticMetaObject.indexOfSignal("updated()");
+ if (d->doUpdateSlotIdx < 0)
+ d->doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
+ if (d->gradient)
+ QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ d->gradient = gradient;
+ if (d->gradient)
+ QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ update();
+}
+
+/*!
+ \qmlproperty real QtQuick2::Rectangle::radius
+ This property holds the corner radius used to draw a rounded rectangle.
+
+ If radius is non-zero, the rectangle will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
+qreal QQuickRectangle::radius() const
+{
+ Q_D(const QQuickRectangle);
+ return d->radius;
+}
+
+void QQuickRectangle::setRadius(qreal radius)
+{
+ Q_D(QQuickRectangle);
+ if (d->radius == radius)
+ return;
+
+ d->radius = radius;
+ update();
+ emit radiusChanged();
+}
+
+/*!
+ \qmlproperty color QtQuick2::Rectangle::color
+ This property holds the color used to fill the rectangle.
+
+ The default color is white.
+
+ \div {class="float-right"}
+ \inlineimage rect-color.png
+ \enddiv
+
+ The following example shows rectangles with colors specified
+ using hexadecimal and named color notation:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-colors.qml rectangles
+
+ \clearfloat
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa gradient
+*/
+QColor QQuickRectangle::color() const
+{
+ Q_D(const QQuickRectangle);
+ return d->color;
+}
+
+void QQuickRectangle::setColor(const QColor &c)
+{
+ Q_D(QQuickRectangle);
+ if (d->color == c)
+ return;
+
+ d->color = c;
+ update();
+ emit colorChanged();
+}
+
+QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ Q_D(QQuickRectangle);
+
+ if (width() <= 0 || height() <= 0
+ || (d->color.alpha() == 0 && (!d->pen || d->pen->width() == 0 || d->pen->color().alpha() == 0))) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGRectangleNode *rectangle = static_cast<QSGRectangleNode *>(oldNode);
+ if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode();
+
+ rectangle->setRect(QRectF(0, 0, width(), height()));
+ rectangle->setColor(d->color);
+
+ if (d->pen && d->pen->isValid()) {
+ rectangle->setPenColor(d->pen->color());
+ rectangle->setPenWidth(d->pen->width());
+ rectangle->setAligned(d->pen->aligned());
+ } else {
+ rectangle->setPenWidth(0);
+ }
+
+ rectangle->setRadius(d->radius);
+
+ QGradientStops stops;
+ if (d->gradient) {
+ QList<QQuickGradientStop *> qxstops = d->gradient->m_stops;
+ for (int i = 0; i < qxstops.size(); ++i){
+ int j = 0;
+ while (j < stops.size() && stops.at(j).first < qxstops[i]->position())
+ j++;
+ stops.insert(j, QGradientStop(qxstops.at(i)->position(), qxstops.at(i)->color()));
+ }
+ }
+ rectangle->setGradientStops(stops);
+
+ rectangle->update();
+
+ return rectangle;
+}
+/*!
+ \qmlproperty bool QtQuick2::Rectangle::smooth
+
+ Set this property if you want the item to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+
+ \image rect-smooth.png
+ On this image, smooth is turned off for the top half and on for the bottom half.
+*/
+
+QRectF QQuickRectangle::boundingRect() const
+{
+ Q_D(const QQuickRectangle);
+ return QRectF(d->penOffset - d->penMargin, d->penOffset - d->penMargin,
+ d->width + 2 * d->penMargin, d->height + 2 * d->penMargin);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
new file mode 100644
index 0000000000..540eb33739
--- /dev/null
+++ b/src/quick/items/qquickrectangle_p.h
@@ -0,0 +1,188 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKRECTANGLE_P_H
+#define QQUICKRECTANGLE_P_H
+
+#include "qquickitem.h"
+
+#include <QtGui/qbrush.h>
+
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY penChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged)
+ Q_PROPERTY(bool aligned READ aligned WRITE setAligned NOTIFY penChanged)
+public:
+ QQuickPen(QObject *parent=0);
+
+ qreal width() const;
+ void setWidth(qreal w);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ bool aligned() const;
+ void setAligned(bool aligned);
+
+ bool isValid() const;
+
+Q_SIGNALS:
+ void penChanged();
+
+private:
+ qreal m_width;
+ QColor m_color;
+ bool m_aligned : 1;
+ bool m_valid : 1;
+};
+
+class Q_AUTOTEST_EXPORT QQuickGradientStop : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal position READ position WRITE setPosition)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+
+public:
+ QQuickGradientStop(QObject *parent=0);
+
+ qreal position() const;
+ void setPosition(qreal position);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+private:
+ void updateGradient();
+
+private:
+ qreal m_position;
+ QColor m_color;
+};
+
+class Q_AUTOTEST_EXPORT QQuickGradient : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeListProperty<QQuickGradientStop> stops READ stops)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ QQuickGradient(QObject *parent=0);
+ ~QQuickGradient();
+
+ QDeclarativeListProperty<QQuickGradientStop> stops();
+
+ const QGradient *gradient() const;
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ void doUpdate();
+
+private:
+ QList<QQuickGradientStop *> m_stops;
+ mutable QGradient *m_gradient;
+ friend class QQuickRectangle;
+ friend class QQuickGradientStop;
+};
+
+class QQuickRectanglePrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QQuickGradient *gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(QQuickPen * border READ border CONSTANT)
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+public:
+ QQuickRectangle(QQuickItem *parent=0);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QQuickPen *border();
+
+ QQuickGradient *gradient() const;
+ void setGradient(QQuickGradient *gradient);
+
+ qreal radius() const;
+ void setRadius(qreal radius);
+
+ virtual QRectF boundingRect() const;
+
+Q_SIGNALS:
+ void colorChanged();
+ void radiusChanged();
+
+protected:
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+private Q_SLOTS:
+ void doUpdate();
+
+private:
+ Q_DISABLE_COPY(QQuickRectangle)
+ Q_DECLARE_PRIVATE(QQuickRectangle)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickPen)
+QML_DECLARE_TYPE(QQuickGradientStop)
+QML_DECLARE_TYPE(QQuickGradient)
+QML_DECLARE_TYPE(QQuickRectangle)
+
+QT_END_HEADER
+
+#endif // QQUICKRECTANGLE_P_H
diff --git a/src/declarative/items/qquickrectangle_p_p.h b/src/quick/items/qquickrectangle_p_p.h
index 93140ce75a..93140ce75a 100644
--- a/src/declarative/items/qquickrectangle_p_p.h
+++ b/src/quick/items/qquickrectangle_p_p.h
diff --git a/src/declarative/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index efa83eec38..efa83eec38 100644
--- a/src/declarative/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h
new file mode 100644
index 0000000000..19beaec422
--- /dev/null
+++ b/src/quick/items/qquickrepeater_p.h
@@ -0,0 +1,110 @@
+// Commit: ebd4bc73c46c2962742a682b6a391fb68c482aec
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKREPEATER_P_H
+#define QQUICKREPEATER_P_H
+
+#include "qquickitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeChangeSet;
+
+class QQuickRepeaterPrivate;
+class Q_AUTOTEST_EXPORT QQuickRepeater : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+
+public:
+ QQuickRepeater(QQuickItem *parent=0);
+ virtual ~QQuickRepeater();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int count() const;
+
+ Q_INVOKABLE QQuickItem *itemAt(int index) const;
+
+Q_SIGNALS:
+ void modelChanged();
+ void delegateChanged();
+ void countChanged();
+
+ void itemAdded(int index, QQuickItem *item);
+ void itemRemoved(int index, QQuickItem *item);
+
+private:
+ void clear();
+ void regenerate();
+
+protected:
+ virtual void componentComplete();
+ void itemChange(ItemChange change, const ItemChangeData &value);
+
+private Q_SLOTS:
+ void createdItem(int index, QQuickItem *item);
+ void initItem(int, QQuickItem *item);
+ void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+
+private:
+ Q_DISABLE_COPY(QQuickRepeater)
+ Q_DECLARE_PRIVATE(QQuickRepeater)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickRepeater)
+
+QT_END_HEADER
+
+#endif // QQUICKREPEATER_P_H
diff --git a/src/declarative/items/qquickrepeater_p_p.h b/src/quick/items/qquickrepeater_p_p.h
index 962d177494..962d177494 100644
--- a/src/declarative/items/qquickrepeater_p_p.h
+++ b/src/quick/items/qquickrepeater_p_p.h
diff --git a/src/declarative/items/qquickscalegrid.cpp b/src/quick/items/qquickscalegrid.cpp
index 9a8f652a9b..9a8f652a9b 100644
--- a/src/declarative/items/qquickscalegrid.cpp
+++ b/src/quick/items/qquickscalegrid.cpp
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
new file mode 100644
index 0000000000..2ce45f7347
--- /dev/null
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -0,0 +1,132 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKSCALEGRID_P_P_H
+#define QQUICKSCALEGRID_P_P_H
+
+#include "qquickborderimage_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtCore/qobject.h>
+
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickScaleGrid : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(TileRule)
+
+ Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
+ Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
+ Q_PROPERTY(int right READ right WRITE setRight NOTIFY borderChanged)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY borderChanged)
+
+public:
+ QQuickScaleGrid(QObject *parent=0);
+ ~QQuickScaleGrid();
+
+ bool isNull() const;
+
+ int left() const { return _left; }
+ void setLeft(int);
+
+ int top() const { return _top; }
+ void setTop(int);
+
+ int right() const { return _right; }
+ void setRight(int);
+
+ int bottom() const { return _bottom; }
+ void setBottom(int);
+
+Q_SIGNALS:
+ void borderChanged();
+
+private:
+ int _left;
+ int _top;
+ int _right;
+ int _bottom;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickGridScaledImage
+{
+public:
+ QQuickGridScaledImage();
+ QQuickGridScaledImage(const QQuickGridScaledImage &);
+ QQuickGridScaledImage(QIODevice*);
+ QQuickGridScaledImage &operator=(const QQuickGridScaledImage &);
+ bool isValid() const;
+ int gridLeft() const;
+ int gridRight() const;
+ int gridTop() const;
+ int gridBottom() const;
+ QQuickBorderImage::TileMode horizontalTileRule() const { return _h; }
+ QQuickBorderImage::TileMode verticalTileRule() const { return _v; }
+
+ QString pixmapUrl() const;
+
+private:
+ static QQuickBorderImage::TileMode stringToRule(const QString &);
+
+private:
+ int _l;
+ int _r;
+ int _t;
+ int _b;
+ QQuickBorderImage::TileMode _h;
+ QQuickBorderImage::TileMode _v;
+ QString _pix;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickScaleGrid)
+
+QT_END_HEADER
+
+#endif // QQUICKSCALEGRID_P_P_H
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
new file mode 100644
index 0000000000..7572a0cf0d
--- /dev/null
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -0,0 +1,763 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <private/qquickshadereffect_p.h>
+#include <private/qquickshadereffectnode_p.h>
+
+#include <QtQuick/qsgmaterial.h>
+#include "qquickitem_p.h"
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <QtQuick/private/qsgtextureprovider_p.h>
+#include "qquickcanvas.h"
+
+#include "qquickimage_p.h"
+#include "qquickshadereffectsource_p.h"
+
+#include <QtCore/qsignalmapper.h>
+#include <QtGui/qopenglframebufferobject.h>
+
+QT_BEGIN_NAMESPACE
+
+static const char qt_default_vertex_code[] =
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_Vertex; \n"
+ "attribute highp vec2 qt_MultiTexCoord0; \n"
+ "varying highp vec2 qt_TexCoord0; \n"
+ "void main() { \n"
+ " qt_TexCoord0 = qt_MultiTexCoord0; \n"
+ " gl_Position = qt_Matrix * qt_Vertex; \n"
+ "}";
+
+static const char qt_default_fragment_code[] =
+ "varying highp vec2 qt_TexCoord0; \n"
+ "uniform sampler2D source; \n"
+ "uniform lowp float qt_Opacity; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
+ "}";
+
+static const char qt_position_attribute_name[] = "qt_Vertex";
+static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
+
+const char *qtPositionAttributeName()
+{
+ return qt_position_attribute_name;
+}
+
+const char *qtTexCoordAttributeName()
+{
+ return qt_texcoord_attribute_name;
+}
+
+/*!
+ \qmlclass ShaderEffect QQuickShaderEffect
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The ShaderEffect element applies custom shaders to a rectangle.
+ \inherits Item
+
+ The ShaderEffect element applies a custom OpenGL
+ \l{vertexShader}{vertex} and \l{fragmentShader}{fragment} shader to a
+ rectangle. It allows you to write effects such as drop shadow, blur,
+ colorize and page curl directly in QML.
+
+ There are two types of input to the \l vertexShader:
+ uniform variables and attributes. Some are predefined:
+ \list
+ \o uniform mat4 qt_Matrix - combined transformation
+ matrix, the product of the matrices from the root item to this
+ ShaderEffect, and an orthogonal projection.
+ \o uniform float qt_Opacity - combined opacity, the product of the
+ opacities from the root item to this ShaderEffect.
+ \o attribute vec4 qt_Vertex - vertex position, the top-left vertex has
+ position (0, 0), the bottom-right (\l{Item::width}{width},
+ \l{Item::height}{height}).
+ \o attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left
+ coordinate is (0, 0), the bottom-right (1, 1).
+ \endlist
+
+ In addition, any property that can be mapped to an OpenGL Shading Language
+ (GLSL) type is available as a uniform variable. The following list shows
+ how properties are mapped to GLSL uniform variables:
+ \list
+ \o bool, int, qreal -> bool, int, float - If the type in the shader is not
+ the same as in QML, the value is converted automatically.
+ \o QColor -> vec4 - When colors are passed to the shader, they are first
+ premultiplied. Thus Qt.rgba(0.2, 0.6, 1.0, 0.5) becomes
+ vec4(0.1, 0.3, 0.5, 0.5) in the shader, for example.
+ \o QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in
+ the shader.
+ \o QPoint, QPointF, QSize, QSizeF -> vec2
+ \o QVector3D -> vec3
+ \o QTransform -> mat4
+ \o \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left
+ corner, and the color values are premultiplied.
+ \endlist
+
+ The output from the \l fragmentShader should be premultiplied. If
+ \l blending is enabled, source-over blending is used. However, additive
+ blending can be achieved by outputting zero in the alpha channel.
+
+ \row
+ \o \image declarative-shadereffectitem.png
+ \o \qml
+ import QtQuick 2.0
+
+ Rectangle {
+ width: 200; height: 100
+ Row {
+ Image { id: img; sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
+ ShaderEffect {
+ width: 100; height: 100
+ property variant src: img
+ vertexShader: "
+ uniform highp mat4 qt_Matrix;
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec2 qt_MultiTexCoord0;
+ varying highp vec2 coord;
+ void main() {
+ coord = qt_MultiTexCoord0;
+ gl_Position = qt_Matrix * qt_Vertex;
+ }"
+ fragmentShader: "
+ varying highp vec2 coord;
+ uniform sampler2D src;
+ uniform lowp float qt_Opacity;
+ void main() {
+ lowp vec4 tex = texture2D(src, coord);
+ gl_FragColor = vec4(vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156))), tex.a) * qt_Opacity;
+ }"
+ }
+ }
+ }
+ \endqml
+ \endrow
+
+ By default, the ShaderEffect consists of four vertices, one for each
+ corner. For non-linear vertex transformations, like page curl, you can
+ specify a fine grid of vertices by specifying a \l mesh resolution.
+
+ \note Scene Graph textures have origin in the top-left corner rather than
+ bottom-left which is common in OpenGL.
+*/
+
+QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_meshResolution(1, 1)
+ , m_mesh(0)
+ , m_cullMode(NoCulling)
+ , m_blending(true)
+ , m_dirtyData(true)
+ , m_programDirty(true)
+ , m_dirtyMesh(true)
+ , m_dirtyGeometry(true)
+{
+ setFlag(QQuickItem::ItemHasContents);
+}
+
+QQuickShaderEffect::~QQuickShaderEffect()
+{
+ reset();
+}
+
+void QQuickShaderEffect::componentComplete()
+{
+ updateProperties();
+ QQuickItem::componentComplete();
+}
+
+/*!
+ \qmlproperty string QtQuick2::ShaderEffect::fragmentShader
+
+ This property holds the fragment shader's GLSL source code.
+ The default shader passes the texture coordinate along to the fragment
+ shader as "varying highp vec2 qt_TexCoord0".
+*/
+
+void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
+{
+ if (m_source.fragmentCode.constData() == code.constData())
+ return;
+ m_source.fragmentCode = code;
+ if (isComponentComplete()) {
+ reset();
+ updateProperties();
+ update();
+ }
+ emit fragmentShaderChanged();
+}
+
+/*!
+ \qmlproperty string QtQuick2::ShaderEffect::vertexShader
+
+ This property holds the vertex shader's GLSL source code.
+ The default shader expects the texture coordinate to be passed from the
+ vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
+ sampler2D named "source".
+*/
+
+void QQuickShaderEffect::setVertexShader(const QByteArray &code)
+{
+ if (m_source.vertexCode.constData() == code.constData())
+ return;
+ m_source.vertexCode = code;
+ if (isComponentComplete()) {
+ reset();
+ updateProperties();
+ update();
+ }
+ emit vertexShaderChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::ShaderEffect::blending
+
+ If this property is true, the output from the \l fragmentShader is blended
+ with the background using source-over blend mode. If false, the background
+ is disregarded. Blending decreases the performance, so you should set this
+ property to false when blending is not needed. The default value is true.
+*/
+
+void QQuickShaderEffect::setBlending(bool enable)
+{
+ if (blending() == enable)
+ return;
+
+ m_blending = enable;
+ update();
+
+ emit blendingChanged();
+}
+
+/*!
+ \qmlproperty variant QtQuick2::ShaderEffect::mesh
+
+ This property defines the mesh used to draw the ShaderEffect. It can hold
+ any mesh object deriving from \l QQuickShaderEffectMesh, such as \l GridMesh.
+ If a size value is assigned to this property, the ShaderEffect implicitly
+ uses a \l GridMesh with the value as
+ \l{GridMesh::resolution}{mesh resolution}. By default, this property is
+ the size 1x1.
+
+ \sa GridMesh
+*/
+
+QVariant QQuickShaderEffect::mesh() const
+{
+ return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
+ : qVariantFromValue(m_meshResolution);
+}
+
+void QQuickShaderEffect::setMesh(const QVariant &mesh)
+{
+ QQuickShaderEffectMesh *newMesh = qobject_cast<QQuickShaderEffectMesh *>(qVariantValue<QObject *>(mesh));
+ if (newMesh && newMesh == m_mesh)
+ return;
+ if (m_mesh)
+ disconnect(m_mesh, SIGNAL(geometryChanged()), this, 0);
+ m_mesh = newMesh;
+ if (m_mesh) {
+ connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
+ } else {
+ if (qVariantCanConvert<QSize>(mesh)) {
+ m_meshResolution = mesh.toSize();
+ } else {
+ QList<QByteArray> res = mesh.toByteArray().split('x');
+ bool ok = res.size() == 2;
+ if (ok) {
+ int w = res.at(0).toInt(&ok);
+ if (ok) {
+ int h = res.at(1).toInt(&ok);
+ if (ok)
+ m_meshResolution = QSize(w, h);
+ }
+ }
+ if (!ok)
+ qWarning("ShaderEffect: mesh property must be size or object deriving from QQuickShaderEffectMesh.");
+ }
+ m_defaultMesh.setResolution(m_meshResolution);
+ }
+
+ m_dirtyMesh = true;
+ update();
+ emit meshChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::ShaderEffect::cullMode
+
+ This property defines which sides of the element should be visible.
+
+ \list
+ \o ShaderEffect.NoCulling - Both sides are visible
+ \o ShaderEffect.BackFaceCulling - only front side is visible
+ \o ShaderEffect.FrontFaceCulling - only back side is visible
+ \endlist
+
+ The default is NoCulling.
+*/
+
+void QQuickShaderEffect::setCullMode(CullMode face)
+{
+ if (face == m_cullMode)
+ return;
+ m_cullMode = face;
+ update();
+ emit cullModeChanged();
+}
+
+void QQuickShaderEffect::changeSource(int index)
+{
+ Q_ASSERT(index >= 0 && index < m_sources.size());
+ QVariant v = property(m_sources.at(index).name.constData());
+ setSource(v, index);
+}
+
+void QQuickShaderEffect::updateData()
+{
+ m_dirtyData = true;
+ update();
+}
+
+void QQuickShaderEffect::updateGeometry()
+{
+ m_dirtyGeometry = true;
+ update();
+}
+
+void QQuickShaderEffect::setSource(const QVariant &var, int index)
+{
+ Q_ASSERT(index >= 0 && index < m_sources.size());
+
+ SourceData &source = m_sources[index];
+
+ source.sourceObject = 0;
+ if (var.isNull()) {
+ return;
+ } else if (!qVariantCanConvert<QObject *>(var)) {
+ qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
+ return;
+ }
+
+ QObject *obj = qVariantValue<QObject *>(var);
+ QQuickItem *item = qobject_cast<QQuickItem *>(obj);
+ if (!item || !item->isTextureProvider()) {
+ qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
+ source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
+ return;
+ }
+
+ source.sourceObject = item;
+
+
+ // TODO: Find better solution.
+ // 'item' needs a canvas to get a scenegraph node.
+ // The easiest way to make sure it gets a canvas is to
+ // make it a part of the same item tree as 'this'.
+ if (item && item->parentItem() == 0) {
+ item->setParentItem(this);
+ item->setVisible(false);
+ }
+}
+
+void QQuickShaderEffect::disconnectPropertySignals()
+{
+ disconnect(this, 0, this, SLOT(updateData()));
+ for (int i = 0; i < m_sources.size(); ++i) {
+ SourceData &source = m_sources[i];
+ disconnect(this, 0, source.mapper, 0);
+ disconnect(source.mapper, 0, this, 0);
+ }
+}
+
+void QQuickShaderEffect::connectPropertySignals()
+{
+ QSet<QByteArray>::const_iterator it;
+ for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
+ int pi = metaObject()->indexOfProperty(it->constData());
+ if (pi >= 0) {
+ QMetaProperty mp = metaObject()->property(pi);
+ if (!mp.hasNotifySignal())
+ qWarning("QQuickShaderEffect: property '%s' does not have notification method!", it->constData());
+ QByteArray signalName("2");
+ signalName.append(mp.notifySignal().signature());
+ connect(this, signalName, this, SLOT(updateData()));
+ } else {
+ qWarning("QQuickShaderEffect: '%s' does not have a matching property!", it->constData());
+ }
+ }
+ for (int i = 0; i < m_sources.size(); ++i) {
+ SourceData &source = m_sources[i];
+ int pi = metaObject()->indexOfProperty(source.name.constData());
+ if (pi >= 0) {
+ QMetaProperty mp = metaObject()->property(pi);
+ QByteArray signalName("2");
+ signalName.append(mp.notifySignal().signature());
+ connect(this, signalName, source.mapper, SLOT(map()));
+ source.mapper->setMapping(this, i);
+ connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
+ } else {
+ qWarning("QQuickShaderEffect: '%s' does not have a matching source!", source.name.constData());
+ }
+ }
+}
+
+void QQuickShaderEffect::reset()
+{
+ disconnectPropertySignals();
+
+ m_source.attributeNames.clear();
+ m_source.uniformNames.clear();
+ m_source.respectsOpacity = false;
+ m_source.respectsMatrix = false;
+ m_source.className = metaObject()->className();
+
+ for (int i = 0; i < m_sources.size(); ++i) {
+ const SourceData &source = m_sources.at(i);
+ delete source.mapper;
+ QQuickItem *item = qobject_cast<QQuickItem *>(source.sourceObject);
+ if (item && item->parentItem() == this)
+ item->setParentItem(0);
+ }
+ m_sources.clear();
+
+ m_programDirty = true;
+ m_dirtyMesh = true;
+}
+
+void QQuickShaderEffect::updateProperties()
+{
+ if (m_source.vertexCode.isEmpty()) {
+ m_source.attributeNames.append(QByteArray(qt_position_attribute_name));
+ m_source.attributeNames.append(QByteArray(qt_texcoord_attribute_name));
+ m_source.respectsMatrix = true;
+ } else {
+ lookThroughShaderCode(m_source.vertexCode);
+ }
+ if (m_source.fragmentCode.isEmpty()) {
+ m_source.respectsOpacity = true;
+ QByteArray name("source");
+ m_source.uniformNames.insert(name);
+ SourceData d;
+ d.mapper = new QSignalMapper;
+ d.name = name;
+ d.sourceObject = 0;
+ m_sources.append(d);
+ } else {
+ lookThroughShaderCode(m_source.fragmentCode);
+ }
+
+ if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name))
+ qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_position_attribute_name);
+ if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
+ qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
+ if (!m_source.respectsMatrix)
+ qWarning("QQuickShaderEffect: Missing reference to \'qt_Matrix\'.");
+ if (!m_source.respectsOpacity)
+ qWarning("QQuickShaderEffect: Missing reference to \'qt_Opacity\'.");
+
+ for (int i = 0; i < m_sources.size(); ++i) {
+ QVariant v = property(m_sources.at(i).name);
+ setSource(v, i);
+ }
+
+ connectPropertySignals();
+}
+
+namespace {
+
+ enum VariableQualifier {
+ AttributeQualifier,
+ UniformQualifier
+ };
+
+ inline bool qt_isalpha(char c)
+ {
+ char ch = c | 0x20;
+ return (ch >= 'a' && ch <= 'z') || c == '_';
+ }
+
+ inline bool qt_isalnum(char c)
+ {
+ return qt_isalpha(c) || (c >= '0' && c <= '9');
+ }
+
+ inline bool qt_isspace(char c)
+ {
+ return c == ' ' || (c >= 0x09 && c <= 0x0d);
+ }
+
+ // Returns -1 if not found, returns index to first character after the name if found.
+ int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
+ int &typeIndex, int &typeLength,
+ int &nameIndex, int &nameLength)
+ {
+ enum Identifier {
+ QualifierIdentifier, // Base state
+ PrecisionIdentifier,
+ TypeIdentifier,
+ NameIdentifier
+ };
+ Identifier expected = QualifierIdentifier;
+ bool compilerDirectiveExpected = index == 0;
+
+ while (index < length) {
+ // Skip whitespace.
+ while (qt_isspace(s[index])) {
+ compilerDirectiveExpected |= s[index] == '\n';
+ ++index;
+ }
+
+ if (qt_isalpha(s[index])) {
+ // Read identifier.
+ int idIndex = index;
+ ++index;
+ while (qt_isalnum(s[index]))
+ ++index;
+ int idLength = index - idIndex;
+
+ const int attrLen = sizeof("attribute") - 1;
+ const int uniLen = sizeof("uniform") - 1;
+ const int loLen = sizeof("lowp") - 1;
+ const int medLen = sizeof("mediump") - 1;
+ const int hiLen = sizeof("highp") - 1;
+
+ switch (expected) {
+ case QualifierIdentifier:
+ if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
+ decl = AttributeQualifier;
+ expected = PrecisionIdentifier;
+ } else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
+ decl = UniformQualifier;
+ expected = PrecisionIdentifier;
+ }
+ break;
+ case PrecisionIdentifier:
+ if ((idLength == loLen && qstrncmp("lowp", s + idIndex, loLen) == 0)
+ || (idLength == medLen && qstrncmp("mediump", s + idIndex, medLen) == 0)
+ || (idLength == hiLen && qstrncmp("highp", s + idIndex, hiLen) == 0))
+ {
+ expected = TypeIdentifier;
+ break;
+ }
+ // Fall through.
+ case TypeIdentifier:
+ typeIndex = idIndex;
+ typeLength = idLength;
+ expected = NameIdentifier;
+ break;
+ case NameIdentifier:
+ nameIndex = idIndex;
+ nameLength = idLength;
+ return index; // Attribute or uniform declaration found. Return result.
+ default:
+ break;
+ }
+ } else if (s[index] == '#' && compilerDirectiveExpected) {
+ // Skip compiler directives.
+ ++index;
+ while (index < length && (s[index] != '\n' || s[index - 1] == '\\'))
+ ++index;
+ } else if (s[index] == '/' && s[index + 1] == '/') {
+ // Skip comments.
+ index += 2;
+ while (index < length && s[index] != '\n')
+ ++index;
+ } else if (s[index] == '/' && s[index + 1] == '*') {
+ // Skip comments.
+ index += 2;
+ while (index < length && (s[index] != '*' || s[index + 1] != '/'))
+ ++index;
+ if (index < length)
+ index += 2; // Skip star-slash.
+ } else {
+ expected = QualifierIdentifier;
+ ++index;
+ }
+ compilerDirectiveExpected = false;
+ }
+ return -1;
+ }
+}
+
+void QQuickShaderEffect::lookThroughShaderCode(const QByteArray &code)
+{
+ int index = 0;
+ int typeIndex, typeLength, nameIndex, nameLength;
+ const char *s = code.constData();
+ VariableQualifier decl;
+ while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
+ nameIndex, nameLength)) != -1)
+ {
+ if (decl == AttributeQualifier) {
+ m_source.attributeNames.append(QByteArray(s + nameIndex, nameLength));
+ } else {
+ Q_ASSERT(decl == UniformQualifier);
+
+ const int matLen = sizeof("qt_Matrix") - 1;
+ const int opLen = sizeof("qt_Opacity") - 1;
+ const int sampLen = sizeof("sampler2D") - 1;
+
+ if (nameLength == matLen && qstrncmp("qt_Matrix", s + nameIndex, matLen) == 0) {
+ m_source.respectsMatrix = true;
+ } else if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) {
+ m_source.respectsOpacity = true;
+ } else {
+ QByteArray name(s + nameIndex, nameLength);
+ m_source.uniformNames.insert(name);
+ if (typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0) {
+ SourceData d;
+ d.mapper = new QSignalMapper;
+ d.name = name;
+ d.sourceObject = 0;
+ m_sources.append(d);
+ }
+ }
+ }
+ }
+}
+
+void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ m_dirtyGeometry = true;
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ QQuickShaderEffectNode *node = static_cast<QQuickShaderEffectNode *>(oldNode);
+
+ // In the case of a bad vertex shader, don't try to create a node...
+ if (m_source.attributeNames.isEmpty()) {
+ if (node)
+ delete node;
+ return 0;
+ }
+
+ if (!node) {
+ node = new QQuickShaderEffectNode;
+ m_programDirty = true;
+ m_dirtyData = true;
+ m_dirtyGeometry = true;
+ }
+
+ QQuickShaderEffectMaterial *material = node->shaderMaterial();
+
+ if (m_dirtyMesh) {
+ node->setGeometry(0);
+ m_dirtyMesh = false;
+ m_dirtyGeometry = true;
+ }
+
+ if (m_dirtyGeometry) {
+ node->setFlag(QSGNode::OwnsGeometry, false);
+ QSGGeometry *geometry = node->geometry();
+ QRectF rect(0, 0, width(), height());
+ QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
+
+ geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
+ if (!geometry) {
+ delete node;
+ return 0;
+ }
+
+ node->setGeometry(geometry);
+ node->setFlag(QSGNode::OwnsGeometry, true);
+
+ m_dirtyGeometry = false;
+ }
+
+ if (m_programDirty) {
+ QQuickShaderEffectProgram s = m_source;
+ if (s.fragmentCode.isEmpty())
+ s.fragmentCode = qt_default_fragment_code;
+ if (s.vertexCode.isEmpty())
+ s.vertexCode = qt_default_vertex_code;
+ s.className = metaObject()->className();
+
+ material->setProgramSource(s);
+ node->markDirty(QSGNode::DirtyMaterial);
+ m_programDirty = false;
+ }
+
+ // Update blending
+ if (bool(material->flags() & QSGMaterial::Blending) != m_blending) {
+ material->setFlag(QSGMaterial::Blending, m_blending);
+ node->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ if (int(material->cullMode()) != int(m_cullMode)) {
+ material->setCullMode(QQuickShaderEffectMaterial::CullMode(m_cullMode));
+ node->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ if (m_dirtyData) {
+ QVector<QPair<QByteArray, QVariant> > values;
+ QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = material->textureProviders();
+
+ for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
+ it != m_source.uniformNames.end(); ++it) {
+ values.append(qMakePair(*it, property(*it)));
+ }
+ for (int i = 0; i < oldTextures.size(); ++i) {
+ QSGTextureProvider *t = oldTextures.at(i).second;
+ if (t)
+ disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ }
+ 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);
+ }
+ material->setUniforms(values);
+ material->setTextureProviders(textures);
+ node->markDirty(QSGNode::DirtyMaterial);
+ m_dirtyData = false;
+ }
+
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
new file mode 100644
index 0000000000..97444fb2f5
--- /dev/null
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKSHADEREFFECT_P_H
+#define QQUICKSHADEREFFECT_P_H
+
+#include <QtQuick/qquickitem.h>
+
+#include <QtQuick/qsgmaterial.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <private/qquickshadereffectnode_p.h>
+#include "qquickshadereffectmesh_p.h"
+
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+const char *qtPositionAttributeName();
+const char *qtTexCoordAttributeName();
+
+class QSGContext;
+class QSignalMapper;
+class QQuickCustomMaterialShader;
+
+class Q_AUTOTEST_EXPORT QQuickShaderEffect : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
+ Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
+ Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY blendingChanged)
+ Q_PROPERTY(QVariant mesh READ mesh WRITE setMesh NOTIFY meshChanged)
+ Q_PROPERTY(CullMode culling READ cullMode WRITE setCullMode NOTIFY cullModeChanged)
+ Q_ENUMS(CullMode)
+
+public:
+ enum CullMode
+ {
+ NoCulling = QQuickShaderEffectMaterial::NoCulling,
+ BackFaceCulling = QQuickShaderEffectMaterial::BackFaceCulling,
+ FrontFaceCulling = QQuickShaderEffectMaterial::FrontFaceCulling
+ };
+
+ QQuickShaderEffect(QQuickItem *parent = 0);
+ ~QQuickShaderEffect();
+
+ virtual void componentComplete();
+
+ QByteArray fragmentShader() const { return m_source.fragmentCode; }
+ void setFragmentShader(const QByteArray &code);
+
+ QByteArray vertexShader() const { return m_source.vertexCode; }
+ void setVertexShader(const QByteArray &code);
+
+ bool blending() const { return m_blending; }
+ void setBlending(bool enable);
+
+ QVariant mesh() const;
+ void setMesh(const QVariant &mesh);
+
+ CullMode cullMode() const { return m_cullMode; }
+ void setCullMode(CullMode face);
+
+Q_SIGNALS:
+ void fragmentShaderChanged();
+ void vertexShaderChanged();
+ void blendingChanged();
+ void meshChanged();
+ void cullModeChanged();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+private Q_SLOTS:
+ void changeSource(int index);
+ void updateData();
+ void updateGeometry();
+
+private:
+ friend class QQuickCustomMaterialShader;
+ friend class QQuickShaderEffectNode;
+
+ void setSource(const QVariant &var, int index);
+ void disconnectPropertySignals();
+ void connectPropertySignals();
+ void reset();
+ void updateProperties();
+ void lookThroughShaderCode(const QByteArray &code);
+
+ QQuickShaderEffectProgram m_source;
+ QSize m_meshResolution;
+ QQuickShaderEffectMesh *m_mesh;
+ QQuickGridMesh m_defaultMesh;
+ CullMode m_cullMode;
+
+ struct SourceData
+ {
+ QSignalMapper *mapper;
+ QPointer<QQuickItem> sourceObject;
+ QByteArray name;
+ };
+ QVector<SourceData> m_sources;
+
+ uint m_blending : 1;
+ uint m_dirtyData : 1;
+
+ uint m_programDirty : 1;
+ uint m_dirtyMesh : 1;
+ uint m_dirtyGeometry : 1;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSHADEREFFECT_P_H
diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp
new file mode 100644
index 0000000000..3154ac7cfd
--- /dev/null
+++ b/src/quick/items/qquickshadereffectmesh.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickshadereffectmesh_p.h"
+#include <QtQuick/qsggeometry.h>
+#include "qquickshadereffect_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQuickShaderEffectMesh::QQuickShaderEffectMesh(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \qmlclass GridMesh QQuickGridMesh
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
+ \brief GridMesh defines a mesh with vertices arranged in a grid.
+
+ GridMesh defines a rectangular mesh consisting of vertices arranged in an
+ evenly spaced grid. It is used to generate \l{QSGGeometry}{geometry}.
+ The grid resolution is specified with the \l resolution property.
+*/
+
+QQuickGridMesh::QQuickGridMesh(QObject *parent)
+ : QQuickShaderEffectMesh(parent)
+ , m_resolution(1, 1)
+{
+ connect(this, SIGNAL(resolutionChanged()), this, SIGNAL(geometryChanged()));
+}
+
+QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &dstRect) const
+{
+ int vmesh = m_resolution.height();
+ int hmesh = m_resolution.width();
+ int attrCount = attributes.count();
+
+ if (!geometry) {
+ bool error = true;
+ Q_UNUSED(error)
+ switch (attrCount) {
+ case 0:
+ qWarning("QQuickGridMesh:: No attributes specified.");
+ break;
+ case 1:
+ if (attributes.at(0) == qtPositionAttributeName()) {
+ error = false;
+ break;
+ }
+ qWarning("QQuickGridMesh:: Missing \'%s\' attribute.",
+ qtPositionAttributeName());
+ break;
+ case 2:
+ if (attributes.contains(qtPositionAttributeName())
+ && attributes.contains(qtTexCoordAttributeName()))
+ {
+ error = false;
+ break;
+ }
+ qWarning("QQuickGridMesh:: Missing \'%s\' or \'%s\' attribute.",
+ qtPositionAttributeName(), qtTexCoordAttributeName());
+ break;
+ default:
+ qWarning("QQuickGridMesh:: Too many attributes specified.");
+ break;
+ }
+
+ geometry = new QSGGeometry(attrCount == 1
+ ? QSGGeometry::defaultAttributes_Point2D()
+ : QSGGeometry::defaultAttributes_TexturedPoint2D(),
+ (vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2),
+ GL_UNSIGNED_SHORT);
+
+ } else {
+ geometry->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
+ }
+
+ QSGGeometry::Point2D *vdata = static_cast<QSGGeometry::Point2D *>(geometry->vertexData());
+
+ bool positionFirst = attributes.at(0) == qtPositionAttributeName();
+
+ QRectF srcRect(0, 0, 1, 1);
+ for (int iy = 0; iy <= vmesh; ++iy) {
+ float fy = iy / float(vmesh);
+ float y = float(dstRect.top()) + fy * float(dstRect.height());
+ float ty = float(srcRect.top()) + fy * float(srcRect.height());
+ for (int ix = 0; ix <= hmesh; ++ix) {
+ float fx = ix / float(hmesh);
+ for (int ia = 0; ia < attrCount; ++ia) {
+ if (positionFirst == (ia == 0)) {
+ vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
+ vdata->y = y;
+ ++vdata;
+ } else {
+ vdata->x = float(srcRect.left()) + fx * float(srcRect.width());
+ vdata->y = ty;
+ ++vdata;
+ }
+ }
+ }
+ }
+
+ quint16 *indices = (quint16 *)geometry->indexDataAsUShort();
+ int i = 0;
+ for (int iy = 0; iy < vmesh; ++iy) {
+ *(indices++) = i + hmesh + 1;
+ for (int ix = 0; ix <= hmesh; ++ix, ++i) {
+ *(indices++) = i + hmesh + 1;
+ *(indices++) = i;
+ }
+ *(indices++) = i - 1;
+ }
+
+ return geometry;
+}
+
+/*!
+ \qmlproperty size QtQuick2::GridMesh::resolution
+
+ This property holds the grid resolution. The resolution's width and height
+ specify the number of cells or spacings between vertices horizontally and
+ vertically respectively. The minimum and default is 1x1, which corresponds
+ to four vertices in total, one in each corner.
+ For non-linear vertex transformations, you probably want to set the
+ resolution higher.
+
+ \row
+ \o \image declarative-gridmesh.png
+ \o \qml
+ import QtQuick 2.0
+
+ ShaderEffect {
+ width: 200
+ height: 200
+ mesh: GridMesh {
+ resolution: Qt.size(20, 20)
+ }
+ property variant source: Image {
+ source: "qt-logo.png"
+ sourceSize { width: 200; height: 200 }
+ smooth: true
+ }
+ vertexShader: "
+ uniform highp mat4 qt_Matrix;
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec2 qt_MultiTexCoord0;
+ varying highp vec2 qt_TexCoord0;
+ uniform highp float width;
+ void main() {
+ highp vec4 pos = qt_Vertex;
+ highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
+ pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
+ gl_Position = qt_Matrix * pos;
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ }"
+ }
+ \endqml
+ \endrow
+*/
+
+void QQuickGridMesh::setResolution(const QSize &res)
+{
+ if (res == m_resolution)
+ return;
+ if (res.width() < 1 || res.height() < 1) {
+ return;
+ }
+ m_resolution = res;
+ emit resolutionChanged();
+}
+
+QSize QQuickGridMesh::resolution() const
+{
+ return m_resolution;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
new file mode 100644
index 0000000000..1671fd53f9
--- /dev/null
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qdeclarativeparserstatus.h"
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtGui/qcolor.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qopenglfunctions.h>
+
+#ifndef QQUICKSHADEREFFECTMESH_P_H
+#define QQUICKSHADEREFFECTMESH_P_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGGeometry;
+class QRectF;
+
+class Q_QUICK_EXPORT QQuickShaderEffectMesh : public QObject
+{
+ Q_OBJECT
+public:
+ QQuickShaderEffectMesh(QObject *parent = 0);
+ // If 'geometry' != 0, 'attributes' is the same as last time the function was called.
+ virtual QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &rect) const = 0;
+
+Q_SIGNALS:
+ // Emitted when the geometry needs to be updated.
+ void geometryChanged();
+};
+
+class QQuickGridMesh : public QQuickShaderEffectMesh
+{
+ Q_OBJECT
+ Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
+public:
+ QQuickGridMesh(QObject *parent = 0);
+ virtual QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &rect) const;
+
+ void setResolution(const QSize &res);
+ QSize resolution() const;
+
+Q_SIGNALS:
+ void resolutionChanged();
+
+private:
+ QSize m_resolution;
+};
+
+inline QColor qt_premultiply_color(const QColor &c)
+{
+ return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
+}
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSHADEREFFECTMESH_P_H
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
new file mode 100644
index 0000000000..02b49b94c5
--- /dev/null
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <private/qquickshadereffectnode_p.h>
+
+#include "qquickshadereffectmesh_p.h"
+#include <QtQuick/private/qsgtextureprovider_p.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCustomMaterialShader : public QSGMaterialShader
+{
+public:
+ QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes);
+ virtual void deactivate();
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+protected:
+ friend class QQuickShaderEffectNode;
+
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ const QQuickShaderEffectMaterialKey m_key;
+ QVector<const char *> m_attributeNames;
+ const QVector<QByteArray> m_attributes;
+
+ QVector<int> m_uniformLocs;
+ int m_opacityLoc;
+ int m_matrixLoc;
+ uint m_textureIndicesSet;
+};
+
+QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes)
+ : m_key(key)
+ , m_attributes(attributes)
+ , m_textureIndicesSet(false)
+{
+ for (int i = 0; i < attributes.count(); ++i)
+ m_attributeNames.append(attributes.at(i).constData());
+ m_attributeNames.append(0);
+}
+
+void QQuickCustomMaterialShader::deactivate()
+{
+ QSGMaterialShader::deactivate();
+ glDisable(GL_CULL_FACE);
+}
+
+void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(newEffect != 0);
+
+ const QQuickShaderEffectMaterial *material = static_cast<const QQuickShaderEffectMaterial *>(newEffect);
+
+ if (!m_textureIndicesSet) {
+ for (int i = 0; i < material->m_textures.size(); ++i)
+ program()->setUniformValue(material->m_textures.at(i).first.constData(), i);
+ m_textureIndicesSet = true;
+ }
+
+ if (m_uniformLocs.size() != material->m_uniformValues.size()) {
+ m_uniformLocs.reserve(material->m_uniformValues.size());
+ for (int i = 0; i < material->m_uniformValues.size(); ++i) {
+ const QByteArray &name = material->m_uniformValues.at(i).first;
+ m_uniformLocs.append(program()->uniformLocation(name.constData()));
+ }
+ }
+
+ QOpenGLFunctions *functions = state.context()->functions();
+ for (int i = material->m_textures.size() - 1; i >= 0; --i) {
+ functions->glActiveTexture(GL_TEXTURE0 + i);
+ if (QSGTextureProvider *provider = material->m_textures.at(i).second) {
+ if (QSGTexture *texture = provider->texture()) {
+ texture->bind();
+ continue;
+ }
+ }
+ qWarning("ShaderEffect: source or provider missing when binding textures");
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ if (material->m_source.respectsOpacity)
+ program()->setUniformValue(m_opacityLoc, state.opacity());
+
+ for (int i = 0; i < material->m_uniformValues.count(); ++i) {
+ const QVariant &v = material->m_uniformValues.at(i).second;
+
+ switch (v.type()) {
+ case QVariant::Color:
+ program()->setUniformValue(m_uniformLocs.at(i), qt_premultiply_color(qvariant_cast<QColor>(v)));
+ break;
+ case QVariant::Double:
+ program()->setUniformValue(m_uniformLocs.at(i), (float) qvariant_cast<double>(v));
+ break;
+ case QVariant::Transform:
+ program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QTransform>(v));
+ break;
+ case QVariant::Int:
+ program()->setUniformValue(m_uniformLocs.at(i), v.toInt());
+ break;
+ case QVariant::Bool:
+ program()->setUniformValue(m_uniformLocs.at(i), GLint(v.toBool()));
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ program()->setUniformValue(m_uniformLocs.at(i), v.toSizeF());
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ program()->setUniformValue(m_uniformLocs.at(i), v.toPointF());
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ QRectF r = v.toRectF();
+ program()->setUniformValue(m_uniformLocs.at(i), r.x(), r.y(), r.width(), r.height());
+ }
+ break;
+ case QVariant::Vector3D:
+ program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QVector3D>(v));
+ break;
+ default:
+ break;
+ }
+ }
+
+ const QQuickShaderEffectMaterial *oldMaterial = static_cast<const QQuickShaderEffectMaterial *>(oldEffect);
+ if (oldEffect == 0 || material->cullMode() != oldMaterial->cullMode()) {
+ switch (material->cullMode()) {
+ case QQuickShaderEffectMaterial::FrontFaceCulling:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ break;
+ case QQuickShaderEffectMaterial::BackFaceCulling:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ break;
+ default:
+ glDisable(GL_CULL_FACE);
+ break;
+ }
+ }
+
+ if ((state.isMatrixDirty()) && material->m_source.respectsMatrix)
+ program()->setUniformValue(m_matrixLoc, state.combinedMatrix());
+}
+
+char const *const *QQuickCustomMaterialShader::attributeNames() const
+{
+ return m_attributeNames.constData();
+}
+
+void QQuickCustomMaterialShader::initialize()
+{
+ m_opacityLoc = program()->uniformLocation("qt_Opacity");
+ m_matrixLoc = program()->uniformLocation("qt_Matrix");
+}
+
+const char *QQuickCustomMaterialShader::vertexShader() const
+{
+ return m_key.vertexCode.constData();
+}
+
+const char *QQuickCustomMaterialShader::fragmentShader() const
+{
+ return m_key.fragmentCode.constData();
+}
+
+
+bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const
+{
+ return vertexCode == other.vertexCode && fragmentCode == other.fragmentCode && className == other.className;
+}
+
+uint qHash(const QQuickShaderEffectMaterialKey &key)
+{
+ return qHash(qMakePair(qMakePair(key.vertexCode, key.fragmentCode), key.className));
+}
+
+
+QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > QQuickShaderEffectMaterial::materialMap;
+
+QQuickShaderEffectMaterial::QQuickShaderEffectMaterial()
+ : m_cullMode(NoCulling)
+{
+ setFlag(Blending, true);
+}
+
+QSGMaterialType *QQuickShaderEffectMaterial::type() const
+{
+ return m_type.data();
+}
+
+QSGMaterialShader *QQuickShaderEffectMaterial::createShader() const
+{
+ return new QQuickCustomMaterialShader(m_source, m_source.attributeNames);
+}
+
+int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
+{
+ return this - static_cast<const QQuickShaderEffectMaterial *>(other);
+}
+
+void QQuickShaderEffectMaterial::setCullMode(QQuickShaderEffectMaterial::CullMode face)
+{
+ m_cullMode = face;
+}
+
+QQuickShaderEffectMaterial::CullMode QQuickShaderEffectMaterial::cullMode() const
+{
+ return m_cullMode;
+}
+
+void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgram &source)
+{
+ m_source = source;
+ m_type = materialMap.value(m_source);
+ if (m_type.isNull()) {
+ m_type = QSharedPointer<QSGMaterialType>(new QSGMaterialType);
+ materialMap.insert(m_source, m_type);
+ }
+}
+
+void QQuickShaderEffectMaterial::setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues)
+{
+ m_uniformValues = uniformValues;
+}
+
+void QQuickShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures)
+{
+ m_textures = textures;
+}
+
+const QVector<QPair<QByteArray, QSGTextureProvider *> > &QQuickShaderEffectMaterial::textureProviders() const
+{
+ return m_textures;
+}
+
+void QQuickShaderEffectMaterial::updateTextures() const
+{
+ for (int i = 0; i < m_textures.size(); ++i) {
+ if (QSGTextureProvider *provider = m_textures.at(i).second) {
+ if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
+ texture->updateTexture();
+ }
+ }
+}
+
+
+QQuickShaderEffectNode::QQuickShaderEffectNode()
+{
+ QSGNode::setFlag(UsePreprocess, true);
+ setMaterial(&m_material);
+
+#ifdef QML_RUNTIME_TESTING
+ description = QLatin1String("shadereffect");
+#endif
+}
+
+QQuickShaderEffectNode::~QQuickShaderEffectNode()
+{
+}
+
+void QQuickShaderEffectNode::markDirtyTexture()
+{
+ markDirty(DirtyMaterial);
+}
+
+void QQuickShaderEffectNode::preprocess()
+{
+ Q_ASSERT(material());
+ static_cast<QQuickShaderEffectMaterial *>(material())->updateTextures();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
new file mode 100644
index 0000000000..abcd4a9b8e
--- /dev/null
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKSHADEREFFECTNODE_P_H
+#define QQUICKSHADEREFFECTNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgmaterial.h>
+#include <QtQuick/private/qsgtextureprovider_p.h>
+#include <QtQuick/qquickitem.h>
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+struct QQuickShaderEffectMaterialKey {
+ QByteArray vertexCode;
+ QByteArray fragmentCode;
+ const char *className;
+
+ bool operator == (const QQuickShaderEffectMaterialKey &other) const;
+};
+
+uint qHash(const QQuickShaderEffectMaterialKey &key);
+
+// TODO: Implement support for multisampling.
+struct QQuickShaderEffectProgram : public QQuickShaderEffectMaterialKey
+{
+ QQuickShaderEffectProgram() : respectsOpacity(false), respectsMatrix(false) {}
+
+ QVector<QByteArray> attributeNames;
+ QSet<QByteArray> uniformNames;
+
+ uint respectsOpacity : 1;
+ uint respectsMatrix : 1;
+};
+
+
+class QQuickCustomMaterialShader;
+class QQuickShaderEffectMaterial : public QSGMaterial
+{
+public:
+ enum CullMode
+ {
+ NoCulling,
+ BackFaceCulling,
+ FrontFaceCulling
+ };
+
+ QQuickShaderEffectMaterial();
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setCullMode(CullMode face);
+ CullMode cullMode() const;
+
+ void setProgramSource(const QQuickShaderEffectProgram &);
+ void setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues);
+ void setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures);
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &textureProviders() const;
+ void updateTextures() const;
+
+protected:
+ friend class QQuickCustomMaterialShader;
+
+ // The type pointer needs to be unique. It is not safe to let the type object be part of the
+ // QQuickShaderEffectMaterial, since it can be deleted and a new one constructed on top of the old
+ // one. The new QQuickShaderEffectMaterial would then get the same type pointer as the old one, and
+ // CustomMaterialShaders based on the old one would incorrectly be used together with the new
+ // one. To guarantee that the type pointer is unique, the type object must live as long as
+ // there are any CustomMaterialShaders of that type.
+ QSharedPointer<QSGMaterialType> m_type;
+
+ QQuickShaderEffectProgram m_source;
+ QVector<QPair<QByteArray, QVariant> > m_uniformValues;
+ QVector<QPair<QByteArray, QSGTextureProvider *> > m_textures;
+ CullMode m_cullMode;
+
+ static QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > materialMap;
+};
+
+
+class QSGShaderEffectMesh;
+
+class QQuickShaderEffectNode : public QObject, public QSGGeometryNode
+{
+ Q_OBJECT
+public:
+ QQuickShaderEffectNode();
+ virtual ~QQuickShaderEffectNode();
+
+ virtual void preprocess();
+
+ QQuickShaderEffectMaterial *shaderMaterial() { return &m_material; }
+
+private Q_SLOTS:
+ void markDirtyTexture();
+
+private:
+ QQuickShaderEffectMaterial m_material;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSHADEREFFECTNODE_P_H
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
new file mode 100644
index 0000000000..e8be7bde85
--- /dev/null
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -0,0 +1,921 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickshadereffectsource_p.h"
+
+#include "qquickitem_p.h"
+#include "qquickcanvas_p.h"
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+
+#include "qopenglframebufferobject.h"
+#include "qmath.h"
+#include <QtQuick/private/qsgtexture_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+
+class QQuickShaderEffectSourceTextureProvider : public QSGTextureProvider
+{
+ Q_OBJECT
+public:
+ QQuickShaderEffectSourceTextureProvider()
+ : sourceTexture(0)
+ {
+ }
+
+ QSGTexture *texture() const {
+ sourceTexture->setMipmapFiltering(mipmapFiltering);
+ sourceTexture->setFiltering(filtering);
+ sourceTexture->setHorizontalWrapMode(horizontalWrap);
+ sourceTexture->setVerticalWrapMode(verticalWrap);
+ return sourceTexture;
+ }
+
+ QQuickShaderEffectTexture *sourceTexture;
+
+ QSGTexture::Filtering mipmapFiltering;
+ QSGTexture::Filtering filtering;
+ QSGTexture::WrapMode horizontalWrap;
+ QSGTexture::WrapMode verticalWrap;
+};
+#include "qquickshadereffectsource.moc"
+
+
+QQuickShaderEffectSourceNode::QQuickShaderEffectSourceNode()
+{
+ setFlag(UsePreprocess, true);
+}
+
+void QQuickShaderEffectSourceNode::markDirtyTexture()
+{
+ markDirty(DirtyMaterial);
+}
+
+
+QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource)
+ : QSGDynamicTexture()
+ , m_item(0)
+ , m_format(GL_RGBA)
+ , m_shaderSource(shaderSource)
+ , m_renderer(0)
+ , m_fbo(0)
+ , m_secondaryFbo(0)
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ , m_debugOverlay(0)
+#endif
+ , m_context(QQuickItemPrivate::get(shaderSource)->sceneGraphContext())
+ , m_mipmap(false)
+ , m_live(true)
+ , m_recursive(false)
+ , m_dirtyTexture(true)
+ , m_multisamplingSupportChecked(false)
+ , m_multisampling(false)
+ , m_grab(false)
+{
+}
+
+QQuickShaderEffectTexture::~QQuickShaderEffectTexture()
+{
+ if (m_renderer)
+ disconnect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
+ delete m_renderer;
+ delete m_fbo;
+ delete m_secondaryFbo;
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ delete m_debugOverlay;
+#endif
+}
+
+int QQuickShaderEffectTexture::textureId() const
+{
+ return m_fbo ? m_fbo->texture() : 0;
+}
+
+bool QQuickShaderEffectTexture::hasAlphaChannel() const
+{
+ return m_format != GL_RGB;
+}
+
+bool QQuickShaderEffectTexture::hasMipmaps() const
+{
+ return m_mipmap;
+}
+
+
+void QQuickShaderEffectTexture::bind()
+{
+#ifndef QT_NO_DEBUG
+ if (!m_recursive && m_fbo && ((m_multisampling && m_secondaryFbo->isBound()) || m_fbo->isBound()))
+ qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively.");
+#endif
+ glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
+ updateBindOptions();
+}
+
+bool QQuickShaderEffectTexture::updateTexture()
+{
+ if ((m_live || m_grab) && m_dirtyTexture) {
+ grab();
+ m_grab = false;
+ return true;
+ }
+ return false;
+}
+
+void QQuickShaderEffectTexture::setHasMipmaps(bool mipmap)
+{
+ if (mipmap == m_mipmap)
+ return;
+ m_mipmap = mipmap;
+ if (m_mipmap && m_fbo && !m_fbo->format().mipmap())
+ markDirtyTexture();
+}
+
+
+void QQuickShaderEffectTexture::setItem(QSGNode *item)
+{
+ if (item == m_item)
+ return;
+ m_item = item;
+ markDirtyTexture();
+}
+
+void QQuickShaderEffectTexture::setRect(const QRectF &rect)
+{
+ if (rect == m_rect)
+ return;
+ m_rect = rect;
+ markDirtyTexture();
+}
+
+void QQuickShaderEffectTexture::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+ m_size = size;
+ markDirtyTexture();
+}
+
+void QQuickShaderEffectTexture::setFormat(GLenum format)
+{
+ if (format == m_format)
+ return;
+ m_format = format;
+ markDirtyTexture();
+}
+
+void QQuickShaderEffectTexture::setLive(bool live)
+{
+ if (live == m_live)
+ return;
+ m_live = live;
+ markDirtyTexture();
+}
+
+void QQuickShaderEffectTexture::scheduleUpdate()
+{
+ if (m_grab)
+ return;
+ m_grab = true;
+ if (m_dirtyTexture)
+ emit updateRequested();
+}
+
+void QQuickShaderEffectTexture::setRecursive(bool recursive)
+{
+ m_recursive = recursive;
+}
+
+void QQuickShaderEffectTexture::markDirtyTexture()
+{
+ m_dirtyTexture = true;
+ if (m_live || m_grab)
+ emit updateRequested();
+}
+
+void QQuickShaderEffectTexture::grab()
+{
+ if (!m_item || m_size.isNull()) {
+ delete m_fbo;
+ delete m_secondaryFbo;
+ m_fbo = m_secondaryFbo = 0;
+ m_dirtyTexture = false;
+ if (m_grab)
+ emit scheduledUpdateCompleted();
+ return;
+ }
+ QSGNode *root = m_item;
+ while (root->firstChild() && root->type() != QSGNode::RootNodeType)
+ root = root->firstChild();
+ if (root->type() != QSGNode::RootNodeType)
+ return;
+
+ if (!m_renderer) {
+ m_renderer = m_context->createRenderer();
+ connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
+ }
+ m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
+
+ bool deleteFboLater = false;
+ if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
+ || (!m_fbo->format().mipmap() && m_mipmap))
+ {
+ if (!m_multisamplingSupportChecked) {
+ QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
+ m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample")
+ && extensions.contains("GL_EXT_framebuffer_blit");
+ m_multisamplingSupportChecked = true;
+ }
+ if (m_multisampling) {
+ // Don't delete the FBO right away in case it is used recursively.
+ deleteFboLater = true;
+ delete m_secondaryFbo;
+ QOpenGLFramebufferObjectFormat format;
+
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+ format.setSamples(8);
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
+ } else {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+ format.setMipmap(m_mipmap);
+ if (m_recursive) {
+ deleteFboLater = true;
+ delete m_secondaryFbo;
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
+ glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
+ updateBindOptions(true);
+ } else {
+ delete m_fbo;
+ delete m_secondaryFbo;
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
+ m_secondaryFbo = 0;
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ updateBindOptions(true);
+ }
+ }
+ }
+
+ if (m_recursive && !m_secondaryFbo) {
+ // m_fbo already created, m_recursive was just set.
+ Q_ASSERT(m_fbo);
+ Q_ASSERT(!m_multisampling);
+
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
+ glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
+ updateBindOptions(true);
+ }
+
+ // Render texture.
+ root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
+ m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update.
+
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ if (qmlFboOverlay()) {
+ if (!m_debugOverlay)
+ m_debugOverlay = m_context->createRectangleNode();
+ m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
+ m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
+ m_debugOverlay->setPenColor(QColor());
+ m_debugOverlay->setPenWidth(0);
+ m_debugOverlay->setRadius(0);
+ m_debugOverlay->update();
+ root->appendChildNode(m_debugOverlay);
+ }
+#endif
+
+ m_dirtyTexture = false;
+
+ QOpenGLContext *ctx = m_context->glContext();
+ m_renderer->setDeviceRect(m_size);
+ m_renderer->setViewportRect(m_size);
+ QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
+ m_renderer->setProjectionMatrixToRect(mirrored);
+ m_renderer->setClearColor(Qt::transparent);
+
+ if (m_multisampling) {
+ m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
+
+ if (deleteFboLater) {
+ delete m_fbo;
+ QOpenGLFramebufferObjectFormat format;
+ format.setInternalTextureFormat(m_format);
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
+ format.setMipmap(m_mipmap);
+ format.setSamples(0);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ updateBindOptions(true);
+ }
+
+ QRect r(QPoint(), m_size);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
+ } else {
+ if (m_recursive) {
+ m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
+
+ if (deleteFboLater) {
+ delete m_fbo;
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+ format.setMipmap(m_mipmap);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ updateBindOptions(true);
+ }
+ qSwap(m_fbo, m_secondaryFbo);
+ } else {
+ m_renderer->renderScene(QSGBindableFbo(m_fbo));
+ }
+ }
+
+ if (m_mipmap) {
+ glBindTexture(GL_TEXTURE_2D, textureId());
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ }
+
+ root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.
+
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ if (qmlFboOverlay())
+ root->removeChildNode(m_debugOverlay);
+#endif
+ if (m_recursive)
+ markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
+
+ if (m_grab)
+ emit scheduledUpdateCompleted();
+}
+
+QImage QQuickShaderEffectTexture::toImage() const
+{
+ if (m_fbo)
+ return m_fbo->toImage();
+
+ return QImage();
+}
+
+/*!
+ \qmlclass ShaderEffectSource QQuickShaderEffectSource
+ \since 5.0
+ \ingroup qml-basic-visual-elements
+ \brief The ShaderEffectSource element renders a QML element into a texture
+ and displays it.
+ \inherits Item
+
+ The ShaderEffectSource element renders \l sourceItem into a texture and
+ displays it in the scene. \l sourceItem is drawn into the texture as though
+ it was a fully opaque root element. Thus \l sourceItem itself can be
+ invisible, but still appear in the texture.
+
+ ShaderEffectSource can be used as:
+ \list
+ \o a texture source in a \l ShaderEffect.
+ This allows you to apply custom shader effects to any QML element.
+ \o a cache for a complex element.
+ The complex element can be rendered once into the texture, which can
+ then be animated freely without the need to render the complex element
+ again every frame.
+ \o an opacity layer.
+ ShaderEffectSource allows you to apply an opacity to elements as a group
+ rather than each element individually.
+ \endlist
+
+ \table
+ \row
+ \o \image declarative-shadereffectsource.png
+ \o \qml
+ import QtQuick 2.0
+
+ Rectangle {
+ width: 200
+ height: 100
+ gradient: Gradient {
+ GradientStop { position: 0; color: "white" }
+ GradientStop { position: 1; color: "black" }
+ }
+ Row {
+ opacity: 0.5
+ Item {
+ id: foo
+ width: 100; height: 100
+ Rectangle { x: 5; y: 5; width: 60; height: 60; color: "red" }
+ Rectangle { x: 20; y: 20; width: 60; height: 60; color: "orange" }
+ Rectangle { x: 35; y: 35; width: 60; height: 60; color: "yellow" }
+ }
+ ShaderEffectSource {
+ width: 100; height: 100
+ sourceItem: foo
+ }
+ }
+ }
+ \endqml
+ \endrow
+ \endtable
+
+ The ShaderEffectSource element does not redirect any mouse or keyboard
+ input to \l sourceItem. If you hide the \l sourceItem by setting
+ \l{Item::visible}{visible} to false or \l{Item::opacity}{opacity} to zero,
+ it will no longer react to input. In cases where the ShaderEffectSource is
+ meant to replace the \l sourceItem, you typically want to hide the
+ \l sourceItem while still handling input. For this, you can use
+ the \l hideSource property.
+
+ \note If \l sourceItem is a \l Rectangle with border, by default half the
+ border width falls outside the texture. To get the whole border, you can
+ extend the \l sourceRect.
+
+ \warning In most cases, using a ShaderEffectSource will decrease
+ performance, and in all cases, it will increase video memory usage.
+ Rendering through a ShaderEffectSource might also lead to lower quality
+ since some OpenGL implementations support multisampled backbuffer,
+ but not multisampled framebuffer objects.
+*/
+
+QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_provider(0)
+ , m_texture(0)
+ , m_wrapMode(ClampToEdge)
+ , m_sourceItem(0)
+ , m_textureSize(0, 0)
+ , m_format(RGBA)
+ , m_live(true)
+ , m_hideSource(false)
+ , m_mipmap(false)
+ , m_recursive(false)
+ , m_grab(true)
+{
+ setFlag(ItemHasContents);
+}
+
+QQuickShaderEffectSource::~QQuickShaderEffectSource()
+{
+ if (m_texture)
+ m_texture->deleteLater();
+
+ if (m_provider)
+ m_provider->deleteLater();
+
+ if (m_sourceItem) {
+ QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem);
+ sd->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ sd->derefFromEffectItem(m_hideSource);
+ }
+}
+
+void QQuickShaderEffectSource::ensureTexture()
+{
+ if (m_texture)
+ return;
+
+ Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
+ && QQuickItemPrivate::get(this)->sceneGraphContext()
+ && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
+ "QQuickShaderEffectSource::ensureTexture",
+ "Cannot be used outside the rendering thread");
+
+ m_texture = new QQuickShaderEffectTexture(this);
+ connect(m_texture, SIGNAL(updateRequested()), this, SLOT(update()));
+ connect(m_texture, SIGNAL(scheduledUpdateCompleted()), this, SIGNAL(scheduledUpdateCompleted()));
+}
+
+QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const
+{
+ if (!m_provider) {
+ // Make sure it gets thread affinity on the rendering thread so deletion works properly..
+ Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
+ && QQuickItemPrivate::get(this)->sceneGraphContext()
+ && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
+ "QQuickShaderEffectSource::textureProvider",
+ "Cannot be used outside the rendering thread");
+ const_cast<QQuickShaderEffectSource *>(this)->m_provider = new QQuickShaderEffectSourceTextureProvider();
+ const_cast<QQuickShaderEffectSource *>(this)->ensureTexture();
+ connect(m_texture, SIGNAL(updateRequested()), m_provider, SIGNAL(textureChanged()));
+ m_provider->sourceTexture = m_texture;
+ }
+ return m_provider;
+}
+
+/*!
+ \qmlproperty enumeration ShaderEffectSource::wrapMode
+
+ This property defines the OpenGL wrap modes associated with the texture.
+ Modifying this property makes most sense when the element is used as a
+ source texture of a \l ShaderEffect.
+
+ \list
+ \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically
+ \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
+ \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
+ \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically
+ \endlist
+
+ \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
+ wrap mode with non-power-of-two textures.
+*/
+
+QQuickShaderEffectSource::WrapMode QQuickShaderEffectSource::wrapMode() const
+{
+ return m_wrapMode;
+}
+
+void QQuickShaderEffectSource::setWrapMode(WrapMode mode)
+{
+ if (mode == m_wrapMode)
+ return;
+ m_wrapMode = mode;
+ update();
+ emit wrapModeChanged();
+}
+
+/*!
+ \qmlproperty Item ShaderEffectSource::sourceItem
+
+ This property holds the element to be rendered into the texture.
+*/
+
+QQuickItem *QQuickShaderEffectSource::sourceItem() const
+{
+ return m_sourceItem;
+}
+
+void QQuickShaderEffectSource::itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect)
+{
+ Q_ASSERT(item == m_sourceItem);
+ Q_UNUSED(item);
+ if (newRect.size() != oldRect.size())
+ update();
+}
+
+void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
+{
+ if (item == m_sourceItem)
+ return;
+ if (m_sourceItem) {
+ QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
+ d->derefFromEffectItem(m_hideSource);
+ d->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ m_sourceItem = item;
+ if (m_sourceItem) {
+ // TODO: Find better solution.
+ // 'm_sourceItem' needs a canvas to get a scenegraph node.
+ // The easiest way to make sure it gets a canvas is to
+ // make it a part of the same item tree as 'this'.
+ if (m_sourceItem->parentItem() == 0) {
+ m_sourceItem->setParentItem(this);
+ m_sourceItem->setVisible(false);
+ }
+ QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
+ d->refFromEffectItem(m_hideSource);
+ d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ update();
+ emit sourceItemChanged();
+}
+
+/*!
+ \qmlproperty rect ShaderEffectSource::sourceRect
+
+ This property defines which rectangular area of the \l sourceItem to
+ render into the texture. The source rectangle can be larger than
+ \l sourceItem itself. If the rectangle is null, which is the default,
+ the whole \l sourceItem is rendered to texture.
+*/
+
+QRectF QQuickShaderEffectSource::sourceRect() const
+{
+ return m_sourceRect;
+}
+
+void QQuickShaderEffectSource::setSourceRect(const QRectF &rect)
+{
+ if (rect == m_sourceRect)
+ return;
+ m_sourceRect = rect;
+ update();
+ emit sourceRectChanged();
+}
+
+/*!
+ \qmlproperty size ShaderEffectSource::textureSize
+
+ This property holds the requested size of the texture. If it is empty,
+ which is the default, the size of the source rectangle is used.
+
+ \note Some platforms have a limit on how small framebuffer objects can be,
+ which means the actual texture size might be larger than the requested
+ size.
+*/
+
+QSize QQuickShaderEffectSource::textureSize() const
+{
+ return m_textureSize;
+}
+
+void QQuickShaderEffectSource::setTextureSize(const QSize &size)
+{
+ if (size == m_textureSize)
+ return;
+ m_textureSize = size;
+ update();
+ emit textureSizeChanged();
+}
+
+/*!
+ \qmlproperty enumeration ShaderEffectSource::format
+
+ This property defines the internal OpenGL format of the texture.
+ Modifying this property makes most sense when the element is used as a
+ source texture of a \l ShaderEffect. Depending on the OpenGL
+ implementation, this property might allow you to save some texture memory.
+
+ \list
+ \o ShaderEffectSource.Alpha - GL_ALPHA
+ \o ShaderEffectSource.RGB - GL_RGB
+ \o ShaderEffectSource.RGBA - GL_RGBA
+ \endlist
+
+ \note Some OpenGL implementations do not support the GL_ALPHA format.
+*/
+
+QQuickShaderEffectSource::Format QQuickShaderEffectSource::format() const
+{
+ return m_format;
+}
+
+void QQuickShaderEffectSource::setFormat(QQuickShaderEffectSource::Format format)
+{
+ if (format == m_format)
+ return;
+ m_format = format;
+ update();
+ emit formatChanged();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::live
+
+ If this property is true, the texture is updated whenever the
+ \l sourceItem changes. Otherwise, it will be a frozen image of the
+ \l sourceItem. The property is true by default.
+*/
+
+bool QQuickShaderEffectSource::live() const
+{
+ return m_live;
+}
+
+void QQuickShaderEffectSource::setLive(bool live)
+{
+ if (live == m_live)
+ return;
+ m_live = live;
+ update();
+ emit liveChanged();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::hideSource
+
+ If this property is true, the \l sourceItem is hidden, though it will still
+ be rendered into the texture. As opposed to hiding the \l sourceItem by
+ setting \l{Item::visible}{visible} to false, setting this property to true
+ will not prevent mouse or keyboard input from reaching \l sourceItem.
+ The property is useful when the ShaderEffectSource is anchored on top of,
+ and meant to replace the \l sourceItem.
+*/
+
+bool QQuickShaderEffectSource::hideSource() const
+{
+ return m_hideSource;
+}
+
+void QQuickShaderEffectSource::setHideSource(bool hide)
+{
+ if (hide == m_hideSource)
+ return;
+ if (m_sourceItem) {
+ QQuickItemPrivate::get(m_sourceItem)->refFromEffectItem(hide);
+ QQuickItemPrivate::get(m_sourceItem)->derefFromEffectItem(m_hideSource);
+ }
+ m_hideSource = hide;
+ update();
+ emit hideSourceChanged();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::mipmap
+
+ If this property is true, mipmaps are generated for the texture.
+
+ \note Some OpenGL ES 2 implementations do not support mipmapping of
+ non-power-of-two textures.
+*/
+
+bool QQuickShaderEffectSource::mipmap() const
+{
+ return m_mipmap;
+}
+
+void QQuickShaderEffectSource::setMipmap(bool enabled)
+{
+ if (enabled == m_mipmap)
+ return;
+ m_mipmap = enabled;
+ update();
+ emit mipmapChanged();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::recursive
+
+ Set this property to true if the ShaderEffectSource has a dependency on
+ itself. ShaderEffectSources form a dependency chain, where one
+ ShaderEffectSource can be part of the \l sourceItem of another.
+ If there is a loop in this chain, a ShaderEffectSource could end up trying
+ to render into the same texture it is using as source, which is not allowed
+ by OpenGL. When this property is set to true, an extra texture is allocated
+ so that ShaderEffectSource can keep a copy of the texture from the previous
+ frame. It can then render into one texture and use the texture from the
+ previous frame as source.
+
+ Setting both this property and \l live to true will cause the scene graph
+ to render continuously. Since the ShaderEffectSource depends on itself,
+ updating it means that it immediately becomes dirty again.
+*/
+
+bool QQuickShaderEffectSource::recursive() const
+{
+ return m_recursive;
+}
+
+void QQuickShaderEffectSource::setRecursive(bool enabled)
+{
+ if (enabled == m_recursive)
+ return;
+ m_recursive = enabled;
+ emit recursiveChanged();
+}
+
+/*!
+ \qmlmethod ShaderEffectSource::scheduleUpdate()
+
+ Schedules a re-rendering of the texture for the next frame.
+ Use this to update the texture when \l live is false.
+*/
+
+void QQuickShaderEffectSource::scheduleUpdate()
+{
+ if (m_grab)
+ return;
+ m_grab = true;
+ update();
+}
+
+static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::WrapMode *hWrap, QSGTexture::WrapMode *vWrap)
+{
+ switch (mode) {
+ case QQuickShaderEffectSource::RepeatHorizontally:
+ *hWrap = QSGTexture::Repeat;
+ *vWrap = QSGTexture::ClampToEdge;
+ break;
+ case QQuickShaderEffectSource::RepeatVertically:
+ *vWrap = QSGTexture::Repeat;
+ *hWrap = QSGTexture::ClampToEdge;
+ break;
+ case QQuickShaderEffectSource::Repeat:
+ *hWrap = *vWrap = QSGTexture::Repeat;
+ break;
+ default:
+ // QQuickShaderEffectSource::ClampToEdge
+ *hWrap = *vWrap = QSGTexture::ClampToEdge;
+ break;
+ }
+}
+
+
+QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ ensureTexture();
+
+ QQuickShaderEffectTexture *tex = qobject_cast<QQuickShaderEffectTexture *>(m_texture);
+ tex->setLive(m_live);
+ tex->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);
+ QSize textureSize = m_textureSize.isEmpty()
+ ? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())))
+ : m_textureSize;
+ Q_ASSERT(!textureSize.isEmpty());
+ QQuickItemPrivate *d = static_cast<QQuickItemPrivate *>(QObjectPrivate::get(this));
+ const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
+ // Keep power-of-two by doubling the size.
+ while (textureSize.width() < minTextureSize.width())
+ textureSize.rwidth() *= 2;
+ while (textureSize.height() < minTextureSize.height())
+ textureSize.rheight() *= 2;
+
+ tex->setSize(textureSize);
+ tex->setRecursive(m_recursive);
+ tex->setFormat(GLenum(m_format));
+ tex->setHasMipmaps(m_mipmap);
+
+ if (m_grab)
+ tex->scheduleUpdate();
+ m_grab = false;
+
+ QSGTexture::Filtering filtering = QQuickItemPrivate::get(this)->smooth
+ ? QSGTexture::Linear
+ : QSGTexture::Nearest;
+ QSGTexture::Filtering mmFiltering = m_mipmap ? filtering : QSGTexture::None;
+ QSGTexture::WrapMode hWrap, vWrap;
+ get_wrap_mode(m_wrapMode, &hWrap, &vWrap);
+
+ if (m_provider) {
+ m_provider->mipmapFiltering = mmFiltering;
+ m_provider->filtering = filtering;
+ m_provider->horizontalWrap = hWrap;
+ m_provider->verticalWrap = vWrap;
+ }
+
+ // Don't create the paint node if we're not spanning any area
+ if (width() == 0 || height() == 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QQuickShaderEffectSourceNode *node = static_cast<QQuickShaderEffectSourceNode *>(oldNode);
+ if (!node) {
+ node = new QQuickShaderEffectSourceNode;
+ node->setTexture(m_texture);
+ connect(m_texture, SIGNAL(updateRequested()), node, SLOT(markDirtyTexture()));
+ }
+
+ // If live and recursive, update continuously.
+ if (m_live && m_recursive)
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ node->setMipmapFiltering(mmFiltering);
+ node->setFiltering(filtering);
+ node->setHorizontalWrapMode(hWrap);
+ node->setVerticalWrapMode(vWrap);
+ node->setTargetRect(QRectF(0, 0, width(), height()));
+ node->setSourceRect(QRectF(0, 0, 1, 1));
+ node->update();
+
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
new file mode 100644
index 0000000000..b648cb5614
--- /dev/null
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKSHADEREFFECTSOURCE_P_H
+#define QQUICKSHADEREFFECTSOURCE_P_H
+
+#include "qquickitem.h"
+#include <QtQuick/private/qsgtextureprovider_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgdefaultimagenode_p.h>
+#include <private/qquickitemchangelistener_p.h>
+
+#include "qpointer.h"
+#include "qsize.h"
+#include "qrect.h"
+
+#define QSG_DEBUG_FBO_OVERLAY
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGNode;
+class UpdatePaintNodeData;
+class QOpenGLFramebufferObject;
+
+class QQuickShaderEffectSourceTextureProvider;
+
+class QQuickShaderEffectSourceNode : public QObject, public QSGDefaultImageNode
+{
+ Q_OBJECT
+
+public:
+ QQuickShaderEffectSourceNode();
+
+private Q_SLOTS:
+ void markDirtyTexture();
+};
+
+class Q_QUICK_EXPORT QQuickShaderEffectTexture : public QSGDynamicTexture
+{
+ Q_OBJECT
+public:
+ QQuickShaderEffectTexture(QQuickItem *shaderSource);
+ ~QQuickShaderEffectTexture();
+
+ virtual bool updateTexture();
+
+ // The item's "paint node", not effect node.
+ QSGNode *item() const { return m_item; }
+ void setItem(QSGNode *item);
+
+ QRectF rect() const { return m_rect; }
+ void setRect(const QRectF &rect);
+
+ QSize size() const { return m_size; }
+ void setSize(const QSize &size);
+
+ void setHasMipmaps(bool mipmap);
+
+ void bind();
+
+ bool hasAlphaChannel() const;
+ bool hasMipmaps() const;
+ int textureId() const;
+ QSize textureSize() const { return m_size; }
+
+ GLenum format() const { return m_format; }
+ void setFormat(GLenum format);
+
+ bool live() const { return bool(m_live); }
+ void setLive(bool live);
+
+ bool recursive() const { return bool(m_recursive); }
+ void setRecursive(bool recursive);
+
+ void scheduleUpdate();
+
+ QImage toImage() const;
+
+Q_SIGNALS:
+ void updateRequested();
+ void scheduledUpdateCompleted();
+
+public Q_SLOTS:
+ void markDirtyTexture();
+
+private:
+ void grab();
+
+ QSGNode *m_item;
+ QRectF m_rect;
+ QSize m_size;
+ GLenum m_format;
+
+ QQuickItem *m_shaderSource;
+ QSGRenderer *m_renderer;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_secondaryFbo;
+
+#ifdef QSG_DEBUG_FBO_OVERLAY
+ QSGRectangleNode *m_debugOverlay;
+#endif
+
+ QSGContext *m_context;
+
+ uint m_mipmap : 1;
+ uint m_live : 1;
+ uint m_recursive : 1;
+ uint m_dirtyTexture : 1;
+ uint m_multisamplingSupportChecked : 1;
+ uint m_multisampling : 1;
+ uint m_grab : 1;
+};
+
+class Q_QUICK_EXPORT QQuickShaderEffectSource : public QQuickItem, public QQuickItemChangeListener
+{
+ Q_OBJECT
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_PROPERTY(QQuickItem *sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged)
+ Q_PROPERTY(QRectF sourceRect READ sourceRect WRITE setSourceRect NOTIFY sourceRectChanged)
+ Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+ Q_PROPERTY(Format format READ format WRITE setFormat NOTIFY formatChanged)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged)
+ Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
+ Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
+ Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
+
+ Q_ENUMS(Format WrapMode)
+public:
+ enum WrapMode {
+ ClampToEdge,
+ RepeatHorizontally,
+ RepeatVertically,
+ Repeat
+ };
+
+ enum Format {
+ Alpha = GL_ALPHA,
+ RGB = GL_RGB,
+ RGBA = GL_RGBA
+ };
+
+ QQuickShaderEffectSource(QQuickItem *parent = 0);
+ ~QQuickShaderEffectSource();
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode mode);
+
+ QQuickItem *sourceItem() const;
+ void setSourceItem(QQuickItem *item);
+
+ QRectF sourceRect() const;
+ void setSourceRect(const QRectF &rect);
+
+ QSize textureSize() const;
+ void setTextureSize(const QSize &size);
+
+ Format format() const;
+ void setFormat(Format format);
+
+ bool live() const;
+ void setLive(bool live);
+
+ bool hideSource() const;
+ void setHideSource(bool hide);
+
+ bool mipmap() const;
+ void setMipmap(bool enabled);
+
+ bool recursive() const;
+ void setRecursive(bool enabled);
+
+ bool isTextureProvider() const { return true; }
+ QSGTextureProvider *textureProvider() const;
+
+ Q_INVOKABLE void scheduleUpdate();
+
+Q_SIGNALS:
+ void wrapModeChanged();
+ void sourceItemChanged();
+ void sourceRectChanged();
+ void textureSizeChanged();
+ void formatChanged();
+ void liveChanged();
+ void hideSourceChanged();
+ void mipmapChanged();
+ void recursiveChanged();
+
+ void scheduledUpdateCompleted();
+
+protected:
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+ virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect);
+
+private:
+ void ensureTexture();
+
+ QQuickShaderEffectSourceTextureProvider *m_provider;
+ QQuickShaderEffectTexture *m_texture;
+ WrapMode m_wrapMode;
+ QPointer<QQuickItem> m_sourceItem;
+ QRectF m_sourceRect;
+ QSize m_textureSize;
+ Format m_format;
+ uint m_live : 1;
+ uint m_hideSource : 1;
+ uint m_mipmap : 1;
+ uint m_recursive : 1;
+ uint m_grab : 1;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSHADEREFFECTSOURCE_P_H
diff --git a/src/declarative/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp
index b476905269..b476905269 100644
--- a/src/declarative/items/qquicksprite.cpp
+++ b/src/quick/items/qquicksprite.cpp
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
new file mode 100644
index 0000000000..a3921ed96a
--- /dev/null
+++ b/src/quick/items/qquicksprite_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQUICKSPRITE_P_H
+#define QQUICKSPRITE_P_H
+
+#include <QObject>
+#include <QUrl>
+#include <QVariantMap>
+#include <QDeclarativeListProperty>
+#include "qquickspriteengine_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickSprite : public QQuickStochasticState
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ //If frame height or width is not specified, it is assumed to be a single long row of square frames.
+ //Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used.
+ Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged)
+ Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged)
+
+public:
+ explicit QQuickSprite(QObject *parent = 0);
+
+ QUrl source() const
+ {
+ return m_source;
+ }
+
+ int frameHeight() const
+ {
+ return m_frameHeight;
+ }
+
+ int frameWidth() const
+ {
+ return m_frameWidth;
+ }
+
+
+signals:
+
+ void sourceChanged(QUrl arg);
+
+ void frameHeightChanged(int arg);
+
+ void frameWidthChanged(int arg);
+
+public slots:
+
+ void setSource(QUrl arg)
+ {
+ if (m_source != arg) {
+ m_source = arg;
+ emit sourceChanged(arg);
+ }
+ }
+
+ void setFrameHeight(int arg)
+ {
+ if (m_frameHeight != arg) {
+ m_frameHeight = arg;
+ emit frameHeightChanged(arg);
+ }
+ }
+
+ void setFrameWidth(int arg)
+ {
+ if (m_frameWidth != arg) {
+ m_frameWidth = arg;
+ emit frameWidthChanged(arg);
+ }
+ }
+
+
+private:
+ friend class QSGImageParticle;
+ friend class QQuickSpriteEngine;
+ friend class QQuickStochasticEngine;
+ int m_generatedCount;
+ int m_framesPerRow;
+ QUrl m_source;
+ int m_frameHeight;
+ int m_frameWidth;
+ int m_rowY;
+
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // QQUICKSPRITE_P_H
diff --git a/src/declarative/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index c25ccf3487..c25ccf3487 100644
--- a/src/declarative/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
new file mode 100644
index 0000000000..283ee17c96
--- /dev/null
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQUICKSPRITEENGINE_P_H
+#define QQUICKSPRITEENGINE_P_H
+
+#include <QObject>
+#include <QVector>
+#include <QTimer>
+#include <QTime>
+#include <QList>
+#include <QDeclarativeListProperty>
+#include <QImage>
+#include <QPair>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickSprite;
+class Q_AUTOTEST_EXPORT QQuickStochasticState : public QObject //For internal use
+{
+ Q_OBJECT
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(int durationVariation READ durationVariance WRITE setDurationVariance NOTIFY durationVarianceChanged)
+ Q_PROPERTY(QVariantMap to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(qreal speedModifiesDuration READ speedModifer WRITE setSpeedModifier NOTIFY speedModifierChanged)
+ Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged)
+
+public:
+ QQuickStochasticState(QObject* parent = 0)
+ : QObject(parent)
+ , m_frames(1)
+ , m_duration(1000)
+ {
+ }
+
+ int duration() const
+ {
+ return m_duration;
+ }
+
+ QString name() const
+ {
+ return m_name;
+ }
+
+ QVariantMap to() const
+ {
+ return m_to;
+ }
+
+ qreal speedModifer() const
+ {
+ return m_speedModifier;
+ }
+
+ int durationVariance() const
+ {
+ return m_durationVariance;
+ }
+
+
+ int variedDuration() const
+ {
+ return m_duration
+ + (m_durationVariance * ((qreal)qrand()/RAND_MAX) * 2)
+ - m_durationVariance;
+ }
+
+ int frames() const
+ {
+ return m_frames;
+ }
+
+signals:
+ void durationChanged(int arg);
+
+ void nameChanged(QString arg);
+
+ void toChanged(QVariantMap arg);
+
+ void speedModifierChanged(qreal arg);
+
+ void durationVarianceChanged(int arg);
+
+ void entered();//### Just playing around - don't expect full state API
+ void framesChanged(int arg);
+
+public slots:
+ void setDuration(int arg)
+ {
+ if (m_duration != arg) {
+ m_duration = arg;
+ emit durationChanged(arg);
+ }
+ }
+
+ void setName(QString arg)
+ {
+ if (m_name != arg) {
+ m_name = arg;
+ emit nameChanged(arg);
+ }
+ }
+
+ void setTo(QVariantMap arg)
+ {
+ if (m_to != arg) {
+ m_to = arg;
+ emit toChanged(arg);
+ }
+ }
+
+ void setSpeedModifier(qreal arg)
+ {
+ if (m_speedModifier != arg) {
+ m_speedModifier = arg;
+ emit speedModifierChanged(arg);
+ }
+ }
+
+ void setDurationVariance(int arg)
+ {
+ if (m_durationVariance != arg) {
+ m_durationVariance = arg;
+ emit durationVarianceChanged(arg);
+ }
+ }
+
+ void setFrames(int arg)
+ {
+ if (m_frames != arg) {
+ m_frames = arg;
+ emit framesChanged(arg);
+ }
+ }
+
+private:
+ QString m_name;
+ int m_frames;
+ QVariantMap m_to;
+ int m_duration;
+ qreal m_speedModifier;
+ int m_durationVariance;
+
+ friend class QQuickStochasticEngine;
+};
+
+class Q_AUTOTEST_EXPORT QQuickStochasticEngine : public QObject
+{
+ Q_OBJECT
+ //TODO: Optimize single state case?
+ Q_PROPERTY(QString globalGoal READ globalGoal WRITE setGlobalGoal NOTIFY globalGoalChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickStochasticState> states READ states)
+public:
+ explicit QQuickStochasticEngine(QObject *parent = 0);
+ QQuickStochasticEngine(QList<QQuickStochasticState*> states, QObject *parent=0);
+ ~QQuickStochasticEngine();
+
+ QDeclarativeListProperty<QQuickStochasticState> states()
+ {
+ return QDeclarativeListProperty<QQuickStochasticState>(this, m_states);
+ }
+
+ QString globalGoal() const
+ {
+ return m_globalGoal;
+ }
+
+ int count() const {return m_things.count();}
+ void setCount(int c);
+
+ void setGoal(int state, int sprite=0, bool jump=false);
+ void start(int index=0, int state=0);
+ void stop(int index=0);
+ int curState(int index=0) {return m_things[index];}
+
+ QQuickStochasticState* state(int idx){return m_states[idx];}
+ int stateIndex(QQuickStochasticState* s){return m_states.indexOf(s);}
+ int stateIndex(const QString& s) {
+ for (int i=0; i<m_states.count(); i++)
+ if (m_states[i]->name() == s)
+ return i;
+ return -1;
+ }
+
+ int stateCount() {return m_states.count();}
+private:
+signals:
+
+ void globalGoalChanged(QString arg);
+ void stateChanged(int idx);
+
+public slots:
+ void setGlobalGoal(QString arg)
+ {
+ if (m_globalGoal != arg) {
+ m_globalGoal = arg;
+ emit globalGoalChanged(arg);
+ }
+ }
+
+ uint updateSprites(uint time);
+
+protected:
+ friend class QQuickParticleSystem;
+ void restart(int index);
+ void addToUpdateList(uint t, int idx);
+ int goalSeek(int curState, int idx, int dist=-1);
+ QList<QQuickStochasticState*> m_states;
+ //### Consider struct or class for the four data variables?
+ QVector<int> m_things;//int is the index in m_states of the current state
+ QVector<int> m_goals;
+ QVector<int> m_duration;
+ QVector<int> m_startTimes;
+ QList<QPair<uint, QList<int> > > m_stateUpdates;//### This could be done faster - priority queue?
+
+ QTime m_advanceTime;
+ uint m_timeOffset;
+ QString m_globalGoal;
+ int m_maxFrames;
+ int m_imageStateCount;
+};
+
+class QQuickSpriteEngine : public QQuickStochasticEngine
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
+public:
+ explicit QQuickSpriteEngine(QObject *parent = 0);
+ QQuickSpriteEngine(QList<QQuickSprite*> sprites, QObject *parent=0);
+ ~QQuickSpriteEngine();
+ QDeclarativeListProperty<QQuickSprite> sprites()
+ {
+ return QDeclarativeListProperty<QQuickSprite>(this, m_sprites);
+ }
+
+
+ int spriteState(int sprite=0);
+ int spriteStart(int sprite=0);
+ int spriteFrames(int sprite=0);
+ int spriteDuration(int sprite=0);
+ int spriteX(int /* sprite */ = 0) { return 0; }//Currently all rows are 0 aligned, if we get more space efficient we might change this
+ int spriteY(int sprite=0);
+ int spriteWidth(int sprite=0);
+ int spriteHeight(int sprite=0);
+ int spriteCount();//Like state count, but for the image states
+ int maxFrames();
+ QImage assembledImage();
+private:
+ QList<QQuickSprite*> m_sprites;
+};
+
+//Common use is to have your own list property which is transparently an engine
+inline void spriteAppend(QDeclarativeListProperty<QQuickSprite> *p, QQuickSprite* s)
+{
+ reinterpret_cast<QList<QQuickSprite *> *>(p->data)->append(s);
+ p->object->metaObject()->invokeMethod(p->object, "createEngine");
+}
+
+inline QQuickSprite* spriteAt(QDeclarativeListProperty<QQuickSprite> *p, int idx)
+{
+ return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->at(idx);
+}
+
+inline void spriteClear(QDeclarativeListProperty<QQuickSprite> *p)
+{
+ reinterpret_cast<QList<QQuickSprite *> *>(p->data)->clear();
+ p->object->metaObject()->invokeMethod(p->object, "createEngine");
+}
+
+inline int spriteCount(QDeclarativeListProperty<QQuickSprite> *p)
+{
+ return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->count();
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSPRITEENGINE_P_H
diff --git a/src/quick/items/qquickspriteimage.cpp b/src/quick/items/qquickspriteimage.cpp
new file mode 100644
index 0000000000..1da46f2ae8
--- /dev/null
+++ b/src/quick/items/qquickspriteimage.cpp
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qquickspriteimage_p.h"
+#include "qquicksprite_p.h"
+#include "qquickspriteengine_p.h"
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgengine.h>
+#include <QtQuick/qsgtexturematerial.h>
+#include <QtQuick/qsgtexture.h>
+#include <QtQuick/qquickcanvas.h>
+#include <QFile>
+#include <cmath>
+#include <qmath.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static const char vertexShaderCode[] =
+ "attribute highp vec2 vTex;\n"
+ "uniform highp vec4 animData;// interpolate(bool), duration, frameCount (this anim), timestamp (this anim)\n"
+ "uniform highp vec4 animPos;//sheet x,y, width/height of this anim\n"
+ "uniform highp vec4 animSheetSize; //width/height of whole sheet, width/height of element\n"
+ "\n"
+ "uniform highp mat4 qt_Matrix;\n"
+ "uniform highp float timestamp;\n"
+ "\n"
+ "varying highp vec4 fTexS;\n"
+ "varying lowp float progress;\n"
+ "\n"
+ "\n"
+ "void main() {\n"
+ " //Calculate frame location in texture\n"
+ " highp float frameIndex = mod((((timestamp - animData.w)*1000.)/animData.y),animData.z);\n"
+ " progress = mod((timestamp - animData.w)*1000., animData.y) / animData.y;\n"
+ "\n"
+ " frameIndex = floor(frameIndex);\n"
+ " fTexS.xy = vec2(((frameIndex + vTex.x) * animPos.z / animSheetSize.x), ((animPos.y + vTex.y * animPos.w) / animSheetSize.y));\n"
+ "\n"
+ " //Next frame is also passed, for interpolation\n"
+ " //### Should the next anim be precalculated to allow for interpolation there?\n"
+ " if (animData.x == 1.0 && frameIndex != animData.z - 1.)//Can't do it for the last frame though, this anim may not loop\n"
+ " frameIndex = mod(frameIndex+1., animData.z);\n"
+ " fTexS.zw = vec2(((frameIndex + vTex.x) * animPos.z / animSheetSize.x), ((animPos.y + vTex.y * animPos.w) / animSheetSize.y));\n"
+ "\n"
+ " gl_Position = qt_Matrix * vec4(animSheetSize.z * vTex.x, animSheetSize.w * vTex.y, 0, 1);\n"
+ "}\n";
+
+static const char fragmentShaderCode[] =
+ "uniform sampler2D texture;\n"
+ "uniform lowp float qt_Opacity;\n"
+ "\n"
+ "varying highp vec4 fTexS;\n"
+ "varying lowp float progress;\n"
+ "\n"
+ "void main() {\n"
+ " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n"
+ "}\n";
+
+class QQuickSpriteMaterial : public QSGMaterial
+{
+public:
+ QQuickSpriteMaterial();
+ virtual ~QQuickSpriteMaterial();
+ virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const
+ {
+ return this - static_cast<const QQuickSpriteMaterial *>(other);
+ }
+
+ QSGTexture *texture;
+
+ qreal timestamp;
+ float interpolate;
+ float frameDuration;
+ float frameCount;
+ float animT;
+ float animX;
+ float animY;
+ float animWidth;
+ float animHeight;
+ float sheetWidth;
+ float sheetHeight;
+ float elementWidth;
+ float elementHeight;
+};
+
+QQuickSpriteMaterial::QQuickSpriteMaterial()
+ : timestamp(0)
+ , interpolate(1.0f)
+ , frameDuration(1.0f)
+ , frameCount(1.0f)
+ , animT(0.0f)
+ , animX(0.0f)
+ , animY(0.0f)
+ , animWidth(1.0f)
+ , animHeight(1.0f)
+ , sheetWidth(1.0f)
+ , sheetHeight(1.0f)
+ , elementWidth(1.0f)
+ , elementHeight(1.0f)
+{
+ setFlag(Blending, true);
+}
+
+QQuickSpriteMaterial::~QQuickSpriteMaterial()
+{
+ delete texture;
+}
+
+class SpriteMaterialData : public QSGMaterialShader
+{
+public:
+ SpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
+ {
+ }
+
+ void deactivate() {
+ QSGMaterialShader::deactivate();
+
+ for (int i=0; i<8; ++i) {
+ program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
+ }
+ }
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+ {
+ QQuickSpriteMaterial *m = static_cast<QQuickSpriteMaterial *>(newEffect);
+ m->texture->bind();
+
+ program()->setUniformValue(m_opacity_id, state.opacity());
+ program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
+ program()->setUniformValue(m_animData_id, m->interpolate, m->frameDuration, m->frameCount, m->animT);
+ program()->setUniformValue(m_animPos_id, m->animX, m->animY, m->animWidth, m->animHeight);
+ program()->setUniformValue(m_animSheetSize_id, m->sheetWidth, m->sheetHeight, m->elementWidth, m->elementHeight);
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ }
+
+ virtual void initialize() {
+ m_matrix_id = program()->uniformLocation("qt_Matrix");
+ m_opacity_id = program()->uniformLocation("qt_Opacity");
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_animData_id = program()->uniformLocation("animData");
+ m_animPos_id = program()->uniformLocation("animPos");
+ m_animSheetSize_id = program()->uniformLocation("animSheetSize");
+ }
+
+ virtual const char *vertexShader() const { return vertexShaderCode; }
+ virtual const char *fragmentShader() const { return fragmentShaderCode; }
+
+ virtual char const *const *attributeNames() const {
+ static const char *attr[] = {
+ "vTex",
+ 0
+ };
+ return attr;
+ }
+
+ int m_matrix_id;
+ int m_opacity_id;
+ int m_timestamp_id;
+ int m_animData_id;
+ int m_animPos_id;
+ int m_animSheetSize_id;
+
+ static float chunkOfBytes[1024];
+};
+
+float SpriteMaterialData::chunkOfBytes[1024];
+
+QSGMaterialShader *QQuickSpriteMaterial::createShader() const
+{
+ return new SpriteMaterialData;
+}
+
+struct SpriteVertex {
+ float tx;
+ float ty;
+};
+
+struct SpriteVertices {
+ SpriteVertex v1;
+ SpriteVertex v2;
+ SpriteVertex v3;
+ SpriteVertex v4;
+};
+
+/*!
+ \qmlclass SpriteImage QQuickSpriteImage
+ \inqmlmodule QtQuick 2
+ \inherits Item
+ \brief The SpriteImage element draws a sprite animation
+
+*/
+/*!
+ \qmlproperty bool QtQuick2::SpriteImage::running
+
+ Whether the sprite is animating or not.
+
+ Default is true
+*/
+/*!
+ \qmlproperty bool QtQuick2::SpriteImage::interpolate
+
+ If true, interpolation will occur between sprite frames to make the
+ animation appear smoother.
+
+ Default is true.
+*/
+/*!
+ \qmlproperty string QtQuick2::SpriteImage::goalState
+
+ The name of the Sprite which the animation should move to.
+
+ Sprite states have defined durations and transitions between them, setting goalState
+ will cause it to disregard any path weightings (including 0) and head down the path
+ which will reach the goalState quickest (fewest animations). It will pass through
+ intermediate states on that path, and animate them for their duration.
+
+ If it is possible to return to the goalState from the starting point of the goalState
+ it will continue to do so until goalState is set to "" or an unreachable state.
+*/
+/*! \qmlmethod void QtQuick2::SpriteImage::jumpTo(string sprite)
+
+ This function causes the sprite to jump to the specified state immediately, intermediate
+ states are not played.
+*/
+/*!
+ \qmlproperty list<Sprite> QtQuick2::SpriteImage::sprites
+
+ 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?
+QQuickSpriteImage::QQuickSpriteImage(QQuickItem *parent) :
+ QQuickItem(parent)
+ , m_node(0)
+ , m_material(0)
+ , m_spriteEngine(0)
+ , m_pleaseReset(false)
+ , m_running(true)
+ , m_interpolate(true)
+{
+ setFlag(ItemHasContents);
+ connect(this, SIGNAL(runningChanged(bool)),
+ this, SLOT(update()));
+}
+
+void QQuickSpriteImage::jumpTo(const QString &sprite)
+{
+ if (!m_spriteEngine)
+ return;
+ m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true);
+}
+
+void QQuickSpriteImage::setGoalState(const QString &sprite)
+{
+ if (m_goalState != sprite){
+ m_goalState = sprite;
+ emit goalStateChanged(sprite);
+ m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite));
+ }
+}
+
+QDeclarativeListProperty<QQuickSprite> QQuickSpriteImage::sprites()
+{
+ return QDeclarativeListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
+}
+
+void QQuickSpriteImage::createEngine()
+{
+ //TODO: delay until component complete
+ if (m_spriteEngine)
+ delete m_spriteEngine;
+ if (m_sprites.count())
+ m_spriteEngine = new QQuickSpriteEngine(m_sprites, this);
+ else
+ m_spriteEngine = 0;
+ reset();
+}
+
+static QSGGeometry::Attribute SpriteImage_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT), // tex
+};
+
+static QSGGeometry::AttributeSet SpriteImage_AttributeSet =
+{
+ 1, // Attribute Count
+ 2 * sizeof(float),
+ SpriteImage_Attributes
+};
+
+QSGGeometryNode* QQuickSpriteImage::buildNode()
+{
+ if (!m_spriteEngine) {
+ qWarning() << "SpriteImage: No sprite engine...";
+ return 0;
+ }
+
+ m_material = new QQuickSpriteMaterial();
+
+ QImage image = m_spriteEngine->assembledImage();
+ if (image.isNull())
+ return 0;
+ m_material->texture = canvas()->createTextureFromImage(image);
+ m_material->texture->setFiltering(QSGTexture::Linear);
+ m_spriteEngine->start(0);
+ m_material->interpolate = m_interpolate ? 1.0 : 0.0;
+ m_material->frameCount = m_spriteEngine->spriteFrames();
+ m_material->frameDuration = m_spriteEngine->spriteDuration();
+ m_material->animT = 0;
+ m_material->animX = m_spriteEngine->spriteX();
+ m_material->animY = m_spriteEngine->spriteY();
+ m_material->animWidth = m_spriteEngine->spriteWidth();
+ m_material->animHeight = m_spriteEngine->spriteHeight();
+ m_material->sheetWidth = image.width();
+ m_material->sheetHeight = image.height();
+ m_material->elementWidth = width();
+ m_material->elementHeight = height();
+
+ int vCount = 4;
+ int iCount = 6;
+ QSGGeometry *g = new QSGGeometry(SpriteImage_AttributeSet, vCount, iCount);
+ g->setDrawingMode(GL_TRIANGLES);
+
+ SpriteVertices *p = (SpriteVertices *) g->vertexData();
+
+ p->v1.tx = 0;
+ p->v1.ty = 0;
+
+ p->v2.tx = 1.0;
+ p->v2.ty = 0;
+
+ p->v3.tx = 0;
+ p->v3.ty = 1.0;
+
+ p->v4.tx = 1.0;
+ p->v4.ty = 1.0;
+
+ quint16 *indices = g->indexDataAsUShort();
+ indices[0] = 0;
+ indices[1] = 1;
+ indices[2] = 2;
+ indices[3] = 1;
+ indices[4] = 3;
+ indices[5] = 2;
+
+
+ m_timestamp.start();
+ m_node = new QSGGeometryNode();
+ m_node->setGeometry(g);
+ m_node->setMaterial(m_material);
+ m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+ return m_node;
+}
+
+void QQuickSpriteImage::reset()
+{
+ m_pleaseReset = true;
+}
+
+QSGNode *QQuickSpriteImage::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
+{
+ if (m_pleaseReset) {
+ delete m_node;
+ delete m_material;
+
+ m_node = 0;
+ m_material = 0;
+ m_pleaseReset = false;
+ }
+
+ prepareNextFrame();
+
+ if (m_running) {
+ update();
+ if (m_node)
+ m_node->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ return m_node;
+}
+
+void QQuickSpriteImage::prepareNextFrame()
+{
+ if (m_node == 0)
+ m_node = buildNode();
+ if (m_node == 0) //error creating node
+ return;
+
+ uint timeInt = m_timestamp.elapsed();
+ qreal time = timeInt / 1000.;
+ m_material->timestamp = time;
+ m_material->elementHeight = height();
+ m_material->elementWidth = width();
+ m_material->interpolate = m_interpolate;
+
+ //Advance State
+ m_spriteEngine->updateSprites(timeInt);
+ int curY = m_spriteEngine->spriteY();
+ if (curY != m_material->animY){
+ m_material->animT = m_spriteEngine->spriteStart()/1000.0;
+ m_material->frameCount = m_spriteEngine->spriteFrames();
+ m_material->frameDuration = m_spriteEngine->spriteDuration();
+ m_material->animX = m_spriteEngine->spriteX();
+ m_material->animY = m_spriteEngine->spriteY();
+ m_material->animWidth = m_spriteEngine->spriteWidth();
+ m_material->animHeight = m_spriteEngine->spriteHeight();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickspriteimage_p.h b/src/quick/items/qquickspriteimage_p.h
new file mode 100644
index 0000000000..fb5c115961
--- /dev/null
+++ b/src/quick/items/qquickspriteimage_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQUICKSPRITEIMAGE_P_H
+#define QQUICKSPRITEIMAGE_P_H
+
+#include <QtQuick/QQuickItem>
+#include <QTime>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGContext;
+class QQuickSprite;
+class QQuickSpriteEngine;
+class QSGGeometryNode;
+class QQuickSpriteMaterial;
+class Q_AUTOTEST_EXPORT QQuickSpriteImage : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged)
+ Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
+ //###try to share similar spriteEngines for less overhead?
+ Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
+ Q_CLASSINFO("DefaultProperty", "sprites")
+
+public:
+ explicit QQuickSpriteImage(QQuickItem *parent = 0);
+
+ QDeclarativeListProperty<QQuickSprite> sprites();
+
+ bool running() const
+ {
+ return m_running;
+ }
+
+ bool interpolate() const
+ {
+ return m_interpolate;
+ }
+
+ QString goalState() const
+ {
+ return m_goalState;
+ }
+
+signals:
+
+ void runningChanged(bool arg);
+ void interpolateChanged(bool arg);
+ void goalStateChanged(QString arg);
+
+public slots:
+
+ void jumpTo(const QString &sprite);
+ void setGoalState(const QString &sprite);
+
+ void setRunning(bool arg)
+ {
+ if (m_running != arg) {
+ m_running = arg;
+ emit runningChanged(arg);
+ }
+ }
+
+ void setInterpolate(bool arg)
+ {
+ if (m_interpolate != arg) {
+ m_interpolate = arg;
+ emit interpolateChanged(arg);
+ }
+ }
+
+private slots:
+ void createEngine();
+protected:
+ void reset();
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+private:
+ void prepareNextFrame();
+ QSGGeometryNode* buildNode();
+ QSGGeometryNode *m_node;
+ QQuickSpriteMaterial *m_material;
+ QList<QQuickSprite*> m_sprites;
+ QQuickSpriteEngine* m_spriteEngine;
+ QTime m_timestamp;
+ int m_maxFrames;
+ bool m_pleaseReset;
+ bool m_running;
+ bool m_interpolate;
+ QString m_goalState;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKSPRITEIMAGE_P_H
diff --git a/src/declarative/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index 8c53e0a63f..8c53e0a63f 100644
--- a/src/declarative/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
new file mode 100644
index 0000000000..3454ac1e11
--- /dev/null
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -0,0 +1,273 @@
+// Commit: 84c47bbb133304d7ef35642fa1fbb17619d4a43d
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKSTATEOPERATIONS_P_H
+#define QQUICKSTATEOPERATIONS_P_H
+
+#include "qquickitem.h"
+#include "qquickanchors_p.h"
+
+#include <QtQuick/private/qdeclarativestate_p.h>
+
+#include <QtDeclarative/qdeclarativescriptstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParentChangePrivate;
+class Q_AUTOTEST_EXPORT QQuickParentChange : public QDeclarativeStateOperation, public QDeclarativeActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickParentChange)
+
+ Q_PROPERTY(QQuickItem *target READ object WRITE setObject)
+ Q_PROPERTY(QQuickItem *parent READ parent WRITE setParent)
+ Q_PROPERTY(QDeclarativeScriptString x READ x WRITE setX)
+ Q_PROPERTY(QDeclarativeScriptString y READ y WRITE setY)
+ Q_PROPERTY(QDeclarativeScriptString width READ width WRITE setWidth)
+ Q_PROPERTY(QDeclarativeScriptString height READ height WRITE setHeight)
+ Q_PROPERTY(QDeclarativeScriptString scale READ scale WRITE setScale)
+ Q_PROPERTY(QDeclarativeScriptString rotation READ rotation WRITE setRotation)
+public:
+ QQuickParentChange(QObject *parent=0);
+ ~QQuickParentChange();
+
+ QQuickItem *object() const;
+ void setObject(QQuickItem *);
+
+ QQuickItem *parent() const;
+ void setParent(QQuickItem *);
+
+ QQuickItem *originalParent() const;
+
+ QDeclarativeScriptString x() const;
+ void setX(QDeclarativeScriptString x);
+ bool xIsSet() const;
+
+ QDeclarativeScriptString y() const;
+ void setY(QDeclarativeScriptString y);
+ bool yIsSet() const;
+
+ QDeclarativeScriptString width() const;
+ void setWidth(QDeclarativeScriptString width);
+ bool widthIsSet() const;
+
+ QDeclarativeScriptString height() const;
+ void setHeight(QDeclarativeScriptString height);
+ bool heightIsSet() const;
+
+ QDeclarativeScriptString scale() const;
+ void setScale(QDeclarativeScriptString scale);
+ bool scaleIsSet() const;
+
+ QDeclarativeScriptString rotation() const;
+ void setRotation(QDeclarativeScriptString rotation);
+ bool rotationIsSet() const;
+
+ virtual ActionList actions();
+
+ virtual void saveOriginals();
+ //virtual void copyOriginals(QDeclarativeActionEvent*);
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual QString typeName() const;
+ virtual bool override(QDeclarativeActionEvent*other);
+ virtual void rewind();
+ virtual void saveCurrentValues();
+};
+
+class QQuickAnchorChanges;
+class QQuickAnchorSetPrivate;
+class Q_AUTOTEST_EXPORT QQuickAnchorSet : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeScriptString left READ left WRITE setLeft RESET resetLeft)
+ Q_PROPERTY(QDeclarativeScriptString right READ right WRITE setRight RESET resetRight)
+ Q_PROPERTY(QDeclarativeScriptString horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter)
+ Q_PROPERTY(QDeclarativeScriptString top READ top WRITE setTop RESET resetTop)
+ Q_PROPERTY(QDeclarativeScriptString bottom READ bottom WRITE setBottom RESET resetBottom)
+ Q_PROPERTY(QDeclarativeScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
+ Q_PROPERTY(QDeclarativeScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline)
+ //Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill)
+ //Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn)
+
+ /*Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())*/
+
+public:
+ QQuickAnchorSet(QObject *parent=0);
+ virtual ~QQuickAnchorSet();
+
+ QDeclarativeScriptString left() const;
+ void setLeft(const QDeclarativeScriptString &edge);
+ void resetLeft();
+
+ QDeclarativeScriptString right() const;
+ void setRight(const QDeclarativeScriptString &edge);
+ void resetRight();
+
+ QDeclarativeScriptString horizontalCenter() const;
+ void setHorizontalCenter(const QDeclarativeScriptString &edge);
+ void resetHorizontalCenter();
+
+ QDeclarativeScriptString top() const;
+ void setTop(const QDeclarativeScriptString &edge);
+ void resetTop();
+
+ QDeclarativeScriptString bottom() const;
+ void setBottom(const QDeclarativeScriptString &edge);
+ void resetBottom();
+
+ QDeclarativeScriptString verticalCenter() const;
+ void setVerticalCenter(const QDeclarativeScriptString &edge);
+ void resetVerticalCenter();
+
+ QDeclarativeScriptString baseline() const;
+ void setBaseline(const QDeclarativeScriptString &edge);
+ void resetBaseline();
+
+ QQuickItem *fill() const;
+ void setFill(QQuickItem *);
+ void resetFill();
+
+ QQuickItem *centerIn() const;
+ void setCenterIn(QQuickItem *);
+ void resetCenterIn();
+
+ /*qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);*/
+
+ QQuickAnchors::Anchors usedAnchors() const;
+
+/*Q_SIGNALS:
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();*/
+
+private:
+ friend class QQuickAnchorChanges;
+ Q_DISABLE_COPY(QQuickAnchorSet)
+ Q_DECLARE_PRIVATE(QQuickAnchorSet)
+};
+
+class QQuickAnchorChangesPrivate;
+class Q_AUTOTEST_EXPORT QQuickAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickAnchorChanges)
+
+ Q_PROPERTY(QQuickItem *target READ object WRITE setObject)
+ Q_PROPERTY(QQuickAnchorSet *anchors READ anchors CONSTANT)
+
+public:
+ QQuickAnchorChanges(QObject *parent=0);
+ ~QQuickAnchorChanges();
+
+ virtual ActionList actions();
+
+ QQuickAnchorSet *anchors();
+
+ QQuickItem *object() const;
+ void setObject(QQuickItem *);
+
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual QString typeName() const;
+ virtual bool override(QDeclarativeActionEvent*other);
+ virtual bool changesBindings();
+ virtual void saveOriginals();
+ virtual bool needsCopy() { return true; }
+ virtual void copyOriginals(QDeclarativeActionEvent*);
+ virtual void clearBindings();
+ virtual void rewind();
+ virtual void saveCurrentValues();
+
+ QList<QDeclarativeAction> additionalActions();
+ virtual void saveTargetValues();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickParentChange)
+QML_DECLARE_TYPE(QQuickAnchorSet)
+QML_DECLARE_TYPE(QQuickAnchorChanges)
+
+QT_END_HEADER
+
+#endif // QQUICKSTATEOPERATIONS_P_H
+
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
new file mode 100644
index 0000000000..d01512740d
--- /dev/null
+++ b/src/quick/items/qquicktext.cpp
@@ -0,0 +1,1950 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquicktext_p.h"
+#include "qquicktext_p_p.h"
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include "qquicktextnode_p.h"
+#include "qquickimage_p_p.h"
+#include <QtQuick/private/qsgtexture_p.h>
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qabstracttextdocumentlayout.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextobject.h>
+#include <QtGui/qtextcursor.h>
+#include <QtGui/qguiapplication.h>
+
+#include <private/qdeclarativestyledtext_p.h>
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+
+#include <qmath.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
+
+class QQuickTextDocumentWithImageResources : public QTextDocument {
+ Q_OBJECT
+
+public:
+ QQuickTextDocumentWithImageResources(QQuickText *parent);
+ virtual ~QQuickTextDocumentWithImageResources();
+
+ void setText(const QString &);
+ int resourcesLoading() const { return outstanding; }
+
+protected:
+ QVariant loadResource(int type, const QUrl &name);
+
+private slots:
+ void requestFinished();
+
+private:
+ QHash<QUrl, QDeclarativePixmap *> m_resources;
+
+ int outstanding;
+ static QSet<QUrl> errors;
+};
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
+
+QString QQuickTextPrivate::elideChar = QString(0x2026);
+
+QQuickTextPrivate::QQuickTextPrivate()
+: color((QRgb)0), style(QQuickText::Normal), hAlign(QQuickText::AlignLeft),
+ vAlign(QQuickText::AlignTop), elideMode(QQuickText::ElideNone),
+ format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap), lineHeight(1),
+ lineHeightMode(QQuickText::ProportionalHeight), lineCount(1), maximumLineCount(INT_MAX),
+ maximumLineCountValid(false),
+ texture(0),
+ imageCacheDirty(false), updateOnComponentComplete(true),
+ richText(false), styledText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false),
+ requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
+ layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), textHasChanged(true),
+ naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull)
+
+#if defined(Q_OS_MAC)
+, layoutThread(0), paintingThread(0)
+#endif
+
+{
+ cacheAllTextAsImage = enableImageCache();
+}
+
+void QQuickTextPrivate::init()
+{
+ Q_Q(QQuickText);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QQuickItem::ItemHasContents);
+}
+
+QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickText *parent)
+: QTextDocument(parent), outstanding(0)
+{
+ setUndoRedoEnabled(false);
+}
+
+QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
+{
+ if (!m_resources.isEmpty())
+ qDeleteAll(m_resources);
+}
+
+QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
+{
+ QDeclarativeContext *context = qmlContext(parent());
+ QUrl url = context->resolvedUrl(name);
+
+ if (type == QTextDocument::ImageResource) {
+ QHash<QUrl, QDeclarativePixmap *>::Iterator iter = m_resources.find(url);
+
+ if (iter == m_resources.end()) {
+ QDeclarativePixmap *p = new QDeclarativePixmap(context->engine(), url);
+ iter = m_resources.insert(url, p);
+
+ if (p->isLoading()) {
+ p->connectFinished(this, SLOT(requestFinished()));
+ outstanding++;
+ }
+ }
+
+ QDeclarativePixmap *p = *iter;
+ if (p->isReady()) {
+ return p->image();
+ } else if (p->isError()) {
+ if (!errors.contains(url)) {
+ errors.insert(url);
+ qmlInfo(parent()) << p->error();
+ }
+ }
+ }
+
+ return QTextDocument::loadResource(type,url); // The *resolved* URL
+}
+
+void QQuickTextDocumentWithImageResources::requestFinished()
+{
+ outstanding--;
+ if (outstanding == 0) {
+ QQuickText *textItem = static_cast<QQuickText*>(parent());
+ QString text = textItem->text();
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+ QQuickTextPrivate *d = QQuickTextPrivate::get(textItem);
+ d->updateLayout();
+ }
+}
+
+void QQuickTextDocumentWithImageResources::setText(const QString &text)
+{
+ if (!m_resources.isEmpty()) {
+ qDeleteAll(m_resources);
+ m_resources.clear();
+ outstanding = 0;
+ }
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+}
+
+QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
+
+QQuickTextPrivate::~QQuickTextPrivate()
+{
+ delete elipsisLayout;
+ delete textLine; textLine = 0;
+}
+
+qreal QQuickTextPrivate::getImplicitWidth() const
+{
+ if (!requireImplicitWidth) {
+ // We don't calculate implicitWidth unless it is required.
+ // We need to force a size update now to ensure implicitWidth is calculated
+ QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
+ me->requireImplicitWidth = true;
+ me->updateSize();
+ }
+ return implicitWidth;
+}
+
+void QQuickTextPrivate::updateLayout()
+{
+ Q_Q(QQuickText);
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+ updateOnComponentComplete = false;
+ layoutTextElided = false;
+ // Setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ if (elipsisLayout) {
+ delete elipsisLayout;
+ elipsisLayout = 0;
+ }
+ layout.clearLayout();
+ layout.setFont(font);
+ if (!styledText) {
+ QString tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && !maximumLineCountValid && elideMode != QQuickText::ElideNone && q->widthValid() && wrapMode == QQuickText::NoWrap) {
+ QFontMetrics fm(font);
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
+ if (tmp != text) {
+ layoutTextElided = true;
+ if (!truncated) {
+ truncated = true;
+ emit q->truncatedChanged();
+ }
+ }
+ }
+ layout.setText(tmp);
+ } else {
+ singleline = false;
+ if (textHasChanged) {
+ QDeclarativeStyledText::parse(text, layout);
+ textHasChanged = false;
+ }
+ }
+ } else {
+ ensureDoc();
+ QTextBlockFormat::LineHeightTypes type;
+ type = lineHeightMode == QQuickText::FixedHeight ? QTextBlockFormat::FixedHeight : QTextBlockFormat::ProportionalHeight;
+ QTextBlockFormat blockFormat;
+ blockFormat.setLineHeight((lineHeightMode == QQuickText::FixedHeight ? lineHeight : lineHeight * 100), type);
+ for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) {
+ QTextCursor cursor(it);
+ cursor.mergeBlockFormat(blockFormat);
+ }
+ }
+
+ updateSize();
+}
+
+void QQuickTextPrivate::updateSize()
+{
+ Q_Q(QQuickText);
+
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+
+ if (!requireImplicitWidth) {
+ emit q->implicitWidthChanged();
+ // if the implicitWidth is used, then updateSize() has already been called (recursively)
+ if (requireImplicitWidth)
+ return;
+ }
+
+ invalidateImageCache();
+
+ QFontMetrics fm(font);
+ if (text.isEmpty()) {
+ q->setImplicitSize(0, fm.height());
+ paintedSize = QSize(0, fm.height());
+ emit q->paintedSizeChanged();
+ q->update();
+ return;
+ }
+
+ int dy = q->height();
+ QSize size(0, 0);
+
+#if defined(Q_OS_MAC)
+ layoutThread = QThread::currentThread();
+#endif
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ QRect textRect = setupTextLayout();
+ layedOutTextRect = textRect;
+ size = textRect.size();
+ dy -= size.height();
+ } else {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ ensureDoc();
+ doc->setDefaultFont(font);
+ QQuickText::HAlignment horizontalAlignment = q->effectiveHAlign();
+ if (rightToLeftText) {
+ if (horizontalAlignment == QQuickText::AlignLeft)
+ horizontalAlignment = QQuickText::AlignRight;
+ else if (horizontalAlignment == QQuickText::AlignRight)
+ horizontalAlignment = QQuickText::AlignLeft;
+ }
+ QTextOption option;
+ option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
+ option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
+ option.setUseDesignMetrics(true);
+ doc->setDefaultTextOption(option);
+ if (requireImplicitWidth && q->widthValid()) {
+ doc->setTextWidth(-1);
+ naturalWidth = doc->idealWidth();
+ }
+ if (wrapMode != QQuickText::NoWrap && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ QSize dsize = doc->size().toSize();
+ layedOutTextRect = QRect(QPoint(0,0), dsize);
+ size = QSize(int(doc->idealWidth()),dsize.height());
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QQuickText::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QQuickText::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ //### need to comfirm cost of always setting these for richText
+ internalWidthUpdate = true;
+ qreal iWidth = -1;
+ if (!q->widthValid())
+ iWidth = size.width();
+ else if (requireImplicitWidth)
+ iWidth = naturalWidth;
+ if (iWidth > -1)
+ q->setImplicitSize(iWidth, size.height());
+ internalWidthUpdate = false;
+
+ if (iWidth == -1)
+ q->setImplicitHeight(size.height());
+ if (paintedSize != size) {
+ paintedSize = size;
+ emit q->paintedSizeChanged();
+ }
+ q->update();
+}
+
+QQuickTextLine::QQuickTextLine()
+ : QObject(), m_line(0), m_height(0)
+{
+}
+
+void QQuickTextLine::setLine(QTextLine *line)
+{
+ m_line = line;
+}
+
+int QQuickTextLine::number() const
+{
+ if (m_line)
+ return m_line->lineNumber();
+ return 0;
+}
+
+qreal QQuickTextLine::width() const
+{
+ if (m_line)
+ return m_line->width();
+ return 0;
+}
+
+void QQuickTextLine::setWidth(qreal width)
+{
+ if (m_line)
+ m_line->setLineWidth(width);
+}
+
+qreal QQuickTextLine::height() const
+{
+ if (m_height)
+ return m_height;
+ if (m_line)
+ return m_line->height();
+ return 0;
+}
+
+void QQuickTextLine::setHeight(qreal height)
+{
+ if (m_line)
+ m_line->setPosition(QPointF(m_line->x(), m_line->y() - m_line->height() + height));
+ m_height = height;
+}
+
+qreal QQuickTextLine::x() const
+{
+ if (m_line)
+ return m_line->x();
+ return 0;
+}
+
+void QQuickTextLine::setX(qreal x)
+{
+ if (m_line)
+ m_line->setPosition(QPointF(x, m_line->y()));
+}
+
+qreal QQuickTextLine::y() const
+{
+ if (m_line)
+ return m_line->y();
+ return 0;
+}
+
+void QQuickTextLine::setY(qreal y)
+{
+ if (m_line)
+ m_line->setPosition(QPointF(m_line->x(), y));
+}
+
+void QQuickText::doLayout()
+{
+ Q_D(QQuickText);
+ d->updateSize();
+}
+
+bool QQuickTextPrivate::isLineLaidOutConnected()
+{
+ static int idx = this->signalIndex("lineLaidOut(QQuickTextLine*)");
+ return this->isSignalConnected(idx);
+}
+
+void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, qreal elideWidth = 0)
+{
+ Q_Q(QQuickText);
+
+#if defined(Q_OS_MAC)
+ if (QThread::currentThread() != paintingThread) {
+#endif
+ if (!line.lineNumber())
+ linesRects.clear();
+
+ if (!textLine)
+ textLine = new QQuickTextLine;
+ textLine->setLine(&line);
+ textLine->setY(height);
+ textLine->setHeight(0);
+
+ // use the text item's width by default if it has one and wrap is on
+ if (q->widthValid() && q->wrapMode() != QQuickText::NoWrap)
+ textLine->setWidth(q->width() - elideWidth);
+ else
+ textLine->setWidth(INT_MAX);
+ if (lineHeight != 1.0)
+ textLine->setHeight((lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight);
+
+ emit q->lineLaidOut(textLine);
+
+ linesRects << QRectF(textLine->x(), textLine->y(), textLine->width(), textLine->height());
+ height += textLine->height();
+
+#if defined(Q_OS_MAC)
+ } else {
+ if (line.lineNumber() < linesRects.count()) {
+ QRectF r = linesRects.at(line.lineNumber());
+ line.setLineWidth(r.width());
+ line.setPosition(r.topLeft());
+ }
+ }
+#endif
+}
+
+/*!
+ Lays out the QQuickTextPrivate::layout QTextLayout in the constraints of the QQuickText.
+
+ Returns the size of the final text. This can be used to position the text vertically (the text is
+ already absolutely positioned horizontally).
+*/
+QRect QQuickTextPrivate::setupTextLayout()
+{
+ // ### text layout handling should be profiled and optimized as needed
+ // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+ Q_Q(QQuickText);
+ layout.setCacheEnabled(true);
+
+ qreal lineWidth = 0;
+ int visibleCount = 0;
+
+ //set manual width
+ if (q->widthValid())
+ lineWidth = q->width();
+
+ QTextOption textOption = layout.textOption();
+ textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
+ textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
+ if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
+ textOption.setUseDesignMetrics(true);
+ layout.setTextOption(textOption);
+
+ QFontMetrics fm(layout.font());
+ elidePos = QPointF();
+
+ if (requireImplicitWidth && q->widthValid()) {
+ // requires an extra layout
+ QString elidedText;
+ if (layoutTextElided) {
+ // We have provided elided text to the layout, but we must calculate unelided width.
+ elidedText = layout.text();
+ layout.setText(text);
+ }
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+ layout.endLayout();
+ QRectF br;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ br = br.united(line.naturalTextRect());
+ }
+ naturalWidth = br.width();
+ if (layoutTextElided)
+ layout.setText(elidedText);
+ }
+
+ qreal height = 0;
+ QRectF br;
+
+ bool truncate = false;
+ bool customLayout = isLineLaidOutConnected();
+ bool elideEnabled = elideMode == QQuickText::ElideRight && q->widthValid();
+
+ layout.beginLayout();
+ if (!lineWidth)
+ lineWidth = INT_MAX;
+ int linesLeft = maximumLineCount;
+ int visibleTextLength = 0;
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+
+ visibleCount++;
+
+ qreal preLayoutHeight = height;
+ if (customLayout) {
+ setupCustomLineGeometry(line, height);
+ } else if (lineWidth) {
+ line.setLineWidth(lineWidth);
+ line.setPosition(QPointF(line.position().x(), height));
+ height += (lineHeightMode == QQuickText::FixedHeight) ? lineHeight : line.height() * lineHeight;
+ }
+
+ bool elide = false;
+ if (elideEnabled && q->heightValid() && height > q->height()) {
+ // This line does not fit in the remaining area.
+ elide = true;
+ if (visibleCount > 1) {
+ --visibleCount;
+ height = preLayoutHeight;
+ line.setLineWidth(0.0);
+ line.setPosition(QPointF(FLT_MAX,FLT_MAX));
+ line = layout.lineAt(visibleCount-1);
+ }
+ } else {
+ visibleTextLength += line.textLength();
+ }
+
+ if (elide || (maximumLineCountValid && --linesLeft == 0)) {
+ if (visibleTextLength < text.length()) {
+ truncate = true;
+ if (elideEnabled) {
+ qreal elideWidth = fm.width(elideChar);
+ // Need to correct for alignment
+ if (customLayout)
+ setupCustomLineGeometry(line, height, elideWidth);
+ else
+ line.setLineWidth(lineWidth - elideWidth);
+ if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
+ line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
+ elidePos.setX(line.naturalTextRect().left() - elideWidth);
+ } else {
+ elidePos.setX(line.naturalTextRect().right());
+ }
+ elidePos.setY(line.position().y());
+ if (!elipsisLayout)
+ elipsisLayout = new QTextLayout(elideChar, layout.font());
+ elipsisLayout->beginLayout();
+ QTextLine el = elipsisLayout->createLine();
+ el.setPosition(elidePos);
+ elipsisLayout->endLayout();
+ br = br.united(el.naturalTextRect());
+ }
+ br = br.united(line.naturalTextRect());
+ break;
+ }
+ }
+ br = br.united(line.naturalTextRect());
+ }
+ layout.endLayout();
+
+ //Update truncated
+ if (truncated != truncate) {
+ truncated = truncate;
+ emit q->truncatedChanged();
+ }
+
+ if (!customLayout)
+ br.setHeight(height);
+
+ if (!q->widthValid())
+ naturalWidth = br.width();
+
+ //Update the number of visible lines
+ if (lineCount != visibleCount) {
+ lineCount = visibleCount;
+ emit q->lineCountChanged();
+ }
+
+ return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
+}
+
+/*!
+ Returns a painted version of the QQuickTextPrivate::layout QTextLayout.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QQuickTextPrivate::textLayoutImage(bool drawStyle)
+{
+ QSize size = layedOutTextRect.size();
+
+ //paint text
+ QPixmap img(size);
+ if (!size.isEmpty()) {
+ img.fill(Qt::transparent);
+/*#ifdef Q_OS_MAC // Fails on CocoaX64
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif*/
+ QPainter p(&img);
+/*#ifdef Q_OS_MAC // Fails on CocoaX64
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif*/
+ drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle);
+ }
+ return img;
+}
+
+/*!
+ Paints the QQuickTextPrivate::layout QTextLayout into \a painter at \a pos. If
+ \a drawStyle is true, the style color overrides all colors in the document.
+*/
+void QQuickTextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
+{
+ if (drawStyle)
+ painter->setPen(styleColor);
+ else
+ painter->setPen(color);
+ painter->setFont(font);
+ layout.draw(painter, pos);
+ if (!elidePos.isNull())
+ painter->drawText(pos + elidePos, elideChar);
+}
+
+/*!
+ Returns a painted version of the QQuickTextPrivate::doc QTextDocument.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QQuickTextPrivate::textDocumentImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+/*#ifdef Q_OS_MAC // Fails on CocoaX64
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif*/
+ QPainter p(&img);
+/*#ifdef Q_OS_MAC // Fails on CocoaX64
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif*/
+
+ QAbstractTextDocumentLayout::PaintContext context;
+
+ QTextOption oldOption(doc->defaultTextOption());
+ if (drawStyle) {
+ context.palette.setColor(QPalette::Text, styleColor);
+ QTextOption colorOption(doc->defaultTextOption());
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ context.palette.setColor(QPalette::Text, color);
+ }
+ doc->documentLayout()->draw(&p, context);
+ if (drawStyle)
+ doc->setDefaultTextOption(oldOption);
+ return img;
+}
+
+/*!
+ Mark the image cache as dirty.
+*/
+void QQuickTextPrivate::invalidateImageCache()
+{
+ Q_Q(QQuickText);
+
+ if (richTextAsImage || cacheAllTextAsImage || (qmlDisableDistanceField() && style != QQuickText::Normal)) { // If actually using the image cache
+ if (imageCacheDirty)
+ return;
+
+ imageCacheDirty = true;
+
+ if (q->isComponentComplete())
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User));
+ } else if (q->isComponentComplete())
+ q->update();
+}
+
+/*!
+ Tests if the image cache is dirty, and repaints it if it is.
+*/
+void QQuickTextPrivate::checkImageCache()
+{
+ Q_Q(QQuickText);
+
+ if (!imageCacheDirty)
+ return;
+
+ if (text.isEmpty()) {
+
+ imageCache = QPixmap();
+
+ } else {
+
+ QPixmap textImage;
+ QPixmap styledImage;
+
+ if (richText) {
+ textImage = textDocumentImage(false);
+ if (style != QQuickText::Normal)
+ styledImage = textDocumentImage(true); //### should use styleColor
+ } else {
+ textImage = textLayoutImage(false);
+ if (style != QQuickText::Normal)
+ styledImage = textLayoutImage(true); //### should use styleColor
+ }
+
+ switch (style) {
+ case QQuickText::Outline:
+ imageCache = drawOutline(textImage, styledImage);
+ break;
+ case QQuickText::Sunken:
+ imageCache = drawOutline(textImage, styledImage, -1);
+ break;
+ case QQuickText::Raised:
+ imageCache = drawOutline(textImage, styledImage, 1);
+ break;
+ default:
+ imageCache = textImage;
+ break;
+ }
+
+ }
+
+ imageCacheDirty = false;
+ textureImageCacheDirty = true;
+ q->update();
+}
+
+/*!
+ Ensures the QQuickTextPrivate::doc variable is set to a valid text document
+*/
+void QQuickTextPrivate::ensureDoc()
+{
+ if (!doc) {
+ Q_Q(QQuickText);
+ doc = new QQuickTextDocumentWithImageResources(q);
+ doc->setDocumentMargin(0);
+ }
+}
+
+/*!
+ Draw \a styleSource as an outline around \a source and return the new image.
+*/
+QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(0, 0);
+ pos += QPoint(-1, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(2, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(-1, -1);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(0, 2);
+ ppm.drawPixmap(pos, styleSource);
+
+ pos += QPoint(0, -1);
+ ppm.drawPixmap(pos, source);
+ ppm.end();
+
+ return img;
+}
+
+/*!
+ Draw \a styleSource below \a source at \a yOffset and return the new image.
+*/
+QPixmap QQuickTextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ ppm.drawPixmap(QPoint(0, yOffset), styleSource);
+ ppm.drawPixmap(0, 0, source);
+
+ ppm.end();
+
+ return img;
+}
+
+/*!
+ \qmlclass Text QQuickText
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ Text items can display both plain and rich text. For example, red text with
+ a specific font and size can be defined like this:
+
+ \qml
+ Text {
+ text: "Hello World!"
+ font.family: "Helvetica"
+ font.pointSize: 24
+ color: "red"
+ }
+ \endqml
+
+ Rich text is defined using HTML-style markup:
+
+ \qml
+ Text {
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \l wrapMode is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \l elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Note that the \l{Supported HTML Subset} is limited. Also, if the text contains
+ HTML img tags that load remote images, the text is reloaded.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+
+ \sa {declarative/text/fonts}{Fonts example}
+*/
+QQuickText::QQuickText(QQuickItem *parent)
+: QQuickImplicitSizeItem(*(new QQuickTextPrivate), parent)
+{
+ Q_D(QQuickText);
+ d->init();
+}
+
+QQuickText::~QQuickText()
+{
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Text::clip
+ This property holds whether the text is clipped.
+
+ Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
+
+ If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Text::onLineLaidOut(line)
+
+ This handler is called for every line during the layout process.
+ This gives the opportunity to position and resize a line as it is being laid out.
+ It can for example be used to create columns or lay out text around objects.
+
+ The properties of a line are:
+ \list
+ \o number (read-only)
+ \o x
+ \o y
+ \o width
+ \o height
+ \endlist
+
+ For example, this will move the first 5 lines of a text element by 100 pixels to the right:
+ \code
+ onLineLaidOut: {
+ if (line.number < 5) {
+ line.x = line.x + 100
+ line.width = line.width - 100
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \qmlsignal QtQuick2::Text::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+
+ \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
+
+ The example code will display the text
+ "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
+
+ Clicking on the highlighted link will output
+ \tt{http://qt.nokia.com link activated} to the console.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::Text::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Text::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::Text::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::Text::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+QFont QQuickText::font() const
+{
+ Q_D(const QQuickText);
+ return d->sourceFont;
+}
+
+void QQuickText::setFont(const QFont &font)
+{
+ Q_D(QQuickText);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+
+ if (oldFont != d->font)
+ d->updateLayout();
+
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty string QtQuick2::Text::text
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as styled text. This determination is made using Qt::mightBeRichText().
+*/
+QString QQuickText::text() const
+{
+ Q_D(const QQuickText);
+ return d->text;
+}
+
+void QQuickText::setText(const QString &n)
+{
+ Q_D(QQuickText);
+ if (d->text == n)
+ return;
+
+ d->richText = d->format == RichText;
+ d->styledText = d->format == StyledText || (d->format == AutoText && Qt::mightBeRichText(n));
+ d->text = n;
+ if (isComponentComplete()) {
+ if (d->richText) {
+ d->ensureDoc();
+ d->doc->setText(n);
+ d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
+ d->richTextAsImage = enableImageCache();
+ } else {
+ d->rightToLeftText = d->text.isRightToLeft();
+ }
+ d->determineHorizontalAlignment();
+ }
+ d->textHasChanged = true;
+ d->updateLayout();
+ emit textChanged(d->text);
+}
+
+/*!
+ \qmlproperty color QtQuick2::Text::color
+
+ The text color.
+
+ An example of green text defined using hexadecimal notation:
+ \qml
+ Text {
+ color: "#00FF00"
+ text: "green text"
+ }
+ \endqml
+
+ An example of steel blue text defined using an SVG color name:
+ \qml
+ Text {
+ color: "steelblue"
+ text: "blue text"
+ }
+ \endqml
+*/
+QColor QQuickText::color() const
+{
+ Q_D(const QQuickText);
+ return d->color;
+}
+
+void QQuickText::setColor(const QColor &color)
+{
+ Q_D(QQuickText);
+ if (d->color == color)
+ return;
+
+ d->color = color;
+ d->invalidateImageCache();
+ emit colorChanged(d->color);
+}
+/*!
+ \qmlproperty enumeration QtQuick2::Text::style
+
+ Set an additional text style.
+
+ Supported text styles are:
+ \list
+ \o Text.Normal - the default
+ \o Text.Outline
+ \o Text.Raised
+ \o Text.Sunken
+ \endlist
+
+ \qml
+ Row {
+ Text { font.pointSize: 24; text: "Normal" }
+ Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
+ Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" }
+ Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
+ }
+ \endqml
+
+ \image declarative-textstyle.png
+*/
+QQuickText::TextStyle QQuickText::style() const
+{
+ Q_D(const QQuickText);
+ return d->style;
+}
+
+void QQuickText::setStyle(QQuickText::TextStyle style)
+{
+ Q_D(QQuickText);
+ if (d->style == style)
+ return;
+
+ // changing to/from Normal requires the boundingRect() to change
+ if (isComponentComplete() && (d->style == Normal || style == Normal))
+ update();
+ d->style = style;
+ d->invalidateImageCache();
+ emit styleChanged(d->style);
+}
+
+/*!
+ \qmlproperty color QtQuick2::Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+
+ \qml
+ Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" }
+ \endqml
+
+ \sa style
+ */
+QColor QQuickText::styleColor() const
+{
+ Q_D(const QQuickText);
+ return d->styleColor;
+}
+
+void QQuickText::setStyleColor(const QColor &color)
+{
+ Q_D(QQuickText);
+ if (d->styleColor == color)
+ return;
+
+ d->styleColor = color;
+ d->invalidateImageCache();
+ emit styleColorChanged(d->styleColor);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::Text::verticalAlignment
+ \qmlproperty enumeration QtQuick2::Text::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is vertically aligned to the top. Horizontal
+ alignment follows the natural alignment of the text, for example text that is read
+ from left to right will be aligned to the left.
+
+ The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and
+ \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom
+ and \c Text.AlignVCenter.
+
+ Note that for a single line of text, the size of the text is the area of the text. In this common case,
+ all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will
+ need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to
+ that of the parent.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of Text, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QQuickText::HAlignment QQuickText::hAlign() const
+{
+ Q_D(const QQuickText);
+ return d->hAlign;
+}
+
+void QQuickText::setHAlign(HAlignment align)
+{
+ Q_D(QQuickText);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete())
+ d->updateLayout();
+}
+
+void QQuickText::resetHAlign()
+{
+ Q_D(QQuickText);
+ d->hAlignImplicit = true;
+ if (isComponentComplete() && d->determineHorizontalAlignment())
+ d->updateLayout();
+}
+
+QQuickText::HAlignment QQuickText::effectiveHAlign() const
+{
+ Q_D(const QQuickText);
+ QQuickText::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QQuickText::AlignLeft:
+ effectiveAlignment = QQuickText::AlignRight;
+ break;
+ case QQuickText::AlignRight:
+ effectiveAlignment = QQuickText::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QQuickTextPrivate::setHAlign(QQuickText::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QQuickText);
+ if (hAlign != alignment || forceAlign) {
+ QQuickText::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+
+ emit q->horizontalAlignmentChanged(hAlign);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QQuickTextPrivate::determineHorizontalAlignment()
+{
+ if (hAlignImplicit) {
+ bool alignToRight = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
+ return setHAlign(alignToRight ? QQuickText::AlignRight : QQuickText::AlignLeft);
+ }
+ return false;
+}
+
+void QQuickTextPrivate::mirrorChange()
+{
+ Q_Q(QQuickText);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QQuickText::AlignRight || hAlign == QQuickText::AlignLeft)) {
+ updateLayout();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+QTextDocument *QQuickTextPrivate::textDocument()
+{
+ return doc;
+}
+
+QQuickText::VAlignment QQuickText::vAlign() const
+{
+ Q_D(const QQuickText);
+ return d->vAlign;
+}
+
+void QQuickText::setVAlign(VAlignment align)
+{
+ Q_D(QQuickText);
+ if (d->vAlign == align)
+ return;
+
+ d->vAlign = align;
+ emit verticalAlignmentChanged(align);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::wrapMode
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set. wrapMode can be one of:
+
+ \list
+ \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width.
+ \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width.
+ \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+*/
+QQuickText::WrapMode QQuickText::wrapMode() const
+{
+ Q_D(const QQuickText);
+ return d->wrapMode;
+}
+
+void QQuickText::setWrapMode(WrapMode mode)
+{
+ Q_D(QQuickText);
+ if (mode == d->wrapMode)
+ return;
+
+ d->wrapMode = mode;
+ d->updateLayout();
+
+ emit wrapModeChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::Text::lineCount
+
+ Returns the number of lines visible in the text item.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount
+*/
+int QQuickText::lineCount() const
+{
+ Q_D(const QQuickText);
+ return d->lineCount;
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Text::truncated
+
+ Returns true if the text has been truncated due to \l maximumLineCount
+ or \l elide.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount, elide
+*/
+bool QQuickText::truncated() const
+{
+ Q_D(const QQuickText);
+ return d->truncated;
+}
+
+/*!
+ \qmlproperty int QtQuick2::Text::maximumLineCount
+
+ Set this property to limit the number of lines that the text item will show.
+ If elide is set to Text.ElideRight, the text will be elided appropriately.
+ By default, this is the value of the largest possible integer.
+
+ This property is not supported for rich text.
+
+ \sa lineCount, elide
+*/
+int QQuickText::maximumLineCount() const
+{
+ Q_D(const QQuickText);
+ return d->maximumLineCount;
+}
+
+void QQuickText::setMaximumLineCount(int lines)
+{
+ Q_D(QQuickText);
+
+ d->maximumLineCountValid = lines==INT_MAX ? false : true;
+ if (d->maximumLineCount != lines) {
+ d->maximumLineCount = lines;
+ d->updateLayout();
+ emit maximumLineCountChanged();
+ }
+}
+
+void QQuickText::resetMaximumLineCount()
+{
+ Q_D(QQuickText);
+ setMaximumLineCount(INT_MAX);
+ d->elidePos = QPointF();
+ if (d->truncated != false) {
+ d->truncated = false;
+ emit truncatedChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are:
+
+ \list
+ \o Text.AutoText (default)
+ \o Text.PlainText
+ \o Text.StyledText
+ \o Text.RichText
+ \endlist
+
+ If the text format is \c Text.AutoText the text element
+ will automatically determine whether the text should be treated as
+ styled text. This determination is made using Qt::mightBeRichText().
+
+ Text.StyledText is an optimized format supporting some basic text
+ styling markup, in the style of html 3.2:
+
+ \code
+ <b></b> - bold
+ <i></i> - italic
+ <br> - new line
+ <p> - paragraph
+ <u> - underlined text
+ <font color="color_name" size="1-7"></font>
+ <h1> to <h6> - headers
+ <a href=""> - anchor
+ <ol type="">, <ul type=""> and <li> - ordered and unordered lists
+ &gt; &lt; &amp;
+ \endcode
+
+ \c Text.StyledText parser is strict, requiring tags to be correctly nested.
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ Text {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+QQuickText::TextFormat QQuickText::textFormat() const
+{
+ Q_D(const QQuickText);
+ return d->format;
+}
+
+void QQuickText::setTextFormat(TextFormat format)
+{
+ Q_D(QQuickText);
+ if (format == d->format)
+ return;
+ d->format = format;
+ bool wasRich = d->richText;
+ d->richText = format == RichText;
+ d->styledText = format == StyledText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (isComponentComplete()) {
+ if (!wasRich && d->richText) {
+ d->ensureDoc();
+ d->doc->setText(d->text);
+ d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
+ d->richTextAsImage = enableImageCache();
+ } else {
+ d->rightToLeftText = d->text.isRightToLeft();
+ }
+ d->determineHorizontalAlignment();
+ }
+ d->updateLayout();
+
+ emit textFormatChanged(d->format);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with rich text.
+
+ Eliding can be:
+ \list
+ \o Text.ElideNone - the default
+ \o Text.ElideLeft
+ \o Text.ElideMiddle
+ \o Text.ElideRight
+ \endlist
+
+ If this property is set to Text.ElideRight, it can be used with multiline
+ text. The text will only elide if \c maximumLineCount, or \c height has been set.
+ If both \c maximumLineCount and \c height are set, \c maximumLineCount will
+ apply unless the lines do not fit in the height allowed.
+
+ If the text is a multi-length string, and the mode is not \c Text.ElideNone,
+ the first string that fits will be used, otherwise the last will be elided.
+
+ Multi-length strings are ordered from longest to shortest, separated by the
+ Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
+*/
+QQuickText::TextElideMode QQuickText::elideMode() const
+{
+ Q_D(const QQuickText);
+ return d->elideMode;
+}
+
+void QQuickText::setElideMode(QQuickText::TextElideMode mode)
+{
+ Q_D(QQuickText);
+ if (mode == d->elideMode)
+ return;
+
+ d->elideMode = mode;
+ d->updateLayout();
+
+ emit elideModeChanged(d->elideMode);
+}
+
+/*! \internal */
+QRectF QQuickText::boundingRect() const
+{
+ Q_D(const QQuickText);
+
+ QRect rect = d->layedOutTextRect;
+ if (d->style != Normal)
+ rect.adjust(-1, 0, 1, 2);
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ int h = height();
+ switch (d->vAlign) {
+ case AlignTop:
+ break;
+ case AlignBottom:
+ rect.moveTop(h - rect.height());
+ break;
+ case AlignVCenter:
+ rect.moveTop((h - rect.height()) / 2);
+ break;
+ }
+
+ return QRectF(rect);
+}
+
+/*! \internal */
+void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickText);
+ bool elide = d->elideMode != QQuickText::ElideNone && widthValid();
+ if ((!d->internalWidthUpdate
+ && (newGeometry.width() != oldGeometry.width() || (elide && newGeometry.height() != oldGeometry.height())))
+ && (d->wrapMode != QQuickText::NoWrap
+ || d->elideMode != QQuickText::ElideNone
+ || d->hAlign != QQuickText::AlignLeft)) {
+ if ((d->singleline || d->maximumLineCountValid || heightValid()) && elide) {
+ // We need to re-elide
+ d->updateLayout();
+ } else {
+ // We just need to re-layout
+ d->updateSize();
+ }
+ }
+
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ Q_D(QQuickText);
+
+ if (d->text.isEmpty()) {
+ delete oldNode;
+ return 0;
+ }
+
+ QRectF bounds = boundingRect();
+
+ // We need to make sure the layout is done in the current thread
+#if defined(Q_OS_MAC)
+ d->paintingThread = QThread::currentThread();
+ if (d->layoutThread != d->paintingThread)
+ d->updateLayout();
+#endif
+
+ // XXX todo - some styled text can be done by the QQuickTextNode
+ if (d->richTextAsImage || d->cacheAllTextAsImage || (qmlDisableDistanceField() && d->style != Normal)) {
+ bool wasDirty = d->textureImageCacheDirty;
+ d->textureImageCacheDirty = false;
+
+ if (d->imageCache.isNull()) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGImageNode *node = 0;
+ if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsTexture) {
+ delete oldNode;
+ node = QQuickItemPrivate::get(this)->sceneGraphContext()->createImageNode();
+ d->texture = new QSGPlainTexture();
+ wasDirty = true;
+ d->nodeType = QQuickTextPrivate::NodeIsTexture;
+ } else {
+ node = static_cast<QSGImageNode *>(oldNode);
+ Q_ASSERT(d->texture);
+ }
+
+ if (wasDirty) {
+ qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->imageCache.toImage());
+ node->setTexture(0);
+ node->setTexture(d->texture);
+ }
+
+ node->setTargetRect(QRectF(bounds.x(), bounds.y(), d->imageCache.width(), d->imageCache.height()));
+ node->setSourceRect(QRectF(0, 0, 1, 1));
+ node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ node->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that..
+ node->update();
+
+ return node;
+
+ } else {
+ QQuickTextNode *node = 0;
+ if (!oldNode || d->nodeType != QQuickTextPrivate::NodeIsText) {
+ delete oldNode;
+ node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
+ d->nodeType = QQuickTextPrivate::NodeIsText;
+ } else {
+ node = static_cast<QQuickTextNode *>(oldNode);
+ }
+
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
+ if (d->richText) {
+ d->ensureDoc();
+ node->addTextDocument(bounds.topLeft(), d->doc, d->color, d->style, d->styleColor);
+
+ } else {
+ node->addTextLayout(QPoint(0, bounds.y()), &d->layout, d->color, d->style, d->styleColor);
+ if (d->elipsisLayout)
+ node->addTextLayout(QPoint(0, bounds.y()), d->elipsisLayout, d->color, d->style, d->styleColor);
+ }
+
+ return node;
+ }
+}
+
+bool QQuickText::event(QEvent *e)
+{
+ Q_D(QQuickText);
+ if (e->type() == QEvent::User) {
+ d->checkImageCache();
+ return true;
+ } else {
+ return QQuickImplicitSizeItem::event(e);
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick2::Text::paintedWidth
+
+ Returns the width of the text, including width past the width
+ which is covered due to insufficient wrapping if WrapMode is set.
+*/
+qreal QQuickText::paintedWidth() const
+{
+ Q_D(const QQuickText);
+ return d->paintedSize.width();
+}
+
+/*!
+ \qmlproperty real QtQuick2::Text::paintedHeight
+
+ Returns the height of the text, including height past the height
+ which is covered due to there being more text than fits in the set height.
+*/
+qreal QQuickText::paintedHeight() const
+{
+ Q_D(const QQuickText);
+ return d->paintedSize.height();
+}
+
+/*!
+ \qmlproperty real QtQuick2::Text::lineHeight
+
+ Sets the line height for the text.
+ The value can be in pixels or a multiplier depending on lineHeightMode.
+
+ The default value is a multiplier of 1.0.
+ The line height must be a positive value.
+*/
+qreal QQuickText::lineHeight() const
+{
+ Q_D(const QQuickText);
+ return d->lineHeight;
+}
+
+void QQuickText::setLineHeight(qreal lineHeight)
+{
+ Q_D(QQuickText);
+
+ if ((d->lineHeight == lineHeight) || (lineHeight < 0.0))
+ return;
+
+ d->lineHeight = lineHeight;
+ d->updateLayout();
+ emit lineHeightChanged(lineHeight);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::Text::lineHeightMode
+
+ This property determines how the line height is specified.
+ The possible values are:
+
+ \list
+ \o Text.ProportionalHeight (default) - this sets the spacing proportional to the
+ line (as a multiplier). For example, set to 2 for double spacing.
+ \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels).
+ \endlist
+*/
+QQuickText::LineHeightMode QQuickText::lineHeightMode() const
+{
+ Q_D(const QQuickText);
+ return d->lineHeightMode;
+}
+
+void QQuickText::setLineHeightMode(LineHeightMode mode)
+{
+ Q_D(QQuickText);
+ if (mode == d->lineHeightMode)
+ return;
+
+ d->lineHeightMode = mode;
+ d->updateLayout();
+
+ emit lineHeightModeChanged(mode);
+}
+
+/*!
+ Returns the number of resources (images) that are being loaded asynchronously.
+*/
+int QQuickText::resourcesLoading() const
+{
+ Q_D(const QQuickText);
+ return d->doc ? d->doc->resourcesLoading() : 0;
+}
+
+/*! \internal */
+void QQuickText::componentComplete()
+{
+ Q_D(QQuickText);
+ if (d->updateOnComponentComplete) {
+ if (d->richText) {
+ d->ensureDoc();
+ d->doc->setText(d->text);
+ d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
+ d->richTextAsImage = enableImageCache();
+ } else {
+ d->rightToLeftText = d->text.isRightToLeft();
+ }
+ d->determineHorizontalAlignment();
+ }
+ QQuickItem::componentComplete();
+ if (d->updateOnComponentComplete)
+ d->updateLayout();
+}
+
+
+QString QQuickTextPrivate::anchorAt(const QPointF &mousePos)
+{
+ if (styledText) {
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ if (line.naturalTextRect().contains(mousePos)) {
+ int charPos = line.xToCursor(mousePos.x());
+ foreach (const QTextLayout::FormatRange &formatRange, layout.additionalFormats()) {
+ if (formatRange.format.isAnchor()
+ && charPos >= formatRange.start
+ && charPos <= formatRange.start + formatRange.length) {
+ return formatRange.format.anchorHref();
+ }
+ }
+ break;
+ }
+ }
+ }
+ return QString();
+}
+
+bool QQuickTextPrivate::isLinkActivatedConnected()
+{
+ static int idx = this->signalIndex("linkActivated(QString)");
+ return this->isSignalConnected(idx);
+}
+
+/*! \internal */
+void QQuickText::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickText);
+
+ if (d->isLinkActivatedConnected()) {
+ if (d->styledText)
+ d->activeLink = d->anchorAt(event->localPos());
+ else if (d->richText && d->doc)
+ d->activeLink = d->doc->documentLayout()->anchorAt(event->localPos());
+ }
+
+ if (d->activeLink.isEmpty())
+ event->setAccepted(false);
+
+ // ### may malfunction if two of the same links are clicked & dragged onto each other)
+
+ if (!event->isAccepted())
+ QQuickItem::mousePressEvent(event);
+
+}
+
+/*! \internal */
+void QQuickText::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickText);
+
+ // ### confirm the link, and send a signal out
+
+ QString link;
+ if (d->isLinkActivatedConnected()) {
+ if (d->styledText)
+ link = d->anchorAt(event->localPos());
+ else if (d->richText && d->doc)
+ link = d->doc->documentLayout()->anchorAt(event->localPos());
+ }
+
+ if (!link.isEmpty() && d->activeLink == link)
+ emit linkActivated(d->activeLink);
+ else
+ event->setAccepted(false);
+
+ if (!event->isAccepted())
+ QQuickItem::mouseReleaseEvent(event);
+}
+
+QT_END_NAMESPACE
+
+#include "qquicktext.moc"
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
new file mode 100644
index 0000000000..3a9f691c53
--- /dev/null
+++ b/src/quick/items/qquicktext_p.h
@@ -0,0 +1,251 @@
+// Commit: 27e4302b7f45f22180693d26747f419177c81e27
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKTEXT_P_H
+#define QQUICKTEXT_P_H
+
+#include "qquickimplicitsizeitem_p.h"
+
+#include <private/qtquickglobal_p.h>
+
+#include <QtGui/qtextoption.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTextPrivate;
+class QQuickTextLine;
+class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(TextStyle)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(TextElideMode)
+ Q_ENUMS(WrapMode)
+ Q_ENUMS(LineHeightMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(TextStyle style READ style WRITE setStyle NOTIFY styleChanged)
+ Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor NOTIFY styleColorChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
+ Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged)
+ Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount)
+
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode?
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged)
+ Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged)
+
+public:
+ QQuickText(QQuickItem *parent=0);
+ ~QQuickText();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter,
+ AlignJustify = Qt::AlignJustify };
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+ enum TextStyle { Normal,
+ Outline,
+ Raised,
+ Sunken };
+ enum TextFormat { PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText,
+ StyledText = 4 };
+ enum TextElideMode { ElideLeft = Qt::ElideLeft,
+ ElideRight = Qt::ElideRight,
+ ElideMiddle = Qt::ElideMiddle,
+ ElideNone = Qt::ElideNone };
+
+ enum WrapMode { NoWrap = QTextOption::NoWrap,
+ WordWrap = QTextOption::WordWrap,
+ WrapAnywhere = QTextOption::WrapAnywhere,
+ WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
+ Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
+ };
+
+ enum LineHeightMode { ProportionalHeight, FixedHeight };
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ TextStyle style() const;
+ void setStyle(TextStyle style);
+
+ QColor styleColor() const;
+ void setStyleColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode w);
+
+ int lineCount() const;
+ bool truncated() const;
+
+ int maximumLineCount() const;
+ void setMaximumLineCount(int lines);
+ void resetMaximumLineCount();
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ TextElideMode elideMode() const;
+ void setElideMode(TextElideMode);
+
+ qreal lineHeight() const;
+ void setLineHeight(qreal lineHeight);
+
+ LineHeightMode lineHeightMode() const;
+ void setLineHeightMode(LineHeightMode);
+
+ virtual void componentComplete();
+
+ int resourcesLoading() const; // mainly for testing
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ QRectF boundingRect() const;
+ Q_INVOKABLE void doLayout();
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void linkActivated(const QString &link);
+ void fontChanged(const QFont &font);
+ void colorChanged(const QColor &color);
+ void styleChanged(TextStyle style);
+ void styleColorChanged(const QColor &color);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapModeChanged();
+ void lineCountChanged();
+ void truncatedChanged();
+ void maximumLineCountChanged();
+ void textFormatChanged(TextFormat textFormat);
+ void elideModeChanged(TextElideMode mode);
+ void paintedSizeChanged();
+ void lineHeightChanged(qreal lineHeight);
+ void lineHeightModeChanged(LineHeightMode mode);
+ void effectiveHorizontalAlignmentChanged();
+ void lineLaidOut(QQuickTextLine *line);
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ virtual bool event(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QQuickText)
+ Q_DECLARE_PRIVATE(QQuickText)
+};
+
+class QTextLine;
+class Q_AUTOTEST_EXPORT QQuickTextLine : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int number READ number)
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+
+public:
+ QQuickTextLine();
+
+ void setLine(QTextLine* line);
+ int number() const;
+
+ qreal width() const;
+ void setWidth(qreal width);
+
+ qreal height() const;
+ void setHeight(qreal height);
+
+ qreal x() const;
+ void setX(qreal x);
+
+ qreal y() const;
+ void setY(qreal y);
+
+private:
+ QTextLine *m_line;
+ qreal m_height;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickText)
+QML_DECLARE_TYPE(QQuickTextLine)
+
+QT_END_HEADER
+
+#endif // QQUICKTEXT_P_H
diff --git a/src/declarative/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 2035f47a9d..2035f47a9d 100644
--- a/src/declarative/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
new file mode 100644
index 0000000000..c43a5be14c
--- /dev/null
+++ b/src/quick/items/qquicktextedit.cpp
@@ -0,0 +1,2091 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquicktextedit_p.h"
+#include "qquicktextedit_p_p.h"
+#include "qquickevents_p_p.h"
+#include "qquickcanvas.h"
+#include "qquicktextnode_p.h"
+#include <QtQuick/qsgsimplerectnode.h>
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qtextobject.h>
+#include <QtCore/qmath.h>
+
+#include <private/qdeclarativeglobal_p.h>
+#include <private/qtextcontrol_p.h>
+#include <private/qtextengine_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+DEFINE_BOOL_CONFIG_OPTION(qmlEnableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE)
+
+/*!
+ \qmlclass TextEdit QQuickTextEdit
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The TextEdit item displays multiple lines of editable formatted text.
+ \inherits Item
+
+ The TextEdit item displays a block of editable, formatted text.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ width: 240
+ text: "<b>Hello</b> <i>World!</i>"
+ font.family: "Helvetica"
+ font.pointSize: 20
+ color: "blue"
+ focus: true
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
+
+ Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
+ to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
+
+ \snippet snippets/declarative/texteditor.qml 0
+
+ A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
+ scrollbar, or a scrollbar that fades in to show location, etc.
+
+ Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
+ be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
+ from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
+
+ You can translate between cursor positions (characters from the start of the document) and pixel
+ points using positionAt() and positionToRectangle().
+
+ \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
+*/
+
+/*!
+ \qmlsignal QtQuick2::TextEdit::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+*/
+QQuickTextEdit::QQuickTextEdit(QQuickItem *parent)
+: QQuickImplicitSizeItem(*(new QQuickTextEditPrivate), parent)
+{
+ Q_D(QQuickTextEdit);
+ d->init();
+}
+
+QString QQuickTextEdit::text() const
+{
+ Q_D(const QQuickTextEdit);
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ if (d->richText)
+ return d->document->toHtml();
+ else
+#endif
+ return d->document->toPlainText();
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextEdit::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent. Use
+ \l{TextEdit::font.pointSize} to set the size of the font in a
+ device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string QtQuick2::TextEdit::text
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
+void QQuickTextEdit::setText(const QString &text)
+{
+ Q_D(QQuickTextEdit);
+ if (QQuickTextEdit::text() == text)
+ return;
+
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ d->control->setHtml(text);
+#else
+ d->control->setPlainText(text);
+#endif
+ d->useImageFallback = qmlEnableImageCache();
+ } else {
+ d->control->setPlainText(text);
+ }
+ q_textChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ \list
+ \o TextEdit.AutoText
+ \o TextEdit.PlainText
+ \o TextEdit.RichText
+ \endlist
+
+ The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ TextEdit {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+QQuickTextEdit::TextFormat QQuickTextEdit::textFormat() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->format;
+}
+
+void QQuickTextEdit::setTextFormat(TextFormat format)
+{
+ Q_D(QQuickTextEdit);
+ if (format == d->format)
+ return;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ d->control->setPlainText(d->text);
+ updateSize();
+ } else if (!wasRich && d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ d->control->setHtml(d->text);
+#else
+ d->control->setPlainText(d->text);
+#endif
+ updateSize();
+ d->useImageFallback = qmlEnableImageCache();
+ }
+ d->format = format;
+ d->control->setAcceptRichText(d->format != PlainText);
+ emit textFormatChanged(d->format);
+}
+
+QFont QQuickTextEdit::font() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->sourceFont;
+}
+
+void QQuickTextEdit::setFont(const QFont &font)
+{
+ Q_D(QQuickTextEdit);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+
+ if (oldFont != d->font) {
+ d->document->setDefaultFont(d->font);
+ if (d->cursor) {
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }
+ updateSize();
+ updateDocument();
+ }
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty color QtQuick2::TextEdit::color
+
+ The text color.
+
+ \qml
+ // green text using hexadecimal notation
+ TextEdit { color: "#00FF00" }
+ \endqml
+
+ \qml
+ // steelblue text using SVG color name
+ TextEdit { color: "steelblue" }
+ \endqml
+*/
+QColor QQuickTextEdit::color() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->color;
+}
+
+void QQuickTextEdit::setColor(const QColor &color)
+{
+ Q_D(QQuickTextEdit);
+ if (d->color == color)
+ return;
+
+ d->color = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Text, color);
+ d->control->setPalette(pal);
+ updateDocument();
+ emit colorChanged(d->color);
+}
+
+/*!
+ \qmlproperty color QtQuick2::TextEdit::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QQuickTextEdit::selectionColor() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->selectionColor;
+}
+
+void QQuickTextEdit::setSelectionColor(const QColor &color)
+{
+ Q_D(QQuickTextEdit);
+ if (d->selectionColor == color)
+ return;
+
+ d->selectionColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Highlight, color);
+ d->control->setPalette(pal);
+ updateDocument();
+ emit selectionColorChanged(d->selectionColor);
+}
+
+/*!
+ \qmlproperty color QtQuick2::TextEdit::selectedTextColor
+
+ The selected text color, used in selections.
+*/
+QColor QQuickTextEdit::selectedTextColor() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->selectedTextColor;
+}
+
+void QQuickTextEdit::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QQuickTextEdit);
+ if (d->selectedTextColor == color)
+ return;
+
+ d->selectedTextColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::HighlightedText, color);
+ d->control->setPalette(pal);
+ updateDocument();
+ emit selectedTextColorChanged(d->selectedTextColor);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::TextEdit::verticalAlignment
+ \qmlproperty enumeration QtQuick2::TextEdit::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ Valid values for \c horizontalAlignment are:
+ \list
+ \o TextEdit.AlignLeft (default)
+ \o TextEdit.AlignRight
+ \o TextEdit.AlignHCenter
+ \o TextEdit.AlignJustify
+ \endlist
+
+ Valid values for \c verticalAlignment are:
+ \list
+ \o TextEdit.AlignTop (default)
+ \o TextEdit.AlignBottom
+ \o TextEdit.AlignVCenter
+ \endlist
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QQuickTextEdit::HAlignment QQuickTextEdit::hAlign() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->hAlign;
+}
+
+void QQuickTextEdit::setHAlign(HAlignment align)
+{
+ Q_D(QQuickTextEdit);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
+ d->updateDefaultTextOption();
+ updateSize();
+ }
+}
+
+void QQuickTextEdit::resetHAlign()
+{
+ Q_D(QQuickTextEdit);
+ d->hAlignImplicit = true;
+ if (d->determineHorizontalAlignment() && isComponentComplete()) {
+ d->updateDefaultTextOption();
+ updateSize();
+ }
+}
+
+QQuickTextEdit::HAlignment QQuickTextEdit::effectiveHAlign() const
+{
+ Q_D(const QQuickTextEdit);
+ QQuickTextEdit::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QQuickTextEdit::AlignLeft:
+ effectiveAlignment = QQuickTextEdit::AlignRight;
+ break;
+ case QQuickTextEdit::AlignRight:
+ effectiveAlignment = QQuickTextEdit::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QQuickTextEdit);
+ if (hAlign != alignment || forceAlign) {
+ QQuickTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+ emit q->horizontalAlignmentChanged(alignment);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QQuickTextEditPrivate::determineHorizontalAlignment()
+{
+ Q_Q(QQuickTextEdit);
+ if (hAlignImplicit && q->isComponentComplete()) {
+ bool alignToRight;
+ if (text.isEmpty()) {
+ const QString preeditText = control->textCursor().block().layout()->preeditAreaText();
+ alignToRight = preeditText.isEmpty()
+ ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft
+ : preeditText.isRightToLeft();
+ } else {
+ alignToRight = rightToLeftText;
+ }
+ return setHAlign(alignToRight ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft);
+ }
+ return false;
+}
+
+void QQuickTextEditPrivate::mirrorChange()
+{
+ Q_Q(QQuickTextEdit);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QQuickTextEdit::AlignRight || hAlign == QQuickTextEdit::AlignLeft)) {
+ updateDefaultTextOption();
+ q->updateSize();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->vAlign;
+}
+
+void QQuickTextEdit::setVAlign(QQuickTextEdit::VAlignment alignment)
+{
+ Q_D(QQuickTextEdit);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+ moveCursorDelegate();
+ emit verticalAlignmentChanged(d->vAlign);
+}
+/*!
+ \qmlproperty enumeration QtQuick2::TextEdit::wrapMode
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ \list
+ \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
+ \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
+ \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+
+ The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
+*/
+QQuickTextEdit::WrapMode QQuickTextEdit::wrapMode() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->wrapMode;
+}
+
+void QQuickTextEdit::setWrapMode(WrapMode mode)
+{
+ Q_D(QQuickTextEdit);
+ if (mode == d->wrapMode)
+ return;
+ d->wrapMode = mode;
+ d->updateDefaultTextOption();
+ updateSize();
+ emit wrapModeChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::lineCount
+
+ Returns the total number of lines in the textEdit item.
+*/
+int QQuickTextEdit::lineCount() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->lineCount;
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::length
+
+ Returns the total number of plain text characters in the TextEdit item.
+
+ As this number doesn't include any formatting markup it may not be the same as the
+ length of the string returned by the \l text property.
+
+ This property can be faster than querying the length the \l text property as it doesn't
+ require any copying or conversion of the TextEdit's internal string data.
+*/
+
+int QQuickTextEdit::length() const
+{
+ Q_D(const QQuickTextEdit);
+ // QTextDocument::characterCount() includes the terminating null character.
+ return qMax(0, d->document->characterCount() - 1);
+}
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::paintedWidth
+
+ Returns the width of the text, including the width past the width
+ which is covered due to insufficient wrapping if \l wrapMode is set.
+*/
+qreal QQuickTextEdit::paintedWidth() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->paintedSize.width();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TextEdit::paintedHeight
+
+ Returns the height of the text, including the height past the height
+ that is covered if the text does not fit within the set height.
+*/
+qreal QQuickTextEdit::paintedHeight() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->paintedSize.height();
+}
+
+/*!
+ \qmlmethod rectangle QtQuick2::TextEdit::positionToRectangle(position)
+
+ Returns the rectangle at the given \a position in the text. The x, y,
+ and height properties correspond to the cursor that would describe
+ that position.
+*/
+QRectF QQuickTextEdit::positionToRectangle(int pos) const
+{
+ Q_D(const QQuickTextEdit);
+ QTextCursor c(d->document);
+ c.setPosition(pos);
+ return d->control->cursorRect(c);
+
+}
+
+/*!
+ \qmlmethod int QtQuick2::TextEdit::positionAt(int x, int y)
+
+ Returns the text position closest to pixel position (\a x, \a y).
+
+ Position 0 is before the first character, position 1 is after the first character
+ but before the second, and so on until position \l {text}.length, which is after all characters.
+*/
+int QQuickTextEdit::positionAt(int x, int y) const
+{
+ Q_D(const QQuickTextEdit);
+ int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
+ QTextCursor cursor = d->control->textCursor();
+ if (r > cursor.position()) {
+ // The cursor position includes positions within the preedit text, but only positions in the
+ // same text block are offset so it is possible to get a position that is either part of the
+ // preedit or the next text block.
+ QTextLayout *layout = cursor.block().layout();
+ const int preeditLength = layout
+ ? layout->preeditAreaText().length()
+ : 0;
+ if (preeditLength > 0
+ && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
+ r = r > cursor.position() + preeditLength
+ ? r - preeditLength
+ : cursor.position();
+ }
+ }
+ return r;
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified position and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextEdit.SelectCharacters)
+ moveCursorSelection(7, TextEdit.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
+void QQuickTextEdit::moveCursorSelection(int pos)
+{
+ //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
+ Q_D(QQuickTextEdit);
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos)
+ return;
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ d->control->setTextCursor(cursor);
+}
+
+void QQuickTextEdit::moveCursorSelection(int pos, SelectionMode mode)
+{
+ Q_D(QQuickTextEdit);
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos)
+ return;
+ if (mode == SelectCharacters) {
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
+ if (cursor.anchor() > cursor.position()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() == cursor.anchor())
+ cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor);
+ else
+ cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
+ } else {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
+ }
+
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != pos)
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
+ if (cursor.anchor() < cursor.position()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
+ } else {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != cursor.anchor()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
+ }
+ }
+
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != pos) {
+ cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ }
+ }
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::cursorVisible
+ If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets active focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QQuickTextEdit::isCursorVisible() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->cursorVisible;
+}
+
+void QQuickTextEdit::setCursorVisible(bool on)
+{
+ Q_D(QQuickTextEdit);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
+ if (!on && !d->persistentSelection)
+ d->control->setCursorIsFocusIndicator(true);
+ d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::cursorPosition
+ The position of the cursor in the TextEdit.
+*/
+int QQuickTextEdit::cursorPosition() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->textCursor().position();
+}
+
+void QQuickTextEdit::setCursorPosition(int pos)
+{
+ Q_D(QQuickTextEdit);
+ if (pos < 0 || pos > d->text.length())
+ return;
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos && cursor.anchor() == pos)
+ return;
+ cursor.setPosition(pos);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty Component QtQuick2::TextEdit::cursorDelegate
+ The delegate for the cursor in the TextEdit.
+
+ If you set a cursorDelegate for a TextEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the text edit when a cursor is
+ needed, and the x and y properties of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
+QDeclarativeComponent* QQuickTextEdit::cursorDelegate() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->cursorComponent;
+}
+
+void QQuickTextEdit::setCursorDelegate(QDeclarativeComponent* c)
+{
+ Q_D(QQuickTextEdit);
+ if (d->cursorComponent) {
+ if (d->cursor) {
+ d->control->setCursorWidth(-1);
+ updateCursor();
+ delete d->cursor;
+ d->cursor = 0;
+ }
+ }
+ d->cursorComponent = c;
+ if (c && c->isReady()) {
+ loadCursorDelegate();
+ } else {
+ if (c)
+ connect(c, SIGNAL(statusChanged()),
+ this, SLOT(loadCursorDelegate()));
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QQuickTextEdit::loadCursorDelegate()
+{
+ Q_D(QQuickTextEdit);
+ if (d->cursorComponent->isLoading())
+ return;
+ QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
+ QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
+ d->cursor = qobject_cast<QQuickItem*>(object);
+ if (d->cursor) {
+ d->control->setCursorWidth(0);
+ updateCursor();
+ QDeclarative_setParent_noEvent(d->cursor, this);
+ d->cursor->setParentItem(this);
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }else{
+ delete object;
+ qmlInfo(this) << "Error loading cursor delegate.";
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QQuickTextEdit::selectionStart() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->textCursor().selectionStart();
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QQuickTextEdit::selectionEnd() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->textCursor().selectionEnd();
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextEdit::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+ \code
+ //myTextEdit is the id of the TextEdit
+ myTextEdit.text.toString().substring(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd);
+ \endcode
+*/
+QString QQuickTextEdit::selectedText() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->textCursor().selectedText();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::activeFocusOnPress
+
+ Whether the TextEdit should gain active focus on a mouse press. By default this is
+ set to true.
+*/
+bool QQuickTextEdit::focusOnPress() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->focusOnPress;
+}
+
+void QQuickTextEdit::setFocusOnPress(bool on)
+{
+ Q_D(QQuickTextEdit);
+ if (d->focusOnPress == on)
+ return;
+ d->focusOnPress = on;
+ emit activeFocusOnPressChanged(d->focusOnPress);
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::persistentSelection
+
+ Whether the TextEdit should keep the selection visible when it loses active focus to another
+ item in the scene. By default this is set to true;
+*/
+bool QQuickTextEdit::persistentSelection() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->persistentSelection;
+}
+
+void QQuickTextEdit::setPersistentSelection(bool on)
+{
+ Q_D(QQuickTextEdit);
+ if (d->persistentSelection == on)
+ return;
+ d->persistentSelection = on;
+ emit persistentSelectionChanged(d->persistentSelection);
+}
+
+/*
+ \qmlproperty real QtQuick2::TextEdit::textMargin
+
+ The margin, in pixels, around the text in the TextEdit.
+*/
+qreal QQuickTextEdit::textMargin() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->textMargin;
+}
+
+void QQuickTextEdit::setTextMargin(qreal margin)
+{
+ Q_D(QQuickTextEdit);
+ if (d->textMargin == margin)
+ return;
+ d->textMargin = margin;
+ d->document->setDocumentMargin(d->textMargin);
+ emit textMarginChanged(d->textMargin);
+}
+
+void QQuickTextEdit::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
+void QQuickTextEdit::componentComplete()
+{
+ Q_D(QQuickTextEdit);
+ QQuickImplicitSizeItem::componentComplete();
+
+ if (d->richText)
+ d->useImageFallback = qmlEnableImageCache();
+
+ if (d->dirty) {
+ d->determineHorizontalAlignment();
+ d->updateDefaultTextOption();
+ updateSize();
+ d->dirty = false;
+ }
+
+}
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::selectByMouse
+
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
+bool QQuickTextEdit::selectByMouse() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->selectByMouse;
+}
+
+void QQuickTextEdit::setSelectByMouse(bool on)
+{
+ Q_D(QQuickTextEdit);
+ if (d->selectByMouse != on) {
+ d->selectByMouse = on;
+ setKeepMouseGrab(on);
+ if (on)
+ setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
+ else
+ setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
+ emit selectByMouseChanged(on);
+ }
+}
+
+/*!
+ \qmlproperty enum QtQuick2::TextEdit::mouseSelectionMode
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextEdit.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
+QQuickTextEdit::SelectionMode QQuickTextEdit::mouseSelectionMode() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->mouseSelectionMode;
+}
+
+void QQuickTextEdit::setMouseSelectionMode(SelectionMode mode)
+{
+ Q_D(QQuickTextEdit);
+ if (d->mouseSelectionMode != mode) {
+ d->mouseSelectionMode = mode;
+ d->control->setWordSelectionEnabled(mode == SelectWords);
+ emit mouseSelectionModeChanged(mode);
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::readOnly
+
+ Whether the user can interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
+void QQuickTextEdit::setReadOnly(bool r)
+{
+ Q_D(QQuickTextEdit);
+ if (r == isReadOnly())
+ return;
+
+ setFlag(QQuickItem::ItemAcceptsInputMethod, !r);
+ Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
+ if (d->selectByMouse)
+ flags = flags | Qt::TextSelectableByMouse;
+ if (!r)
+ flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
+ d->control->setTextInteractionFlags(flags);
+ if (!r)
+ d->control->moveCursor(QTextCursor::End);
+
+ emit readOnlyChanged(r);
+}
+
+bool QQuickTextEdit::isReadOnly() const
+{
+ Q_D(const QQuickTextEdit);
+ return !(d->control->textInteractionFlags() & Qt::TextEditable);
+}
+
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
+void QQuickTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+ Q_D(QQuickTextEdit);
+ d->control->setTextInteractionFlags(flags);
+}
+
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
+Qt::TextInteractionFlags QQuickTextEdit::textInteractionFlags() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->textInteractionFlags();
+}
+
+/*!
+ \qmlproperty rectangle QtQuick2::TextEdit::cursorRectangle
+
+ The rectangle where the text cursor is rendered
+ within the text edit. Read-only.
+*/
+QRect QQuickTextEdit::cursorRectangle() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->control->cursorRect().toRect().translated(0,d->yoff);
+}
+
+bool QQuickTextEdit::event(QEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ if (event->type() == QEvent::ShortcutOverride) {
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ return event->isAccepted();
+ }
+ return QQuickImplicitSizeItem::event(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QQuickTextEdit::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::keyPressEvent(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QQuickTextEdit::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::keyReleaseEvent(event);
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::deselect()
+
+ Removes active text selection.
+*/
+void QQuickTextEdit::deselect()
+{
+ Q_D(QQuickTextEdit);
+ QTextCursor c = d->control->textCursor();
+ c.clearSelection();
+ d->control->setTextCursor(c);
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::selectAll()
+
+ Causes all text to be selected.
+*/
+void QQuickTextEdit::selectAll()
+{
+ Q_D(QQuickTextEdit);
+ d->control->selectAll();
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
+void QQuickTextEdit::selectWord()
+{
+ Q_D(QQuickTextEdit);
+ QTextCursor c = d->control->textCursor();
+ c.select(QTextCursor::WordUnderCursor);
+ d->control->setTextCursor(c);
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+*/
+void QQuickTextEdit::select(int start, int end)
+{
+ Q_D(QQuickTextEdit);
+ if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
+ return;
+ QTextCursor cursor = d->control->textCursor();
+ cursor.beginEditBlock();
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.setPosition(end, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ d->control->setTextCursor(cursor);
+
+ // QTBUG-11100
+ updateSelectionMarkers();
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
+bool QQuickTextEdit::isRightToLeft(int start, int end)
+{
+ Q_D(QQuickTextEdit);
+ if (start > end) {
+ qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
+ return false;
+ } else {
+ return d->text.mid(start, end - start).isRightToLeft();
+ }
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod QtQuick2::TextEdit::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
+void QQuickTextEdit::cut()
+{
+ Q_D(QQuickTextEdit);
+ d->control->cut();
+}
+
+/*!
+ \qmlmethod QtQuick2::TextEdit::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
+void QQuickTextEdit::copy()
+{
+ Q_D(QQuickTextEdit);
+ d->control->copy();
+}
+
+/*!
+ \qmlmethod QtQuick2::TextEdit::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
+void QQuickTextEdit::paste()
+{
+ Q_D(QQuickTextEdit);
+ d->control->paste();
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ if (d->focusOnPress){
+ bool hadActiveFocus = hasActiveFocus();
+ forceActiveFocus();
+ // re-open input panel on press if already focused
+ if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
+ openSoftwareInputPanel();
+ }
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QQuickTextEdit::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::mouseReleaseEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QQuickTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QQuickTextEdit::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::mouseMoveEvent(event);
+}
+
+/*!
+\overload
+Handles the given input method \a event.
+*/
+void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QQuickTextEdit);
+ const bool wasComposing = isInputMethodComposing();
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (wasComposing != isInputMethodComposing())
+ emit inputMethodComposingChanged();
+}
+
+void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (change == ItemActiveFocusHasChanged) {
+ setCursorVisible(value.boolValue); // ### refactor: focus handling && d->canvas && d->canvas->hasFocus());
+ }
+ QQuickItem::itemChange(change, value);
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QQuickTextEdit);
+
+ QVariant v;
+ switch (property) {
+ case Qt::ImEnabled:
+ v = (bool)(flags() & ItemAcceptsInputMethod);
+ break;
+ case Qt::ImHints:
+ v = (int)inputMethodHints();
+ break;
+ default:
+ v = d->control->inputMethodQuery(property);
+ break;
+ }
+ return v;
+
+}
+
+void QQuickTextEdit::updateImageCache(const QRectF &)
+{
+ Q_D(QQuickTextEdit);
+
+ // Do we really need the image cache?
+ if (!d->richText || !d->useImageFallback) {
+ if (!d->pixmapCache.isNull())
+ d->pixmapCache = QPixmap();
+ return;
+ }
+
+ if (width() != d->pixmapCache.width() || height() != d->pixmapCache.height())
+ d->pixmapCache = QPixmap(width(), height());
+
+ if (d->pixmapCache.isNull())
+ return;
+
+ // ### Use supplied rect, clear area and update only this part (for cursor updates)
+ QRectF bounds = QRectF(0, 0, width(), height());
+ d->pixmapCache.fill(Qt::transparent);
+ {
+ QPainter painter(&d->pixmapCache);
+
+ painter.setRenderHint(QPainter::TextAntialiasing);
+ painter.translate(0, d->yoff);
+
+ d->control->drawContents(&painter, bounds);
+ }
+
+}
+
+QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
+{
+ Q_UNUSED(updatePaintNodeData);
+ Q_D(QQuickTextEdit);
+
+ QSGNode *currentNode = oldNode;
+ if (d->richText && d->useImageFallback) {
+ QSGImageNode *node = 0;
+ if (oldNode == 0 || d->nodeType != QQuickTextEditPrivate::NodeIsTexture) {
+ delete oldNode;
+ node = QQuickItemPrivate::get(this)->sceneGraphContext()->createImageNode();
+ d->texture = new QSGPlainTexture();
+ d->nodeType = QQuickTextEditPrivate::NodeIsTexture;
+ currentNode = node;
+ } else {
+ node = static_cast<QSGImageNode *>(oldNode);
+ }
+
+ qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->pixmapCache.toImage());
+ node->setTexture(0);
+ node->setTexture(d->texture);
+
+ node->setTargetRect(QRectF(0, 0, d->pixmapCache.width(), d->pixmapCache.height()));
+ node->setSourceRect(QRectF(0, 0, 1, 1));
+ node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ node->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ node->setFiltering(QSGTexture::Linear); // Nonsmooth text just ugly, so don't do that..
+ node->update();
+
+ } else if (oldNode == 0 || d->documentDirty) {
+ d->documentDirty = false;
+
+#if defined(Q_OS_MAC)
+ // Make sure document is relayouted in the paint node on Mac
+ // to avoid crashes due to the font engines created in the
+ // shaping process
+ d->document->markContentsDirty(0, d->document->characterCount());
+#endif
+
+ QQuickTextNode *node = 0;
+ if (oldNode == 0 || d->nodeType != QQuickTextEditPrivate::NodeIsText) {
+ delete oldNode;
+ node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
+ d->nodeType = QQuickTextEditPrivate::NodeIsText;
+ currentNode = node;
+ } else {
+ node = static_cast<QQuickTextNode *>(oldNode);
+ }
+
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
+ QRectF bounds = boundingRect();
+
+ QColor selectionColor = d->control->palette().color(QPalette::Highlight);
+ QColor selectedTextColor = d->control->palette().color(QPalette::HighlightedText);
+ node->addTextDocument(bounds.topLeft(), d->document, d->color, QQuickText::Normal, QColor(),
+ selectionColor, selectedTextColor, selectionStart(),
+ selectionEnd() - 1); // selectionEnd() returns first char after
+ // selection
+
+#if defined(Q_OS_MAC)
+ // We also need to make sure the document layout is redone when
+ // control is returned to the main thread, as all the font engines
+ // are now owned by the rendering thread
+ d->document->markContentsDirty(0, d->document->characterCount());
+#endif
+ }
+
+ if (d->nodeType == QQuickTextEditPrivate::NodeIsText && d->cursorComponent == 0 && !isReadOnly()) {
+ QQuickTextNode *node = static_cast<QQuickTextNode *>(currentNode);
+
+ QColor color = (!d->cursorVisible || !d->control->cursorOn())
+ ? QColor(0, 0, 0, 0)
+ : d->color;
+
+ if (node->cursorNode() == 0) {
+ node->setCursor(cursorRectangle(), color);
+ } else {
+ node->cursorNode()->setRect(cursorRectangle());
+ node->cursorNode()->setColor(color);
+ }
+
+ }
+
+ return currentNode;
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::canPaste
+
+ Returns true if the TextEdit is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
+bool QQuickTextEdit::canPaste() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->canPaste;
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextEdit::inputMethodComposing
+
+
+ This property holds whether the TextEdit has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextEdit to edit or commit the partial text. This property can be used
+ to determine when to disable events handlers that may interfere with the
+ correct operation of an input method.
+*/
+bool QQuickTextEdit::isInputMethodComposing() const
+{
+ Q_D(const QQuickTextEdit);
+ if (QTextLayout *layout = d->control->textCursor().block().layout())
+ return layout->preeditAreaText().length() > 0;
+ return false;
+}
+
+void QQuickTextEditPrivate::init()
+{
+ Q_Q(QQuickTextEdit);
+
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QQuickItem::ItemAcceptsInputMethod);
+ q->setFlag(QQuickItem::ItemHasContents);
+
+ control = new QTextControl(q);
+ control->setIgnoreUnusedNavigationEvents(true);
+ control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable);
+ control->setDragEnabled(false);
+
+ // By default, QTextControl will issue both a updateCursorRequest() and an updateRequest()
+ // when the cursor needs to be repainted. We need the signals to be separate to be able to
+ // distinguish the cursor updates so that we can avoid updating the whole subtree when the
+ // cursor blinks.
+ if (!QObject::disconnect(control, SIGNAL(updateCursorRequest(QRectF)),
+ control, SIGNAL(updateRequest(QRectF)))) {
+ qWarning("QQuickTextEditPrivate::init: Failed to disconnect updateCursorRequest and updateRequest");
+ }
+
+ // QTextControl follows the default text color
+ // defined by the platform, declarative text
+ // should be black by default
+ QPalette pal = control->palette();
+ if (pal.color(QPalette::Text) != color) {
+ pal.setColor(QPalette::Text, color);
+ control->setPalette(pal);
+ }
+
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateDocument()));
+ QObject::connect(control, SIGNAL(updateCursorRequest()), q, SLOT(updateCursor()));
+ QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
+ QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
+ QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
+#ifndef QT_NO_CLIPBOARD
+ QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
+ QObject::connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
+ canPaste = control->canPaste();
+#endif
+
+ document = control->document();
+ document->setDefaultFont(font);
+ document->setDocumentMargin(textMargin);
+ document->setUndoRedoEnabled(false); // flush undo buffer.
+ document->setUndoRedoEnabled(true);
+ updateDefaultTextOption();
+}
+
+void QQuickTextEdit::q_textChanged()
+{
+ Q_D(QQuickTextEdit);
+ d->text = text();
+ d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft();
+ d->determineHorizontalAlignment();
+ d->updateDefaultTextOption();
+ updateSize();
+ updateTotalLines();
+ emit textChanged(d->text);
+}
+
+void QQuickTextEdit::moveCursorDelegate()
+{
+ Q_D(QQuickTextEdit);
+ d->determineHorizontalAlignment();
+ updateMicroFocus();
+ emit cursorRectangleChanged();
+ if (!d->cursor)
+ return;
+ QRectF cursorRect = cursorRectangle();
+ d->cursor->setX(cursorRect.x());
+ d->cursor->setY(cursorRect.y());
+}
+
+void QQuickTextEditPrivate::updateSelection()
+{
+ Q_Q(QQuickTextEdit);
+ QTextCursor cursor = control->textCursor();
+ bool startChange = (lastSelectionStart != cursor.selectionStart());
+ bool endChange = (lastSelectionEnd != cursor.selectionEnd());
+ cursor.beginEditBlock();
+ cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ control->setTextCursor(cursor);
+ if (startChange)
+ q->selectionStartChanged();
+ if (endChange)
+ q->selectionEndChanged();
+}
+
+void QQuickTextEdit::updateSelectionMarkers()
+{
+ Q_D(QQuickTextEdit);
+ if (d->lastSelectionStart != d->control->textCursor().selectionStart()) {
+ d->lastSelectionStart = d->control->textCursor().selectionStart();
+ emit selectionStartChanged();
+ }
+ if (d->lastSelectionEnd != d->control->textCursor().selectionEnd()) {
+ d->lastSelectionEnd = d->control->textCursor().selectionEnd();
+ emit selectionEndChanged();
+ }
+}
+
+QRectF QQuickTextEdit::boundingRect() const
+{
+ Q_D(const QQuickTextEdit);
+ QRectF r = QQuickImplicitSizeItem::boundingRect();
+ int cursorWidth = 1;
+ if (d->cursor)
+ cursorWidth = d->cursor->width();
+ if (!d->document->isEmpty())
+ cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ r.setRight(r.right() + cursorWidth);
+ return r.translated(0,d->yoff);
+}
+
+qreal QQuickTextEditPrivate::getImplicitWidth() const
+{
+ Q_Q(const QQuickTextEdit);
+ if (!requireImplicitWidth) {
+ // We don't calculate implicitWidth unless it is required.
+ // We need to force a size update now to ensure implicitWidth is calculated
+ const_cast<QQuickTextEditPrivate*>(this)->requireImplicitWidth = true;
+ const_cast<QQuickTextEdit*>(q)->updateSize();
+ }
+ return implicitWidth;
+}
+
+//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
+// need to do all the calculations each time
+void QQuickTextEdit::updateSize()
+{
+ Q_D(QQuickTextEdit);
+ if (isComponentComplete()) {
+ qreal naturalWidth = d->implicitWidth;
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid()) {
+ if (!d->requireImplicitWidth) {
+ emit implicitWidthChanged();
+ // if the implicitWidth is used, then updateSize() has already been called (recursively)
+ if (d->requireImplicitWidth)
+ return;
+ }
+ if (d->requireImplicitWidth) {
+ d->document->setTextWidth(-1);
+ naturalWidth = d->document->idealWidth();
+ }
+ if (d->document->textWidth() != width())
+ d->document->setTextWidth(width());
+ } else {
+ d->document->setTextWidth(-1);
+ }
+ QFontMetrics fm = QFontMetrics(d->font);
+ int dy = height();
+ dy -= (int)d->document->size().height();
+
+ int nyoff;
+ if (heightValid()) {
+ if (d->vAlign == AlignBottom)
+ nyoff = dy;
+ else if (d->vAlign == AlignVCenter)
+ nyoff = dy/2;
+ else
+ nyoff = 0;
+ } else {
+ nyoff = 0;
+ }
+ if (nyoff != d->yoff)
+ d->yoff = nyoff;
+ setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
+
+ //### need to comfirm cost of always setting these
+ int newWidth = qCeil(d->document->idealWidth());
+ if (!widthValid() && d->document->textWidth() != newWidth)
+ 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())
+ iWidth = newWidth;
+ else if (d->requireImplicitWidth)
+ iWidth = naturalWidth;
+ qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
+ if (iWidth > -1)
+ setImplicitSize(iWidth, newHeight);
+ else
+ setImplicitHeight(newHeight);
+
+ d->paintedSize = QSize(newWidth, newHeight);
+ emit paintedSizeChanged();
+ } else {
+ d->dirty = true;
+ }
+ updateDocument();
+}
+
+void QQuickTextEdit::updateDocument()
+{
+ Q_D(QQuickTextEdit);
+ d->documentDirty = true;
+
+ if (isComponentComplete()) {
+ updateImageCache();
+ update();
+ }
+}
+
+void QQuickTextEdit::updateCursor()
+{
+ Q_D(QQuickTextEdit);
+ if (isComponentComplete()) {
+ updateImageCache(d->control->cursorRect());
+ update();
+ }
+}
+
+void QQuickTextEdit::updateTotalLines()
+{
+ Q_D(QQuickTextEdit);
+
+ int subLines = 0;
+
+ for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
+ QTextLayout *layout = it.layout();
+ if (!layout)
+ continue;
+ subLines += layout->lineCount()-1;
+ }
+
+ int newTotalLines = d->document->lineCount() + subLines;
+ if (d->lineCount != newTotalLines) {
+ d->lineCount = newTotalLines;
+ emit lineCountChanged();
+ }
+}
+
+void QQuickTextEditPrivate::updateDefaultTextOption()
+{
+ Q_Q(QQuickTextEdit);
+ QTextOption opt = document->defaultTextOption();
+ int oldAlignment = opt.alignment();
+
+ QQuickTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
+ if (rightToLeftText) {
+ if (horizontalAlignment == QQuickTextEdit::AlignLeft)
+ horizontalAlignment = QQuickTextEdit::AlignRight;
+ else if (horizontalAlignment == QQuickTextEdit::AlignRight)
+ horizontalAlignment = QQuickTextEdit::AlignLeft;
+ }
+ opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
+
+ QTextOption::WrapMode oldWrapMode = opt.wrapMode();
+ opt.setWrapMode(QTextOption::WrapMode(wrapMode));
+
+ bool oldUseDesignMetrics = opt.useDesignMetrics();
+ bool useDesignMetrics = !qmlDisableDistanceField();
+ opt.setUseDesignMetrics(useDesignMetrics);
+
+ if (oldWrapMode == opt.wrapMode()
+ && oldAlignment == opt.alignment()
+ && oldUseDesignMetrics == useDesignMetrics) {
+ return;
+ }
+ document->setDefaultTextOption(opt);
+}
+
+
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
+void QQuickTextEdit::openSoftwareInputPanel()
+{
+ if (qGuiApp)
+ qGuiApp->inputPanel()->show();
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
+void QQuickTextEdit::closeSoftwareInputPanel()
+{
+ if (qGuiApp)
+ qGuiApp->inputPanel()->hide();
+}
+
+void QQuickTextEdit::focusInEvent(QFocusEvent *event)
+{
+ Q_D(const QQuickTextEdit);
+ if (d->focusOnPress && !isReadOnly())
+ openSoftwareInputPanel();
+ QQuickImplicitSizeItem::focusInEvent(event);
+}
+
+void QQuickTextEdit::q_canPasteChanged()
+{
+ Q_D(QQuickTextEdit);
+ bool old = d->canPaste;
+ d->canPaste = d->control->canPaste();
+ if (old!=d->canPaste)
+ emit canPasteChanged();
+}
+
+/*!
+ \qmlmethod string QtQuick2::TextEdit::getText(int start, int end)
+
+ Returns the section of text that is between the \a start and \a end positions.
+
+ The returned text does not include any rich text formatting.
+*/
+
+QString QQuickTextEdit::getText(int start, int end) const
+{
+ Q_D(const QQuickTextEdit);
+ start = qBound(0, start, d->document->characterCount() - 1);
+ end = qBound(0, end, d->document->characterCount() - 1);
+ QTextCursor cursor(d->document);
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.setPosition(end, QTextCursor::KeepAnchor);
+ return cursor.selectedText();
+}
+
+/*!
+ \qmlmethod string QtQuick2::TextEdit::getFormattedText(int start, int end)
+
+ Returns the section of text that is between the \a start and \a end positions.
+
+ The returned text will be formatted according the \l textFormat property.
+*/
+
+QString QQuickTextEdit::getFormattedText(int start, int end) const
+{
+ Q_D(const QQuickTextEdit);
+
+ start = qBound(0, start, d->document->characterCount() - 1);
+ end = qBound(0, end, d->document->characterCount() - 1);
+
+ QTextCursor cursor(d->document);
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.setPosition(end, QTextCursor::KeepAnchor);
+
+ if (d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ return cursor.selection().toHtml();
+#else
+ return cursor.selection().toPlainText();
+#endif
+ } else {
+ return cursor.selection().toPlainText();
+ }
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextEdit::insert(int position, string text)
+
+ Inserts \a text into the TextEdit at position.
+*/
+void QQuickTextEdit::insert(int position, const QString &text)
+{
+ Q_D(QQuickTextEdit);
+ if (position < 0 || position >= d->document->characterCount())
+ return;
+ QTextCursor cursor(d->document);
+ cursor.setPosition(position);
+ d->richText = d->richText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ cursor.insertHtml(text);
+#else
+ cursor.insertText(text);
+#endif
+ } else {
+ cursor.insertText(text);
+ }
+}
+
+/*!
+ \qmlmethod string QtQuick2::TextEdit::getText(int start, int end)
+
+ Removes the section of text that is between the \a start and \a end positions from the TextEdit.
+*/
+
+void QQuickTextEdit::remove(int start, int end)
+{
+ Q_D(QQuickTextEdit);
+ start = qBound(0, start, d->document->characterCount() - 1);
+ end = qBound(0, end, d->document->characterCount() - 1);
+ QTextCursor cursor(d->document);
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.setPosition(end, QTextCursor::KeepAnchor);
+ cursor.removeSelectedText();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
new file mode 100644
index 0000000000..e234d6ef95
--- /dev/null
+++ b/src/quick/items/qquicktextedit_p.h
@@ -0,0 +1,312 @@
+// Commit: 27e4302b7f45f22180693d26747f419177c81e27
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKTEXTEDIT_P_H
+#define QQUICKTEXTEDIT_P_H
+
+#include "qquickimplicitsizeitem_p.h"
+
+#include <QtGui/qtextoption.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTextEditPrivate;
+class Q_AUTOTEST_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(WrapMode)
+ Q_ENUMS(SelectionMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
+ Q_PROPERTY(int length READ length NOTIFY textChanged)
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_PROPERTY(QDeclarativeComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
+ Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
+ Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged)
+ Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+ Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
+ Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
+ Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
+
+public:
+ QQuickTextEdit(QQuickItem *parent=0);
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter,
+ AlignJustify = Qt::AlignJustify
+ };
+
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum TextFormat {
+ PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText
+ };
+
+ enum WrapMode { NoWrap = QTextOption::NoWrap,
+ WordWrap = QTextOption::WordWrap,
+ WrapAnywhere = QTextOption::WrapAnywhere,
+ WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
+ Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
+ };
+
+ enum SelectionMode {
+ SelectCharacters,
+ SelectWords
+ };
+
+ Q_INVOKABLE void openSoftwareInputPanel();
+ Q_INVOKABLE void closeSoftwareInputPanel();
+
+ QString text() const;
+ void setText(const QString &);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode w);
+
+ int lineCount() const;
+
+ int length() const;
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int pos);
+
+ QDeclarativeComponent* cursorDelegate() const;
+ void setCursorDelegate(QDeclarativeComponent*);
+
+ int selectionStart() const;
+ int selectionEnd() const;
+
+ QString selectedText() const;
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool on);
+
+ bool persistentSelection() const;
+ void setPersistentSelection(bool on);
+
+ qreal textMargin() const;
+ void setTextMargin(qreal margin);
+
+ bool selectByMouse() const;
+ void setSelectByMouse(bool);
+
+ SelectionMode mouseSelectionMode() const;
+ void setMouseSelectionMode(SelectionMode mode);
+
+ bool canPaste() const;
+
+ virtual void componentComplete();
+
+ /* FROM EDIT */
+ void setReadOnly(bool);
+ bool isReadOnly() const;
+
+ void setTextInteractionFlags(Qt::TextInteractionFlags flags);
+ Qt::TextInteractionFlags textInteractionFlags() const;
+
+ QRect cursorRectangle() const;
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ Q_INVOKABLE QRectF positionToRectangle(int) const;
+ Q_INVOKABLE int positionAt(int x, int y) const;
+ Q_INVOKABLE void moveCursorSelection(int pos);
+ Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
+
+ QRectF boundingRect() const;
+
+ bool isInputMethodComposing() const;
+
+ Q_INVOKABLE QString getText(int start, int end) const;
+ Q_INVOKABLE QString getFormattedText(int start, int end) const;
+
+Q_SIGNALS:
+ void textChanged(const QString &);
+ void paintedSizeChanged();
+ void cursorPositionChanged();
+ void cursorRectangleChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectionChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapModeChanged();
+ void lineCountChanged();
+ void textFormatChanged(TextFormat textFormat);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void activeFocusOnPressChanged(bool activeFocusOnPressed);
+ void persistentSelectionChanged(bool isPersistentSelection);
+ void textMarginChanged(qreal textMargin);
+ void selectByMouseChanged(bool selectByMouse);
+ void mouseSelectionModeChanged(SelectionMode mode);
+ void linkActivated(const QString &link);
+ void canPasteChanged();
+ void inputMethodComposingChanged();
+ void effectiveHorizontalAlignmentChanged();
+
+public Q_SLOTS:
+ void selectAll();
+ void selectWord();
+ void select(int start, int end);
+ void deselect();
+ bool isRightToLeft(int start, int end);
+#ifndef QT_NO_CLIPBOARD
+ void cut();
+ void copy();
+ void paste();
+#endif
+ void insert(int position, const QString &text);
+ void remove(int start, int end);
+
+private Q_SLOTS:
+ void q_textChanged();
+ void updateSelectionMarkers();
+ void moveCursorDelegate();
+ void loadCursorDelegate();
+ void q_canPasteChanged();
+ void updateDocument();
+ void updateCursor();
+
+private:
+ void updateSize();
+ void updateTotalLines();
+ void updateImageCache(const QRectF &rect = QRectF());
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ bool event(QEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+ void focusInEvent(QFocusEvent *event);
+
+ // mouse filter?
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void inputMethodEvent(QInputMethodEvent *e);
+ virtual void itemChange(ItemChange, const ItemChangeData &);
+
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
+
+private:
+ Q_DISABLE_COPY(QQuickTextEdit)
+ Q_DECLARE_PRIVATE(QQuickTextEdit)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTextEdit)
+
+QT_END_HEADER
+
+#endif // QQUICKTEXTEDIT_P_H
diff --git a/src/declarative/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 7bcbe2a189..7bcbe2a189 100644
--- a/src/declarative/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
new file mode 100644
index 0000000000..e9caaf2ee8
--- /dev/null
+++ b/src/quick/items/qquicktextinput.cpp
@@ -0,0 +1,2007 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquicktextinput_p.h"
+#include "qquicktextinput_p_p.h"
+#include "qquickcanvas.h"
+
+#include <private/qdeclarativeglobal_p.h>
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtGui/qevent.h>
+#include <QTextBoundaryFinder>
+#include "qquicktextnode_p.h"
+#include <QtQuick/qsgsimplerectnode.h>
+
+#include <QtGui/qstylehints.h>
+#include <QtGui/qinputpanel.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
+/*!
+ \qmlclass TextInput QQuickTextInput
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+ \brief The TextInput item displays an editable line of text.
+ \inherits Item
+
+ The TextInput element displays a single line of editable plain text.
+
+ TextInput is used to accept a line of text input. Input constraints
+ can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
+ and setting \l echoMode to an appropriate value enables TextInput to be used for
+ a password input field.
+
+ On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
+ If you want such bindings (on any platform), you will need to construct them in QML.
+
+ \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
+*/
+QQuickTextInput::QQuickTextInput(QQuickItem* parent)
+: QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
+{
+ Q_D(QQuickTextInput);
+ d->init();
+}
+
+QQuickTextInput::~QQuickTextInput()
+{
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::text
+
+ The text in the TextInput.
+*/
+QString QQuickTextInput::text() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->text();
+}
+
+void QQuickTextInput::setText(const QString &s)
+{
+ Q_D(QQuickTextInput);
+ if (s == text())
+ return;
+ d->control->setText(s);
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TextInput::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::TextInput::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
+QFont QQuickTextInput::font() const
+{
+ Q_D(const QQuickTextInput);
+ return d->sourceFont;
+}
+
+void QQuickTextInput::setFont(const QFont &font)
+{
+ Q_D(QQuickTextInput);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+ if (oldFont != d->font) {
+ d->control->setFont(d->font);
+ updateSize();
+ updateCursorRectangle();
+ if (d->cursorItem) {
+ d->cursorItem->setHeight(QFontMetrics(d->font).height());
+ }
+ }
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty color QtQuick2::TextInput::color
+
+ The text color.
+*/
+QColor QQuickTextInput::color() const
+{
+ Q_D(const QQuickTextInput);
+ return d->color;
+}
+
+void QQuickTextInput::setColor(const QColor &c)
+{
+ Q_D(QQuickTextInput);
+ if (c != d->color) {
+ d->color = c;
+ update();
+ emit colorChanged(c);
+ }
+}
+
+
+/*!
+ \qmlproperty color QtQuick2::TextInput::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QQuickTextInput::selectionColor() const
+{
+ Q_D(const QQuickTextInput);
+ return d->selectionColor;
+}
+
+void QQuickTextInput::setSelectionColor(const QColor &color)
+{
+ Q_D(QQuickTextInput);
+ if (d->selectionColor == color)
+ return;
+
+ d->selectionColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::Highlight, d->selectionColor);
+ d->control->setPalette(p);
+ if (d->control->hasSelectedText())
+ update();
+ emit selectionColorChanged(color);
+}
+/*!
+ \qmlproperty color QtQuick2::TextInput::selectedTextColor
+
+ The highlighted text color, used in selections.
+*/
+QColor QQuickTextInput::selectedTextColor() const
+{
+ Q_D(const QQuickTextInput);
+ return d->selectedTextColor;
+}
+
+void QQuickTextInput::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QQuickTextInput);
+ if (d->selectedTextColor == color)
+ return;
+
+ d->selectedTextColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::HighlightedText, d->selectedTextColor);
+ d->control->setPalette(p);
+ if (d->control->hasSelectedText())
+ update();
+ emit selectedTextColorChanged(color);
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
+ \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
+
+ Sets the horizontal alignment of the text within the TextInput item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ TextInput does not have vertical alignment, as the natural height is
+ exactly the height of the single line of text. If you set the height
+ manually to something larger, TextInput will always be top aligned
+ vertically. You can use anchors to align it however you want within
+ another item.
+
+ The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
+ \c TextInput.AlignHCenter.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextInput, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
+{
+ Q_D(const QQuickTextInput);
+ return d->hAlign;
+}
+
+void QQuickTextInput::setHAlign(HAlignment align)
+{
+ Q_D(QQuickTextInput);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
+ updateCursorRectangle();
+ }
+}
+
+void QQuickTextInput::resetHAlign()
+{
+ Q_D(QQuickTextInput);
+ d->hAlignImplicit = true;
+ if (d->determineHorizontalAlignment() && isComponentComplete()) {
+ updateCursorRectangle();
+ }
+}
+
+QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
+{
+ Q_D(const QQuickTextInput);
+ QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QQuickTextInput::AlignLeft:
+ effectiveAlignment = QQuickTextInput::AlignRight;
+ break;
+ case QQuickTextInput::AlignRight:
+ effectiveAlignment = QQuickTextInput::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QQuickTextInput);
+ if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
+ QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+ emit q->horizontalAlignmentChanged(alignment);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QQuickTextInputPrivate::determineHorizontalAlignment()
+{
+ if (hAlignImplicit) {
+ // if no explicit alignment has been set, follow the natural layout direction of the text
+ QString text = control->text();
+ if (text.isEmpty())
+ text = control->preeditAreaText();
+ bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
+ return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
+ }
+ return false;
+}
+
+void QQuickTextInputPrivate::mirrorChange()
+{
+ Q_Q(QQuickTextInput);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
+ q->updateCursorRectangle();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::readOnly
+
+ Sets whether user input can modify the contents of the TextInput.
+
+ If readOnly is set to true, then user input will not affect the text
+ property. Any bindings or attempts to set the text property will still
+ work.
+*/
+bool QQuickTextInput::isReadOnly() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->isReadOnly();
+}
+
+void QQuickTextInput::setReadOnly(bool ro)
+{
+ Q_D(QQuickTextInput);
+ if (d->control->isReadOnly() == ro)
+ return;
+
+ setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
+ d->control->setReadOnly(ro);
+ if (!ro)
+ d->control->setCursorPosition(d->control->end());
+
+ emit readOnlyChanged(ro);
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextInput::maximumLength
+ The maximum permitted length of the text in the TextInput.
+
+ If the text is too long, it is truncated at the limit.
+
+ By default, this property contains a value of 32767.
+*/
+int QQuickTextInput::maxLength() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->maxLength();
+}
+
+void QQuickTextInput::setMaxLength(int ml)
+{
+ Q_D(QQuickTextInput);
+ if (d->control->maxLength() == ml)
+ return;
+
+ d->control->setMaxLength(ml);
+
+ emit maximumLengthChanged(ml);
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::cursorVisible
+ Set to true when the TextInput shows a cursor.
+
+ This property is set and unset when the TextInput gets active focus, so that other
+ properties can be bound to whether the cursor is currently showing. As it
+ gets set and unset automatically, when you set the value yourself you must
+ keep in mind that your value may be overwritten.
+
+ It can be set directly in script, for example if a KeyProxy might
+ forward keys to it and you desire it to look active when this happens
+ (but without actually giving it active focus).
+
+ It should not be set directly on the element, like in the below QML,
+ as the specified value will be overridden an lost on focus changes.
+
+ \code
+ TextInput {
+ text: "Text"
+ cursorVisible: false
+ }
+ \endcode
+
+ In the above snippet the cursor will still become visible when the
+ TextInput gains active focus.
+*/
+bool QQuickTextInput::isCursorVisible() const
+{
+ Q_D(const QQuickTextInput);
+ return d->cursorVisible;
+}
+
+void QQuickTextInput::setCursorVisible(bool on)
+{
+ Q_D(QQuickTextInput);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
+ QRect r = d->control->cursorRect();
+ if (d->control->inputMask().isEmpty())
+ updateRect(r);
+ else
+ updateRect();
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int QtQuick2::TextInput::cursorPosition
+ The position of the cursor in the TextInput.
+*/
+int QQuickTextInput::cursorPosition() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->cursor();
+}
+void QQuickTextInput::setCursorPosition(int cp)
+{
+ Q_D(QQuickTextInput);
+ if (cp < 0 || cp > d->control->text().length())
+ return;
+ d->control->moveCursor(cp);
+}
+
+/*!
+ Returns a Rect which encompasses the cursor, but which may be larger than is
+ required. Ignores custom cursor delegates.
+*/
+QRect QQuickTextInput::cursorRectangle() const
+{
+ Q_D(const QQuickTextInput);
+ QRect r = d->control->cursorRect();
+ // Scroll and make consistent with TextEdit
+ // QLineControl inexplicably adds 1 to the height and horizontal padding
+ // for unicode direction markers.
+ r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
+ return r;
+}
+/*!
+ \qmlproperty int QtQuick2::TextInput::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QQuickTextInput::selectionStart() const
+{
+ Q_D(const QQuickTextInput);
+ return d->lastSelectionStart;
+}
+/*!
+ \qmlproperty int QtQuick2::TextInput::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QQuickTextInput::selectionEnd() const
+{
+ Q_D(const QQuickTextInput);
+ return d->lastSelectionEnd;
+}
+/*!
+ \qmlmethod void QtQuick2::TextInput::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+*/
+void QQuickTextInput::select(int start, int end)
+{
+ Q_D(QQuickTextInput);
+ if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
+ return;
+ d->control->setSelection(start, end-start);
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::selectedText
+
+ This read-only property provides the text currently selected in the
+ text input.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+
+ \js
+ myTextInput.text.toString().substring(myTextInput.selectionStart,
+ myTextInput.selectionEnd);
+ \endjs
+*/
+QString QQuickTextInput::selectedText() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->selectedText();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
+
+ Whether the TextInput should gain active focus on a mouse press. By default this is
+ set to true.
+*/
+bool QQuickTextInput::focusOnPress() const
+{
+ Q_D(const QQuickTextInput);
+ return d->focusOnPress;
+}
+
+void QQuickTextInput::setFocusOnPress(bool b)
+{
+ Q_D(QQuickTextInput);
+ if (d->focusOnPress == b)
+ return;
+
+ d->focusOnPress = b;
+
+ emit activeFocusOnPressChanged(d->focusOnPress);
+}
+/*!
+ \qmlproperty bool QtQuick2::TextInput::autoScroll
+
+ Whether the TextInput should scroll when the text is longer than the width. By default this is
+ set to true.
+*/
+bool QQuickTextInput::autoScroll() const
+{
+ Q_D(const QQuickTextInput);
+ return d->autoScroll;
+}
+
+void QQuickTextInput::setAutoScroll(bool b)
+{
+ Q_D(QQuickTextInput);
+ if (d->autoScroll == b)
+ return;
+
+ d->autoScroll = b;
+ //We need to repaint so that the scrolling is taking into account.
+ updateSize(true);
+ updateCursorRectangle();
+ emit autoScrollChanged(d->autoScroll);
+}
+
+#ifndef QT_NO_VALIDATOR
+
+/*!
+ \qmlclass IntValidator QIntValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for integer values.
+
+ IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
+ will accept locale specific digits, group separators, and positive and negative signs. In
+ addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
+ locale.
+*/
+/*!
+ \qmlproperty int QtQuick2::IntValidator::top
+
+ This property holds the validator's highest acceptable value.
+ By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+ \qmlproperty int QtQuick2::IntValidator::bottom
+
+ This property holds the validator's lowest acceptable value.
+ By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+ \qmlclass DoubleValidator QDoubleValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for non-integer numbers.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::DoubleValidator::top
+
+ This property holds the validator's maximum acceptable value.
+ By default, this property contains a value of infinity.
+*/
+/*!
+ \qmlproperty real QtQuick2::DoubleValidator::bottom
+
+ This property holds the validator's minimum acceptable value.
+ By default, this property contains a value of -infinity.
+*/
+/*!
+ \qmlproperty int QtQuick2::DoubleValidator::decimals
+
+ This property holds the validator's maximum number of digits after the decimal point.
+ By default, this property contains a value of 1000.
+*/
+/*!
+ \qmlproperty enumeration QtQuick2::DoubleValidator::notation
+ This property holds the notation of how a string can describe a number.
+
+ The possible values for this property are:
+
+ \list
+ \o DoubleValidator.StandardNotation
+ \o DoubleValidator.ScientificNotation (default)
+ \endlist
+
+ If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+ \qmlclass RegExpValidator QRegExpValidator
+ \inqmlmodule QtQuick 2
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator, which counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regExp QtQuick2::RegExpValidator::regExp
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+ matching "a".
+
+ By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+/*!
+ \qmlproperty Validator QtQuick2::TextInput::validator
+
+ Allows you to set a validator on the TextInput. When a validator is set
+ the TextInput will only accept input which leaves the text property in
+ an acceptable or intermediate state. The accepted signal will only be sent
+ if the text is in an acceptable state when enter is pressed.
+
+ Currently supported validators are IntValidator, DoubleValidator and
+ RegExpValidator. An example of using validators is shown below, which allows
+ input of integers between 11 and 31 into the text input:
+
+ \code
+ import QtQuick 1.0
+ TextInput{
+ validator: IntValidator{bottom: 11; top: 31;}
+ focus: true
+ }
+ \endcode
+
+ \sa acceptableInput, inputMask
+*/
+
+QValidator* QQuickTextInput::validator() const
+{
+ Q_D(const QQuickTextInput);
+ //###const cast isn't good, but needed for property system?
+ return const_cast<QValidator*>(d->control->validator());
+}
+
+void QQuickTextInput::setValidator(QValidator* v)
+{
+ Q_D(QQuickTextInput);
+ if (d->control->validator() == v)
+ return;
+
+ d->control->setValidator(v);
+ if (!d->control->hasAcceptableInput()) {
+ d->oldValidity = false;
+ emit acceptableInputChanged();
+ }
+
+ emit validatorChanged();
+}
+#endif // QT_NO_VALIDATOR
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::inputMask
+
+ Allows you to set an input mask on the TextInput, restricting the allowable
+ text inputs. See QLineEdit::inputMask for further details, as the exact
+ same mask strings are used by TextInput.
+
+ \sa acceptableInput, validator
+*/
+QString QQuickTextInput::inputMask() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->inputMask();
+}
+
+void QQuickTextInput::setInputMask(const QString &im)
+{
+ Q_D(QQuickTextInput);
+ if (d->control->inputMask() == im)
+ return;
+
+ d->control->setInputMask(im);
+ emit inputMaskChanged(d->control->inputMask());
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::acceptableInput
+
+ This property is always true unless a validator or input mask has been set.
+ If a validator or input mask has been set, this property will only be true
+ if the current text is acceptable to the validator or input mask as a final
+ string (not as an intermediate string).
+*/
+bool QQuickTextInput::hasAcceptableInput() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->hasAcceptableInput();
+}
+
+/*!
+ \qmlsignal QtQuick2::TextInput::onAccepted()
+
+ This handler is called when the Return or Enter key is pressed.
+ Note that if there is a \l validator or \l inputMask set on the text
+ input, the handler will only be emitted if the input is in an acceptable
+ state.
+*/
+
+void QQuickTextInputPrivate::updateInputMethodHints()
+{
+ Q_Q(QQuickTextInput);
+ Qt::InputMethodHints hints = inputMethodHints;
+ uint echo = control->echoMode();
+ if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
+ hints |= Qt::ImhHiddenText;
+ else if (echo == QQuickTextInput::PasswordEchoOnEdit)
+ hints &= ~Qt::ImhHiddenText;
+ if (echo != QQuickTextInput::Normal)
+ hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ q->setInputMethodHints(hints);
+}
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::echoMode
+
+ Specifies how the text should be displayed in the TextInput.
+ \list
+ \o TextInput.Normal - Displays the text as it is. (Default)
+ \o TextInput.Password - Displays asterisks instead of characters.
+ \o TextInput.NoEcho - Displays nothing.
+ \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
+ while editing, otherwise displays asterisks.
+ \endlist
+*/
+QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
+{
+ Q_D(const QQuickTextInput);
+ return (QQuickTextInput::EchoMode)d->control->echoMode();
+}
+
+void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
+{
+ Q_D(QQuickTextInput);
+ if (echoMode() == echo)
+ return;
+ d->control->setEchoMode((QLineControl::EchoMode)echo);
+ d->updateInputMethodHints();
+ q_textChanged();
+ emit echoModeChanged(echoMode());
+}
+
+Qt::InputMethodHints QQuickTextInput::imHints() const
+{
+ Q_D(const QQuickTextInput);
+ return d->inputMethodHints;
+}
+
+void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickTextInput);
+ if (d->inputMethodHints == hints)
+ return;
+ d->inputMethodHints = hints;
+ d->updateInputMethodHints();
+}
+
+/*!
+ \qmlproperty Component QtQuick2::TextInput::cursorDelegate
+ The delegate for the cursor in the TextInput.
+
+ If you set a cursorDelegate for a TextInput, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the TextInput when a cursor is
+ needed, and the x property of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
+QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
+{
+ Q_D(const QQuickTextInput);
+ return d->cursorComponent;
+}
+
+void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
+{
+ Q_D(QQuickTextInput);
+ if (d->cursorComponent == c)
+ return;
+
+ d->cursorComponent = c;
+ if (!c) {
+ //note that the components are owned by something else
+ delete d->cursorItem;
+ } else {
+ d->startCreatingCursor();
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QQuickTextInputPrivate::startCreatingCursor()
+{
+ Q_Q(QQuickTextInput);
+ if (cursorComponent->isReady()) {
+ q->createCursor();
+ } else if (cursorComponent->isLoading()) {
+ q->connect(cursorComponent, SIGNAL(statusChanged(int)),
+ q, SLOT(createCursor()));
+ } else { // isError
+ qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
+ }
+}
+
+void QQuickTextInput::createCursor()
+{
+ Q_D(QQuickTextInput);
+ if (d->cursorComponent->isError()) {
+ qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
+ return;
+ }
+
+ if (!d->cursorComponent->isReady())
+ return;
+
+ if (d->cursorItem)
+ delete d->cursorItem;
+ QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
+ QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
+ d->cursorItem = qobject_cast<QQuickItem*>(object);
+ if (!d->cursorItem) {
+ delete object;
+ qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
+ return;
+ }
+
+ QDeclarative_setParent_noEvent(d->cursorItem, this);
+ d->cursorItem->setParentItem(this);
+ d->cursorItem->setX(d->control->cursorToX());
+ d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
+}
+
+/*!
+ \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
+
+ This function takes a character position and returns the rectangle that the
+ cursor would occupy, if it was placed at that character position.
+
+ This is similar to setting the cursorPosition, and then querying the cursor
+ rectangle, but the cursorPosition is not changed.
+*/
+QRectF QQuickTextInput::positionToRectangle(int pos) const
+{
+ Q_D(const QQuickTextInput);
+ if (pos > d->control->cursorPosition())
+ pos += d->control->preeditAreaText().length();
+ return QRectF(d->control->cursorToX(pos)-d->hscroll,
+ 0.0,
+ d->control->cursorWidth(),
+ cursorRectangle().height());
+}
+
+/*!
+ \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
+
+ This function returns the character position at
+ x pixels from the left of the textInput. Position 0 is before the
+ first character, position 1 is after the first character but before the second,
+ and so on until position text.length, which is after all characters.
+
+ This means that for all x values before the first character this function returns 0,
+ and for all x values after the last character this function returns text.length.
+
+ The cursor position type specifies how the cursor position should be resolved.
+
+ \list
+ \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
+ \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
+ \endlist
+*/
+int QQuickTextInput::positionAt(int x) const
+{
+ return positionAt(x, CursorBetweenCharacters);
+}
+
+int QQuickTextInput::positionAt(int x, CursorPosition position) const
+{
+ Q_D(const QQuickTextInput);
+ int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
+ const int cursor = d->control->cursor();
+ if (pos > cursor) {
+ const int preeditLength = d->control->preeditAreaText().length();
+ pos = pos > cursor + preeditLength
+ ? pos - preeditLength
+ : cursor;
+ }
+ return pos;
+}
+
+void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
+{
+ Q_D(QQuickTextInput);
+ // Don't allow MacOSX up/down support, and we don't allow a completer.
+ bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
+ if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
+ // Ignore when moving off the end unless there is a selection,
+ // because then moving will do something (deselect).
+ int cursorPosition = d->control->cursor();
+ if (cursorPosition == 0)
+ ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
+ if (cursorPosition == d->control->text().length())
+ ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
+ }
+ if (ignore) {
+ ev->ignore();
+ } else {
+ d->control->processKeyEvent(ev);
+ }
+ if (!ev->isAccepted())
+ QQuickImplicitSizeItem::keyPressEvent(ev);
+}
+
+void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
+{
+ Q_D(QQuickTextInput);
+ const bool wasComposing = d->control->preeditAreaText().length() > 0;
+ if (d->control->isReadOnly()) {
+ ev->ignore();
+ } else {
+ d->control->processInputMethodEvent(ev);
+ }
+ if (!ev->isAccepted())
+ QQuickImplicitSizeItem::inputMethodEvent(ev);
+
+ if (wasComposing != (d->control->preeditAreaText().length() > 0))
+ emit inputMethodComposingChanged();
+}
+
+void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextInput);
+
+ if (d->selectByMouse && event->button() == Qt::LeftButton) {
+ d->control->commitPreedit();
+ int cursor = d->xToPos(event->localPos().x());
+ d->control->selectWordAtPos(cursor);
+ event->setAccepted(true);
+ if (!d->hasPendingTripleClick()) {
+ d->tripleClickStartPoint = event->localPos().toPoint();
+ d->tripleClickTimer.start();
+ }
+ } else {
+ if (d->sendMouseEventToInputContext(event))
+ return;
+ QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
+ }
+}
+
+void QQuickTextInput::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextInput);
+
+ d->pressPos = event->localPos();
+
+ if (d->focusOnPress) {
+ bool hadActiveFocus = hasActiveFocus();
+ forceActiveFocus();
+ // re-open input panel on press if already focused
+ if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
+ openSoftwareInputPanel();
+ }
+ if (d->selectByMouse) {
+ setKeepMouseGrab(false);
+ d->selectPressed = true;
+ QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
+ if (d->hasPendingTripleClick()
+ && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
+ event->setAccepted(true);
+ selectAll();
+ return;
+ }
+ }
+
+ if (d->sendMouseEventToInputContext(event))
+ return;
+
+ bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
+ int cursor = d->xToPos(event->localPos().x());
+ d->control->moveCursor(cursor, mark);
+ event->setAccepted(true);
+}
+
+void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextInput);
+
+ if (d->selectPressed) {
+ if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
+ setKeepMouseGrab(true);
+
+ if (d->control->composeMode()) {
+ // start selection
+ int startPos = d->xToPos(d->pressPos.x());
+ int currentPos = d->xToPos(event->localPos().x());
+ if (startPos != currentPos)
+ d->control->setSelection(startPos, currentPos - startPos);
+ } else {
+ moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
+ }
+ event->setAccepted(true);
+ } else {
+ QQuickImplicitSizeItem::mouseMoveEvent(event);
+ }
+}
+
+void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickTextInput);
+ if (d->sendMouseEventToInputContext(event))
+ return;
+ if (d->selectPressed) {
+ d->selectPressed = false;
+ setKeepMouseGrab(false);
+ }
+ d->control->processEvent(event);
+ if (!event->isAccepted())
+ QQuickImplicitSizeItem::mouseReleaseEvent(event);
+}
+
+bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
+{
+#if !defined QT_NO_IM
+ if (control->composeMode()) {
+ int tmp_cursor = xToPos(event->localPos().x());
+ int mousePos = tmp_cursor - control->cursor();
+ if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
+ if (event->type() == QEvent::MouseButtonRelease) {
+ qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
+ }
+ return true;
+ }
+ }
+#else
+ Q_UNUSED(event);
+ Q_UNUSED(eventType)
+#endif
+
+ return false;
+}
+
+void QQuickTextInput::mouseUngrabEvent()
+{
+ Q_D(QQuickTextInput);
+ d->selectPressed = false;
+ setKeepMouseGrab(false);
+}
+
+bool QQuickTextInput::event(QEvent* ev)
+{
+ Q_D(QQuickTextInput);
+ //Anything we don't deal with ourselves, pass to the control
+ bool handled = false;
+ switch (ev->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease://###Should the control be doing anything with release?
+ case QEvent::InputMethod:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ break;
+ default:
+ handled = d->control->processEvent(ev);
+ }
+ if (!handled)
+ handled = QQuickImplicitSizeItem::event(ev);
+ return handled;
+}
+
+void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width()) {
+ updateSize();
+ updateCursorRectangle();
+ }
+ QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+int QQuickTextInputPrivate::calculateTextWidth()
+{
+ return qRound(control->naturalTextWidth());
+}
+
+void QQuickTextInputPrivate::updateHorizontalScroll()
+{
+ Q_Q(QQuickTextInput);
+ const int preeditLength = control->preeditAreaText().length();
+ const int width = q->width();
+ int widthUsed = calculateTextWidth();
+
+ if (!autoScroll || widthUsed <= width) {
+ QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
+ // text fits in br; use hscroll for alignment
+ switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
+ case Qt::AlignRight:
+ hscroll = widthUsed - width;
+ break;
+ case Qt::AlignHCenter:
+ hscroll = (widthUsed - width) / 2;
+ break;
+ default:
+ // Left
+ hscroll = 0;
+ break;
+ }
+ } else {
+ int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
+ if (cix - hscroll >= width) {
+ // text doesn't fit, cursor is to the right of br (scroll right)
+ hscroll = cix - width;
+ } else if (cix - hscroll < 0 && hscroll < widthUsed) {
+ // text doesn't fit, cursor is to the left of br (scroll left)
+ hscroll = cix;
+ } else if (widthUsed - hscroll < width) {
+ // text doesn't fit, text document is to the left of br; align
+ // right
+ hscroll = widthUsed - width;
+ }
+ if (preeditLength > 0) {
+ // check to ensure long pre-edit text doesn't push the cursor
+ // off to the left
+ cix = qRound(control->cursorToX(
+ control->cursor() + qMax(0, control->preeditCursor() - 1)));
+ if (cix < hscroll)
+ hscroll = cix;
+ }
+ }
+}
+
+QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ Q_D(QQuickTextInput);
+
+ QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
+ if (node == 0)
+ node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
+ d->textNode = node;
+
+ if (!d->textLayoutDirty) {
+ QSGSimpleRectNode *cursorNode = node->cursorNode();
+ if (cursorNode != 0 && !isReadOnly()) {
+ QFontMetrics fm = QFontMetrics(d->font);
+ // the y offset is there to keep the baseline constant in case we have script changes in the text.
+ QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
+ offset.rx() += d->control->cursorToX();
+
+ QRect br(boundingRect().toRect());
+ cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
+
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ } else {
+ d->showCursor();
+ }
+ }
+ } else {
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
+ QPoint offset = QPoint(0,0);
+ QFontMetrics fm = QFontMetrics(d->font);
+ QRect br(boundingRect().toRect());
+ if (d->autoScroll) {
+ // the y offset is there to keep the baseline constant in case we have script changes in the text.
+ offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
+ } else {
+ offset = QPoint(d->hscroll, 0);
+ }
+
+ QTextLayout *textLayout = d->control->textLayout();
+ if (!textLayout->text().isEmpty()) {
+ node->addTextLayout(offset, textLayout, d->color,
+ QQuickText::Normal, QColor(),
+ d->selectionColor, d->selectedTextColor,
+ d->control->selectionStart(),
+ d->control->selectionEnd() - 1); // selectionEnd() returns first char after
+ // selection
+ }
+
+ if (!isReadOnly() && d->cursorItem == 0) {
+ offset.rx() += d->control->cursorToX();
+ node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ } else {
+ d->showCursor();
+ }
+ }
+
+ d->textLayoutDirty = false;
+ }
+
+ return node;
+}
+
+QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QQuickTextInput);
+ switch (property) {
+ case Qt::ImEnabled:
+ return QVariant((bool)(flags() & ItemAcceptsInputMethod));
+ case Qt::ImHints:
+ return QVariant((int)inputMethodHints());
+ case Qt::ImCursorRectangle:
+ return cursorRectangle();
+ case Qt::ImFont:
+ return font();
+ case Qt::ImCursorPosition:
+ return QVariant(d->control->cursor());
+ case Qt::ImSurroundingText:
+ if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
+ && !d->control->passwordEchoEditing()) {
+ return QVariant(displayText());
+ } else {
+ return QVariant(d->control->realText());
+ }
+ case Qt::ImCurrentSelection:
+ return QVariant(selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(maxLength());
+ case Qt::ImAnchorPosition:
+ if (d->control->selectionStart() == d->control->selectionEnd())
+ return QVariant(d->control->cursor());
+ else if (d->control->selectionStart() == d->control->cursor())
+ return QVariant(d->control->selectionEnd());
+ else
+ return QVariant(d->control->selectionStart());
+ default:
+ return QVariant();
+ }
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::deselect()
+
+ Removes active text selection.
+*/
+void QQuickTextInput::deselect()
+{
+ Q_D(QQuickTextInput);
+ d->control->deselect();
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::selectAll()
+
+ Causes all text to be selected.
+*/
+void QQuickTextInput::selectAll()
+{
+ Q_D(QQuickTextInput);
+ d->control->setSelection(0, d->control->text().length());
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
+bool QQuickTextInput::isRightToLeft(int start, int end)
+{
+ Q_D(QQuickTextInput);
+ if (start > end) {
+ qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
+ return false;
+ } else {
+ return d->control->text().mid(start, end - start).isRightToLeft();
+ }
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod QtQuick2::TextInput::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
+void QQuickTextInput::cut()
+{
+ Q_D(QQuickTextInput);
+ d->control->copy();
+ d->control->del();
+}
+
+/*!
+ \qmlmethod QtQuick2::TextInput::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
+void QQuickTextInput::copy()
+{
+ Q_D(QQuickTextInput);
+ d->control->copy();
+}
+
+/*!
+ \qmlmethod QtQuick2::TextInput::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
+void QQuickTextInput::paste()
+{
+ Q_D(QQuickTextInput);
+ if (!d->control->isReadOnly())
+ d->control->paste();
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
+void QQuickTextInput::selectWord()
+{
+ Q_D(QQuickTextInput);
+ d->control->selectWordAtPos(d->control->cursor());
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::passwordCharacter
+
+ This is the character displayed when echoMode is set to Password or
+ PasswordEchoOnEdit. By default it is an asterisk.
+
+ If this property is set to a string with more than one character,
+ the first character is used. If the string is empty, the value
+ is ignored and the property is not set.
+*/
+QString QQuickTextInput::passwordCharacter() const
+{
+ Q_D(const QQuickTextInput);
+ return QString(d->control->passwordCharacter());
+}
+
+void QQuickTextInput::setPasswordCharacter(const QString &str)
+{
+ Q_D(QQuickTextInput);
+ if (str.length() < 1)
+ return;
+ d->control->setPasswordCharacter(str.constData()[0]);
+ EchoMode echoMode_ = echoMode();
+ if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
+ updateSize();
+ }
+ emit passwordCharacterChanged();
+}
+
+/*!
+ \qmlproperty string QtQuick2::TextInput::displayText
+
+ This is the text displayed in the TextInput.
+
+ If \l echoMode is set to TextInput::Normal, this holds the
+ same value as the TextInput::text property. Otherwise,
+ this property holds the text visible to the user, while
+ the \l text property holds the actual entered text.
+*/
+QString QQuickTextInput::displayText() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->displayText();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::selectByMouse
+
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
+bool QQuickTextInput::selectByMouse() const
+{
+ Q_D(const QQuickTextInput);
+ return d->selectByMouse;
+}
+
+void QQuickTextInput::setSelectByMouse(bool on)
+{
+ Q_D(QQuickTextInput);
+ if (d->selectByMouse != on) {
+ d->selectByMouse = on;
+ emit selectByMouseChanged(on);
+ }
+}
+
+/*!
+ \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextInput.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
+
+QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
+{
+ Q_D(const QQuickTextInput);
+ return d->mouseSelectionMode;
+}
+
+void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
+{
+ Q_D(QQuickTextInput);
+ if (d->mouseSelectionMode != mode) {
+ d->mouseSelectionMode = mode;
+ emit mouseSelectionModeChanged(mode);
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::canPaste
+
+ Returns true if the TextInput is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
+bool QQuickTextInput::canPaste() const
+{
+ Q_D(const QQuickTextInput);
+ return d->canPaste;
+}
+
+void QQuickTextInput::moveCursorSelection(int position)
+{
+ Q_D(QQuickTextInput);
+ d->control->moveCursor(position, true);
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextInput.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified position and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextInput.SelectCharacters)
+ moveCursorSelection(7, TextInput.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
+void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
+{
+ Q_D(QQuickTextInput);
+
+ if (mode == SelectCharacters) {
+ d->control->moveCursor(pos, true);
+ } else if (pos != d->control->cursor()){
+ const int cursor = d->control->cursor();
+ int anchor;
+ if (!d->control->hasSelectedText())
+ anchor = d->control->cursor();
+ else if (d->control->selectionStart() == d->control->cursor())
+ anchor = d->control->selectionEnd();
+ else
+ anchor = d->control->selectionStart();
+
+ if (anchor < pos || (anchor == pos && cursor < pos)) {
+ const QString text = d->control->text();
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
+ finder.setPosition(anchor);
+
+ const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
+ if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
+ || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
+ finder.toPreviousBoundary();
+ }
+ anchor = finder.position() != -1 ? finder.position() : 0;
+
+ finder.setPosition(pos);
+ if (pos > 0 && !finder.boundaryReasons())
+ finder.toNextBoundary();
+ const int cursor = finder.position() != -1 ? finder.position() : text.length();
+
+ d->control->setSelection(anchor, cursor - anchor);
+ } else if (anchor > pos || (anchor == pos && cursor > pos)) {
+ const QString text = d->control->text();
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
+ finder.setPosition(anchor);
+
+ const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
+ if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
+ || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
+ finder.toNextBoundary();
+ }
+
+ anchor = finder.position() != -1 ? finder.position() : text.length();
+
+ finder.setPosition(pos);
+ if (pos < text.length() && !finder.boundaryReasons())
+ finder.toPreviousBoundary();
+ const int cursor = finder.position() != -1 ? finder.position() : 0;
+
+ d->control->setSelection(anchor, cursor - anchor);
+ }
+ }
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus()
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
+void QQuickTextInput::openSoftwareInputPanel()
+{
+ if (qGuiApp)
+ qGuiApp->inputPanel()->show();
+}
+
+/*!
+ \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus();
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
+void QQuickTextInput::closeSoftwareInputPanel()
+{
+ if (qGuiApp)
+ qGuiApp->inputPanel()->hide();
+}
+
+void QQuickTextInput::focusInEvent(QFocusEvent *event)
+{
+ Q_D(const QQuickTextInput);
+ if (d->focusOnPress && !isReadOnly())
+ openSoftwareInputPanel();
+ QQuickImplicitSizeItem::focusInEvent(event);
+}
+
+void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ Q_D(QQuickTextInput);
+ if (change == ItemActiveFocusHasChanged) {
+ bool hasFocus = value.boolValue;
+ d->focused = hasFocus;
+ setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
+ if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
+ d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
+ if (!hasFocus)
+ d->control->deselect();
+ }
+ QQuickItem::itemChange(change, value);
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
+
+
+ This property holds whether the TextInput has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextInput to edit or commit the partial text. This property can be
+ used to determine when to disable events handlers that may interfere with
+ the correct operation of an input method.
+*/
+bool QQuickTextInput::isInputMethodComposing() const
+{
+ Q_D(const QQuickTextInput);
+ return d->control->preeditAreaText().length() > 0;
+}
+
+void QQuickTextInputPrivate::init()
+{
+ Q_Q(QQuickTextInput);
+ control->setParent(q);//Now mandatory due to accessibility changes
+ control->setCursorWidth(1);
+ control->setPasswordCharacter(QLatin1Char('*'));
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QQuickItem::ItemAcceptsInputMethod);
+ q->setFlag(QQuickItem::ItemHasContents);
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(cursorPosChanged()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(selectionChanged()));
+ q->connect(control, SIGNAL(textChanged(QString)),
+ q, SLOT(q_textChanged()));
+ q->connect(control, SIGNAL(accepted()),
+ q, SIGNAL(accepted()));
+ q->connect(control, SIGNAL(updateNeeded(QRect)),
+ q, SLOT(updateRect(QRect)));
+#ifndef QT_NO_CLIPBOARD
+ q->connect(q, SIGNAL(readOnlyChanged(bool)),
+ q, SLOT(q_canPasteChanged()));
+ q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
+ q, SLOT(q_canPasteChanged()));
+ canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
+#endif // QT_NO_CLIPBOARD
+ q->connect(control, SIGNAL(updateMicroFocus()),
+ q, SLOT(updateCursorRectangle()));
+ q->connect(control, SIGNAL(displayTextChanged(QString)),
+ q, SLOT(updateRect()));
+ q->updateSize();
+ imHints &= ~Qt::ImhMultiLine;
+ oldValidity = control->hasAcceptableInput();
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
+ QPalette p = control->palette();
+ selectedTextColor = p.color(QPalette::HighlightedText);
+ selectionColor = p.color(QPalette::Highlight);
+ determineHorizontalAlignment();
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option = control->textLayout()->textOption();
+ option.setUseDesignMetrics(true);
+ control->textLayout()->setTextOption(option);
+ }
+}
+
+void QQuickTextInput::cursorPosChanged()
+{
+ Q_D(QQuickTextInput);
+ updateCursorRectangle();
+ emit cursorPositionChanged();
+ // XXX todo - not in 4.8?
+#if 0
+ d->control->resetCursorBlinkTimer();
+#endif
+
+ if (!d->control->hasSelectedText()) {
+ if (d->lastSelectionStart != d->control->cursor()) {
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if (d->lastSelectionEnd != d->control->cursor()) {
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+ }
+}
+
+void QQuickTextInput::updateCursorRectangle()
+{
+ Q_D(QQuickTextInput);
+ d->determineHorizontalAlignment();
+ d->updateHorizontalScroll();
+ updateRect();//TODO: Only update rect between pos's
+ updateMicroFocus();
+ emit cursorRectangleChanged();
+ if (d->cursorItem)
+ d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
+}
+
+void QQuickTextInput::selectionChanged()
+{
+ Q_D(QQuickTextInput);
+ updateRect();//TODO: Only update rect in selection
+ emit selectedTextChanged();
+
+ if (d->lastSelectionStart != d->control->selectionStart()) {
+ d->lastSelectionStart = d->control->selectionStart();
+ if (d->lastSelectionStart == -1)
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if (d->lastSelectionEnd != d->control->selectionEnd()) {
+ d->lastSelectionEnd = d->control->selectionEnd();
+ if (d->lastSelectionEnd == -1)
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+}
+
+void QQuickTextInput::q_textChanged()
+{
+ Q_D(QQuickTextInput);
+ emit textChanged();
+ emit displayTextChanged();
+ updateSize();
+ d->determineHorizontalAlignment();
+ d->updateHorizontalScroll();
+ updateMicroFocus();
+ if (hasAcceptableInput() != d->oldValidity) {
+ d->oldValidity = hasAcceptableInput();
+ emit acceptableInputChanged();
+ }
+}
+
+void QQuickTextInputPrivate::showCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(color);
+}
+
+void QQuickTextInputPrivate::hideCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
+}
+
+void QQuickTextInput::updateRect(const QRect &r)
+{
+ Q_D(QQuickTextInput);
+ if (!isComponentComplete())
+ return;
+
+ if (r.isEmpty()) {
+ d->textLayoutDirty = true;
+ }
+
+ update();
+}
+
+QRectF QQuickTextInput::boundingRect() const
+{
+ Q_D(const QQuickTextInput);
+ QRectF r = QQuickImplicitSizeItem::boundingRect();
+
+ int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ r.setRight(r.right() + cursorWidth);
+ return r;
+}
+
+void QQuickTextInput::updateSize(bool needsRedraw)
+{
+ Q_D(QQuickTextInput);
+ int w = width();
+ int h = height();
+ setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
+ if (w==width() && h==height() && needsRedraw)
+ update();
+}
+
+void QQuickTextInput::q_canPasteChanged()
+{
+ Q_D(QQuickTextInput);
+ bool old = d->canPaste;
+#ifndef QT_NO_CLIPBOARD
+ d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
+#endif
+ if (d->canPaste != old)
+ emit canPasteChanged();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
new file mode 100644
index 0000000000..3ea86477a1
--- /dev/null
+++ b/src/quick/items/qquicktextinput_p.h
@@ -0,0 +1,300 @@
+// Commit: 2f173e4945dd8414636c1061acfaf9c2d8b718d8
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKTEXTINPUT_P_H
+#define QQUICKTEXTINPUT_P_H
+
+#include "qquickimplicitsizeitem_p.h"
+#include <QtGui/qvalidator.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTextInputPrivate;
+class QValidator;
+class Q_AUTOTEST_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(EchoMode)
+ Q_ENUMS(SelectionMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
+
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
+
+ Q_PROPERTY(int maximumLength READ maxLength WRITE setMaxLength NOTIFY maximumLengthChanged)
+#ifndef QT_NO_VALIDATOR
+ Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
+#endif
+ Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ imHints WRITE setIMHints)
+
+ Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
+ Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
+ Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
+ Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged)
+ Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged)
+ Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged)
+ Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
+ Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
+ Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
+
+public:
+ QQuickTextInput(QQuickItem * parent=0);
+ ~QQuickTextInput();
+
+ enum EchoMode {//To match QLineEdit::EchoMode
+ Normal,
+ NoEcho,
+ Password,
+ PasswordEchoOnEdit
+ };
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ enum SelectionMode {
+ SelectCharacters,
+ SelectWords
+ };
+
+ enum CursorPosition {
+ CursorBetweenCharacters,
+ CursorOnCharacter
+ };
+
+ //Auxilliary functions needed to control the TextInput from QML
+ Q_INVOKABLE int positionAt(int x) const;
+ Q_INVOKABLE int positionAt(int x, CursorPosition position) const;
+ Q_INVOKABLE QRectF positionToRectangle(int pos) const;
+ Q_INVOKABLE void moveCursorSelection(int pos);
+ Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
+
+ Q_INVOKABLE void openSoftwareInputPanel();
+ Q_INVOKABLE void closeSoftwareInputPanel();
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ bool isReadOnly() const;
+ void setReadOnly(bool);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int cp);
+
+ QRect cursorRectangle() const;
+
+ int selectionStart() const;
+ int selectionEnd() const;
+
+ QString selectedText() const;
+
+ int maxLength() const;
+ void setMaxLength(int ml);
+
+#ifndef QT_NO_VALIDATOR
+ QValidator * validator() const;
+ void setValidator(QValidator* v);
+#endif
+ QString inputMask() const;
+ void setInputMask(const QString &im);
+
+ EchoMode echoMode() const;
+ void setEchoMode(EchoMode echo);
+
+ QString passwordCharacter() const;
+ void setPasswordCharacter(const QString &str);
+
+ QString displayText() const;
+
+ QDeclarativeComponent* cursorDelegate() const;
+ void setCursorDelegate(QDeclarativeComponent*);
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool);
+
+ bool autoScroll() const;
+ void setAutoScroll(bool);
+
+ bool selectByMouse() const;
+ void setSelectByMouse(bool);
+
+ SelectionMode mouseSelectionMode() const;
+ void setMouseSelectionMode(SelectionMode mode);
+
+ bool hasAcceptableInput() const;
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+ QRectF boundingRect() const;
+ bool canPaste() const;
+
+ bool isInputMethodComposing() const;
+
+ Qt::InputMethodHints imHints() const;
+ void setIMHints(Qt::InputMethodHints hints);
+
+Q_SIGNALS:
+ void textChanged();
+ void cursorPositionChanged();
+ void cursorRectangleChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectedTextChanged();
+ void accepted();
+ void acceptableInputChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void maximumLengthChanged(int maximumLength);
+ void validatorChanged();
+ void inputMaskChanged(const QString &inputMask);
+ void echoModeChanged(EchoMode echoMode);
+ void passwordCharacterChanged();
+ void displayTextChanged();
+ void activeFocusOnPressChanged(bool activeFocusOnPress);
+ void autoScrollChanged(bool autoScroll);
+ void selectByMouseChanged(bool selectByMouse);
+ void mouseSelectionModeChanged(SelectionMode mode);
+ void canPasteChanged();
+ void inputMethodComposingChanged();
+ void effectiveHorizontalAlignmentChanged();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void keyPressEvent(QKeyEvent* ev);
+ void inputMethodEvent(QInputMethodEvent *);
+ void mouseUngrabEvent();
+ bool event(QEvent *e);
+ void focusInEvent(QFocusEvent *event);
+ virtual void itemChange(ItemChange, const ItemChangeData &);
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
+
+public Q_SLOTS:
+ void selectAll();
+ void selectWord();
+ void select(int start, int end);
+ void deselect();
+ bool isRightToLeft(int start, int end);
+#ifndef QT_NO_CLIPBOARD
+ void cut();
+ void copy();
+ void paste();
+#endif
+
+private Q_SLOTS:
+ void updateSize(bool needsRedraw = true);
+ void q_textChanged();
+ void selectionChanged();
+ void createCursor();
+ void cursorPosChanged();
+ void updateCursorRectangle();
+ void updateRect(const QRect &r = QRect());
+ void q_canPasteChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickTextInput)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTextInput)
+#ifndef QT_NO_VALIDATOR
+QML_DECLARE_TYPE(QValidator)
+QML_DECLARE_TYPE(QIntValidator)
+QML_DECLARE_TYPE(QDoubleValidator)
+QML_DECLARE_TYPE(QRegExpValidator)
+#endif
+
+QT_END_HEADER
+
+#endif // QQUICKTEXTINPUT_P_H
diff --git a/src/declarative/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 900b0804bb..900b0804bb 100644
--- a/src/declarative/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
new file mode 100644
index 0000000000..bfb3591d04
--- /dev/null
+++ b/src/quick/items/qquicktextnode.cpp
@@ -0,0 +1,1344 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquicktextnode_p.h"
+#include <QtQuick/qsgsimplerectnode.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <private/qsgdistancefieldglyphnode_p.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+
+#include <QtCore/qpoint.h>
+#include <qmath.h>
+#include <qtextdocument.h>
+#include <qtextlayout.h>
+#include <qabstracttextdocumentlayout.h>
+#include <qxmlstream.h>
+#include <qrawfont.h>
+#include <qtexttable.h>
+#include <qtextlist.h>
+#include <private/qdeclarativestyledtext_p.h>
+#include <private/qfont_p.h>
+#include <private/qfontengine_p.h>
+#include <private/qrawfont_p.h>
+#include <private/qtextimagehandler_p.h>
+#include <private/qtextdocumentlayout_p.h>
+#include <qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Creates an empty QQuickTextNode
+*/
+QQuickTextNode::QQuickTextNode(QSGContext *context)
+ : m_context(context), m_cursorNode(0)
+{
+#if defined(QML_RUNTIME_TESTING)
+ description = QLatin1String("text");
+#endif
+}
+
+QQuickTextNode::~QQuickTextNode()
+{
+ qDeleteAll(m_textures);
+}
+
+#if 0
+void QQuickTextNode::setColor(const QColor &color)
+{
+ if (m_usePixmapCache) {
+ setUpdateFlag(UpdateNodes);
+ } else {
+ for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
+ if (childNode->subType() == GlyphNodeSubType) {
+ QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
+ if (glyphNode->color() == m_color)
+ glyphNode->setColor(color);
+ } else if (childNode->subType() == SolidRectNodeSubType) {
+ QSGSimpleRectNode *solidRectNode = static_cast<QSGSimpleRectNode *>(childNode);
+ if (solidRectNode->color() == m_color)
+ solidRectNode->setColor(color);
+ }
+ }
+ }
+ m_color = color;
+}
+
+void QQuickTextNode::setStyleColor(const QColor &styleColor)
+{
+ if (m_textStyle != QQuickTextNode::NormalTextStyle) {
+ if (m_usePixmapCache) {
+ setUpdateFlag(UpdateNodes);
+ } else {
+ for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
+ if (childNode->subType() == GlyphNodeSubType) {
+ QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
+ if (glyphNode->color() == m_styleColor)
+ glyphNode->setColor(styleColor);
+ } else if (childNode->subType() == SolidRectNodeSubType) {
+ QSGSimpleRectNode *solidRectNode = static_cast<QSGSimpleRectNode *>(childNode);
+ if (solidRectNode->color() == m_styleColor)
+ solidRectNode->setColor(styleColor);
+ }
+ }
+ }
+ }
+ m_styleColor = styleColor;
+}
+#endif
+
+QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
+ QQuickText::TextStyle style, const QColor &styleColor,
+ QSGNode *parentNode)
+{
+ QSGGlyphNode *node = m_context->createGlyphNode();
+ node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
+ node->setStyle(style);
+ node->setStyleColor(styleColor);
+ node->setColor(color);
+ node->update();
+
+ /* We flag the geometry as static, but we never call markVertexDataDirty
+ or markIndexDataDirty on them. This is because all text nodes are
+ discarded when a change occurs. If we start appending/removing from
+ existing geometry, then we also need to start marking the geometry as
+ dirty.
+ */
+ node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
+ node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
+
+ if (parentNode == 0)
+ parentNode = this;
+ parentNode->appendChildNode(node);
+
+ return node;
+}
+
+void QQuickTextNode::setCursor(const QRectF &rect, const QColor &color)
+{
+ if (m_cursorNode != 0)
+ delete m_cursorNode;
+
+ m_cursorNode = new QSGSimpleRectNode(rect, color);
+ appendChildNode(m_cursorNode);
+}
+
+namespace {
+
+ struct BinaryTreeNode {
+ enum SelectionState {
+ Unselected,
+ Selected
+ };
+
+ BinaryTreeNode()
+ : selectionState(Unselected)
+ , clipNode(0)
+ , decorations(QQuickTextNode::NoDecoration)
+ , ascent(0.0)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+
+ }
+
+ BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a)
+ : boundingRect(brect)
+ , selectionState(selState)
+ , clipNode(0)
+ , decorations(QQuickTextNode::NoDecoration)
+ , image(i)
+ , ascent(a)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+ }
+
+ BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
+ const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc,
+ const QPointF &pos, qreal a)
+ : glyphRun(g)
+ , boundingRect(brect)
+ , selectionState(selState)
+ , clipNode(0)
+ , decorations(decs)
+ , color(c)
+ , backgroundColor(bc)
+ , position(pos)
+ , ascent(a)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+ }
+
+ QGlyphRun glyphRun;
+ QRectF boundingRect;
+ SelectionState selectionState;
+ QSGClipNode *clipNode;
+ QQuickTextNode::Decorations decorations;
+ QColor color;
+ QColor backgroundColor;
+ QPointF position;
+ QImage image;
+ qreal ascent;
+
+ int leftChildIndex;
+ int rightChildIndex;
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
+ const QRectF &rect,
+ const QImage &image,
+ qreal ascent,
+ SelectionState selectionState)
+ {
+ insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent));
+ }
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
+ const QGlyphRun &glyphRun,
+ SelectionState selectionState,
+ const QColor &textColor,
+ const QColor &backgroundColor,
+ const QPointF &position)
+ {
+ QRectF searchRect = glyphRun.boundingRect();
+ searchRect.translate(position);
+
+ if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height()))
+ return;
+
+ QQuickTextNode::Decorations decorations = QQuickTextNode::NoDecoration;
+ decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration);
+ decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration);
+ decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration);
+ decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
+
+ qreal ascent = glyphRun.rawFont().ascent();
+ insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
+ textColor, backgroundColor, position, ascent));
+ }
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
+ const BinaryTreeNode &binaryTreeNode)
+ {
+ int newIndex = binaryTree->size();
+ binaryTree->append(binaryTreeNode);
+ if (newIndex == 0)
+ return;
+
+ int searchIndex = 0;
+ forever {
+ BinaryTreeNode *node = binaryTree->data() + searchIndex;
+ if (binaryTreeNode.boundingRect.left() < node->boundingRect.left()) {
+ if (node->leftChildIndex < 0) {
+ node->leftChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->leftChildIndex;
+ }
+ } else {
+ if (node->rightChildIndex < 0) {
+ node->rightChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->rightChildIndex;
+ }
+ }
+ }
+ }
+
+ static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
+ QVarLengthArray<int> *sortedIndexes,
+ int currentIndex = 0)
+ {
+ Q_ASSERT(currentIndex < binaryTree.size());
+
+ const BinaryTreeNode *node = binaryTree.data() + currentIndex;
+ if (node->leftChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
+
+ sortedIndexes->append(currentIndex);
+
+ if (node->rightChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
+ }
+ };
+
+ // Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
+ // and rectangle nodes to represent the text, decorations and selection. Will try to minimize
+ // number of nodes, and join decorations in neighbouring items
+ class SelectionEngine
+ {
+ public:
+ SelectionEngine() : m_hasSelection(false) {}
+
+ QTextLine currentLine() const { return m_currentLine; }
+
+ void setCurrentLine(const QTextLine &currentLine)
+ {
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+ m_currentLine = currentLine;
+ }
+
+ void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle,
+ const QBrush &borderBrush);
+ void addFrameDecorations(QTextDocument *document, QTextFrame *frame);
+ void addImage(const QRectF &rect, const QImage &image, qreal ascent,
+ BinaryTreeNode::SelectionState selectionState,
+ QTextFrameFormat::Position layoutPosition);
+ void addTextObject(const QPointF &position, const QTextCharFormat &format,
+ BinaryTreeNode::SelectionState selectionState,
+ QTextDocument *textDocument, int pos,
+ QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
+ void addSelectedGlyphs(const QGlyphRun &glyphRun);
+ void addUnselectedGlyphs(const QGlyphRun &glyphRun);
+ void addGlyphsInRange(int rangeStart, int rangeEnd,
+ const QColor &color, const QColor &backgroundColor,
+ int selectionStart, int selectionEnd);
+ void addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
+ int start, int end,
+ int selectionStart, int selectionEnd);
+
+ void addToSceneGraph(QQuickTextNode *parent,
+ QQuickText::TextStyle style = QQuickText::Normal,
+ const QColor &styleColor = QColor());
+
+ void setSelectionColor(const QColor &selectionColor)
+ {
+ m_selectionColor = selectionColor;
+ }
+
+ void setSelectedTextColor(const QColor &selectedTextColor)
+ {
+ m_selectedTextColor = selectedTextColor;
+ }
+
+ void setTextColor(const QColor &textColor)
+ {
+ m_textColor = textColor;
+ }
+
+ void setPosition(const QPointF &position)
+ {
+ m_position = position;
+ }
+
+ private:
+ struct TextDecoration
+ {
+ TextDecoration() : selectionState(BinaryTreeNode::Unselected) {}
+ TextDecoration(const BinaryTreeNode::SelectionState &s,
+ const QRectF &r,
+ const QColor &c)
+ : selectionState(s)
+ , rect(r)
+ , color(c)
+ {
+ }
+
+ BinaryTreeNode::SelectionState selectionState;
+ QRectF rect;
+ QColor color;
+ };
+
+ void processCurrentLine();
+ void addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
+ qreal offset, qreal thickness);
+
+ QColor m_selectionColor;
+ QColor m_textColor;
+ QColor m_backgroundColor;
+ QColor m_selectedTextColor;
+ QPointF m_position;
+
+ QTextLine m_currentLine;
+ bool m_hasSelection;
+
+ QList<QPair<QRectF, QColor> > m_backgrounds;
+ QList<QRectF> m_selectionRects;
+ QVarLengthArray<BinaryTreeNode> m_currentLineTree;
+
+ QList<TextDecoration> m_lines;
+ QVector<BinaryTreeNode> m_processedNodes;
+
+ QList<QPair<QRectF, QImage> > m_images;
+ };
+
+ void SelectionEngine::addTextDecorations(const QVarLengthArray<TextDecoration> &textDecorations,
+ qreal offset, qreal thickness)
+ {
+ for (int i=0; i<textDecorations.size(); ++i) {
+ TextDecoration textDecoration = textDecorations.at(i);
+
+ {
+ QRectF &rect = textDecoration.rect;
+ rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
+ rect.setHeight(thickness);
+ }
+
+ m_lines.append(textDecoration);
+ }
+ }
+
+ void SelectionEngine::processCurrentLine()
+ {
+ // No glyphs, do nothing
+ if (m_currentLineTree.isEmpty())
+ return;
+
+ // 1. Go through current line and get correct decoration position for each node based on
+ // neighbouring decorations. Add decoration to global list
+ // 2. Create clip nodes for all selected text. Try to merge as many as possible within
+ // the line.
+ // 3. Add QRects to a list of selection rects.
+ // 4. Add all nodes to a global processed list
+ QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
+ BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);
+
+ Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());
+
+ BinaryTreeNode::SelectionState currentSelectionState = BinaryTreeNode::Unselected;
+ QRectF currentRect;
+
+ QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
+ qreal underlineOffset = 0.0;
+ qreal underlineThickness = 0.0;
+
+ qreal overlineOffset = 0.0;
+ qreal overlineThickness = 0.0;
+
+ qreal strikeOutOffset = 0.0;
+ qreal strikeOutThickness = 0.0;
+
+ QRectF decorationRect = currentRect;
+
+ QColor lastColor;
+ QColor lastBackgroundColor;
+
+ QVarLengthArray<TextDecoration> pendingUnderlines;
+ QVarLengthArray<TextDecoration> pendingOverlines;
+ QVarLengthArray<TextDecoration> pendingStrikeOuts;
+ if (!sortedIndexes.isEmpty()) {
+ QSGClipNode *currentClipNode = m_hasSelection ? new QSGClipNode : 0;
+ bool currentClipNodeUsed = false;
+ for (int i=0; i<=sortedIndexes.size(); ++i) {
+ BinaryTreeNode *node = 0;
+ if (i < sortedIndexes.size()) {
+ int sortedIndex = sortedIndexes.at(i);
+ Q_ASSERT(sortedIndex < m_currentLineTree.size());
+
+ node = m_currentLineTree.data() + sortedIndex;
+ }
+
+ if (i == 0)
+ currentSelectionState = node->selectionState;
+
+ // Update decorations
+ if (currentDecorations != QQuickTextNode::NoDecoration) {
+ decorationRect.setY(m_position.y() + m_currentLine.y());
+ decorationRect.setHeight(m_currentLine.height());
+
+ if (node != 0)
+ decorationRect.setRight(node->boundingRect.left());
+
+ TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
+ if (currentDecorations & QQuickTextNode::Underline)
+ pendingUnderlines.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::Overline)
+ pendingOverlines.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::StrikeOut)
+ pendingStrikeOuts.append(textDecoration);
+
+ if (currentDecorations & QQuickTextNode::Background)
+ m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
+ }
+
+ // If we've reached an unselected node from a selected node, we add the
+ // selection rect to the graph, and we add decoration every time the
+ // selection state changes, because that means the text color changes
+ if (node == 0 || node->selectionState != currentSelectionState) {
+ if (node != 0)
+ currentRect.setRight(node->boundingRect.left());
+ currentRect.setY(m_position.y() + m_currentLine.y());
+ currentRect.setHeight(m_currentLine.height());
+
+ // Draw selection all the way up to the left edge of the unselected item
+ if (currentSelectionState == BinaryTreeNode::Selected)
+ m_selectionRects.append(currentRect);
+
+ if (currentClipNode != 0) {
+ if (!currentClipNodeUsed) {
+ delete currentClipNode;
+ } else {
+ currentClipNode->setIsRectangular(true);
+ currentClipNode->setClipRect(currentRect);
+ }
+ }
+
+ if (node != 0 && m_hasSelection)
+ currentClipNode = new QSGClipNode;
+ else
+ currentClipNode = 0;
+ currentClipNodeUsed = false;
+
+ if (node != 0) {
+ currentSelectionState = node->selectionState;
+ currentRect = node->boundingRect;
+
+ // Make sure currentRect is valid, otherwise the unite won't work
+ if (currentRect.isNull())
+ currentRect.setSize(QSizeF(1, 1));
+ }
+ } else {
+ if (currentRect.isNull())
+ currentRect = node->boundingRect;
+ else
+ currentRect = currentRect.united(node->boundingRect);
+ }
+
+ if (node != 0) {
+ node->clipNode = currentClipNode;
+ currentClipNodeUsed = true;
+
+ decorationRect = node->boundingRect;
+
+ // If previous item(s) had underline and current does not, then we add the
+ // pending lines to the lists and likewise for overlines and strikeouts
+ if (!pendingUnderlines.isEmpty()
+ && !(node->decorations & QQuickTextNode::Underline)) {
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ pendingUnderlines.clear();
+
+ underlineOffset = 0.0;
+ underlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingOverlines.isEmpty()) {
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ pendingOverlines.clear();
+
+ overlineOffset = 0.0;
+ overlineThickness = 0.0;
+ }
+
+ // ### Add pending when overlineOffset/thickness changes to minimize number of
+ // nodes
+ if (!pendingStrikeOuts.isEmpty()) {
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+
+ pendingStrikeOuts.clear();
+
+ strikeOutOffset = 0.0;
+ strikeOutThickness = 0.0;
+ }
+
+ // Merge current values with previous. Prefer greatest thickness
+ QRawFont rawFont = node->glyphRun.rawFont();
+ if (node->decorations & QQuickTextNode::Underline) {
+ if (rawFont.lineThickness() > underlineThickness) {
+ underlineThickness = rawFont.lineThickness();
+ underlineOffset = rawFont.underlinePosition();
+ }
+ }
+
+ if (node->decorations & QQuickTextNode::Overline) {
+ overlineOffset = -rawFont.ascent();
+ overlineThickness = rawFont.lineThickness();
+ }
+
+ if (node->decorations & QQuickTextNode::StrikeOut) {
+ strikeOutThickness = rawFont.lineThickness();
+ strikeOutOffset = rawFont.ascent() / -3.0;
+ }
+
+ currentDecorations = node->decorations;
+ lastColor = node->color;
+ lastBackgroundColor = node->backgroundColor;
+ m_processedNodes.append(*node);
+ }
+ }
+
+ if (!pendingUnderlines.isEmpty())
+ addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);
+
+ if (!pendingOverlines.isEmpty())
+ addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);
+
+ if (!pendingStrikeOuts.isEmpty())
+ addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
+ }
+
+ m_currentLineTree.clear();
+ m_currentLine = QTextLine();
+ m_hasSelection = false;
+ }
+
+ void SelectionEngine::addImage(const QRectF &rect, const QImage &image, qreal ascent,
+ BinaryTreeNode::SelectionState selectionState,
+ QTextFrameFormat::Position layoutPosition)
+ {
+ QRectF searchRect = rect;
+ if (layoutPosition == QTextFrameFormat::InFlow) {
+ if (m_currentLineTree.isEmpty()) {
+ searchRect.moveTopLeft(m_position);
+ } else {
+ const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1;
+ if (lastNode->glyphRun.isRightToLeft()) {
+ QPointF lastPos = lastNode->boundingRect.topLeft();
+ searchRect.moveTopRight(lastPos - QPointF(0, ascent));
+ } else {
+ QPointF lastPos = lastNode->boundingRect.topRight();
+ searchRect.moveTopLeft(lastPos - QPointF(0, ascent));
+ }
+ }
+ }
+
+ BinaryTreeNode::insert(&m_currentLineTree, searchRect, image, ascent, selectionState);
+ }
+
+ void SelectionEngine::addTextObject(const QPointF &position, const QTextCharFormat &format,
+ BinaryTreeNode::SelectionState selectionState,
+ QTextDocument *textDocument, int pos,
+ QTextFrameFormat::Position layoutPosition)
+ {
+ QTextObjectInterface *handler = textDocument->documentLayout()->handlerForObject(format.objectType());
+ if (handler != 0) {
+ QImage image;
+ QSizeF size = handler->intrinsicSize(textDocument, pos, format);
+
+ if (format.objectType() == QTextFormat::ImageObject) {
+ QTextImageFormat imageFormat = format.toImageFormat();
+ QTextImageHandler *imageHandler = static_cast<QTextImageHandler *>(handler);
+ image = imageHandler->image(textDocument, imageFormat);
+ }
+
+ if (image.isNull()) {
+ image = QImage(size.toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::transparent);
+ {
+ QPainter painter(&image);
+ handler->drawObject(&painter, image.rect(), textDocument, pos, format);
+ }
+ }
+
+ qreal ascent;
+ QFontMetrics m(format.font());
+ switch (format.verticalAlignment())
+ {
+ case QTextCharFormat::AlignMiddle:
+ ascent = size.height() / 2 - 1;
+ break;
+ case QTextCharFormat::AlignBaseline:
+ ascent = size.height() - m.descent() - 1;
+ break;
+ default:
+ ascent = size.height() - 1;
+ }
+
+ addImage(QRectF(position, size), image, ascent, selectionState, layoutPosition);
+ }
+ }
+
+ void SelectionEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
+ {
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Unselected,
+ m_textColor, m_backgroundColor, m_position);
+ }
+
+ void SelectionEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
+ {
+ int currentSize = m_currentLineTree.size();
+ BinaryTreeNode::insert(&m_currentLineTree, glyphRun, BinaryTreeNode::Selected,
+ m_textColor, m_backgroundColor, m_position);
+ m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
+ }
+
+ void SelectionEngine::addGlyphsForRanges(const QVarLengthArray<QTextLayout::FormatRange> &ranges,
+ int start, int end,
+ int selectionStart, int selectionEnd)
+ {
+ int currentPosition = start;
+ int remainingLength = end - start;
+ for (int j=0; j<ranges.size(); ++j) {
+ const QTextLayout::FormatRange &range = ranges.at(j);
+ if (range.start + range.length >= currentPosition
+ && range.start < currentPosition + remainingLength) {
+
+ if (range.start > currentPosition) {
+ addGlyphsInRange(currentPosition, range.start - currentPosition,
+ QColor(), QColor(), selectionStart, selectionEnd);
+ }
+
+ int rangeEnd = qMin(range.start + range.length, currentPosition + remainingLength);
+ QColor rangeColor = range.format.hasProperty(QTextFormat::ForegroundBrush)
+ ? range.format.foreground().color()
+ : QColor();
+ QColor rangeBackgroundColor = range.format.hasProperty(QTextFormat::BackgroundBrush)
+ ? range.format.background().color()
+ : QColor();
+
+ addGlyphsInRange(range.start, rangeEnd - range.start,
+ rangeColor, rangeBackgroundColor,
+ selectionStart, selectionEnd);
+
+ currentPosition = range.start + range.length;
+ remainingLength = end - currentPosition;
+
+ } else if (range.start > currentPosition + remainingLength || remainingLength <= 0) {
+ break;
+ }
+ }
+
+ if (remainingLength > 0) {
+ addGlyphsInRange(currentPosition, remainingLength, QColor(), QColor(),
+ selectionStart, selectionEnd);
+ }
+
+ }
+
+ void SelectionEngine::addGlyphsInRange(int rangeStart, int rangeLength,
+ const QColor &color, const QColor &backgroundColor,
+ int selectionStart, int selectionEnd)
+ {
+ QColor oldColor;
+ if (color.isValid()) {
+ oldColor = m_textColor;
+ m_textColor = color;
+ }
+
+ QColor oldBackgroundColor = m_backgroundColor;
+ if (backgroundColor.isValid()) {
+ oldBackgroundColor = m_backgroundColor;
+ m_backgroundColor = backgroundColor;
+ }
+
+ bool hasSelection = selectionEnd >= 0
+ && selectionStart <= selectionEnd;
+
+ QTextLine &line = m_currentLine;
+ int rangeEnd = rangeStart + rangeLength;
+ if (!hasSelection || (selectionStart > rangeEnd || selectionEnd < rangeStart)) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ } else {
+ if (rangeStart < selectionStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart,
+ qMin(selectionStart - rangeStart,
+ rangeLength));
+
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ }
+
+ if (rangeEnd > selectionStart) {
+ int start = qMax(selectionStart, rangeStart);
+ int length = qMin(selectionEnd - start + 1, rangeEnd - start);
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(start, length);
+
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addSelectedGlyphs(glyphRun);
+ }
+ }
+
+ if (selectionEnd >= rangeStart && selectionEnd < rangeEnd) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, rangeEnd - selectionEnd - 1);
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ addUnselectedGlyphs(glyphRun);
+ }
+ }
+ }
+
+ if (backgroundColor.isValid())
+ m_backgroundColor = oldBackgroundColor;
+
+ if (oldColor.isValid())
+ m_textColor = oldColor;
+ }
+
+ void SelectionEngine::addBorder(const QRectF &rect, qreal border,
+ QTextFrameFormat::BorderStyle borderStyle,
+ const QBrush &borderBrush)
+ {
+ QColor color = borderBrush.color();
+
+ // Currently we don't support other styles than solid
+ Q_UNUSED(borderStyle);
+
+ m_backgrounds.append(qMakePair(QRectF(rect.left(), rect.top(), border, rect.height() + border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.top(), rect.width(), border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.right(), rect.top() + border, border, rect.height() - border), color));
+ m_backgrounds.append(qMakePair(QRectF(rect.left() + border, rect.bottom(), rect.width(), border), color));
+ }
+
+ void SelectionEngine::addFrameDecorations(QTextDocument *document, QTextFrame *frame)
+ {
+ QTextDocumentLayout *documentLayout = qobject_cast<QTextDocumentLayout *>(document->documentLayout());
+ QTextFrameFormat frameFormat = frame->format().toFrameFormat();
+
+ QTextTable *table = qobject_cast<QTextTable *>(frame);
+ QRectF boundingRect = table == 0
+ ? documentLayout->frameBoundingRect(frame)
+ : documentLayout->tableBoundingRect(table);
+
+ QBrush bg = frame->frameFormat().background();
+ if (bg.style() != Qt::NoBrush)
+ m_backgrounds.append(qMakePair(boundingRect, bg.color()));
+
+ if (!frameFormat.hasProperty(QTextFormat::FrameBorder))
+ return;
+
+ qreal borderWidth = frameFormat.border();
+ if (qFuzzyIsNull(borderWidth))
+ return;
+
+ QBrush borderBrush = frameFormat.borderBrush();
+ QTextFrameFormat::BorderStyle borderStyle = frameFormat.borderStyle();
+ if (borderStyle == QTextFrameFormat::BorderStyle_None)
+ return;
+
+ addBorder(boundingRect.adjusted(frameFormat.leftMargin(), frameFormat.topMargin(),
+ -frameFormat.rightMargin(), -frameFormat.bottomMargin()),
+ borderWidth, borderStyle, borderBrush);
+ if (table != 0) {
+ int rows = table->rows();
+ int columns = table->columns();
+
+ for (int row=0; row<rows; ++row) {
+ for (int column=0; column<columns; ++column) {
+ QTextTableCell cell = table->cellAt(row, column);
+
+ QRectF cellRect = documentLayout->tableCellBoundingRect(table, cell);
+ addBorder(cellRect.adjusted(-borderWidth, -borderWidth, 0, 0), borderWidth,
+ borderStyle, borderBrush);
+ }
+ }
+ }
+ }
+
+ void SelectionEngine::addToSceneGraph(QQuickTextNode *parentNode,
+ QQuickText::TextStyle style,
+ const QColor &styleColor)
+ {
+ if (m_currentLine.isValid())
+ processCurrentLine();
+
+
+ for (int i=0; i<m_backgrounds.size(); ++i) {
+ const QRectF &rect = m_backgrounds.at(i).first;
+ const QColor &color = m_backgrounds.at(i).second;
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(rect, color));
+ }
+
+ // First, prepend all selection rectangles to the tree
+ for (int i=0; i<m_selectionRects.size(); ++i) {
+ const QRectF &rect = m_selectionRects.at(i);
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
+ }
+
+ // Finally, add decorations for each node to the tree.
+ for (int i=0; i<m_lines.size(); ++i) {
+ const TextDecoration &textDecoration = m_lines.at(i);
+
+ QColor color = textDecoration.selectionState == BinaryTreeNode::Selected
+ ? m_selectedTextColor
+ : textDecoration.color;
+
+ parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
+ }
+
+ // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
+ // font, selection state and clip node.
+ typedef QPair<QFontEngine *, QPair<QSGClipNode *, QPair<QRgb, int> > > KeyType;
+ QHash<KeyType, BinaryTreeNode *> map;
+ for (int i=0; i<m_processedNodes.size(); ++i) {
+ BinaryTreeNode *node = m_processedNodes.data() + i;
+
+ if (node->image.isNull()) {
+ QGlyphRun glyphRun = node->glyphRun;
+ QRawFont rawFont = glyphRun.rawFont();
+ QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
+
+ QFontEngine *fontEngine = rawFontD->fontEngine;
+
+ KeyType key(qMakePair(fontEngine,
+ qMakePair(node->clipNode,
+ qMakePair(node->color.rgba(), int(node->selectionState)))));
+
+ BinaryTreeNode *otherNode = map.value(key, 0);
+ if (otherNode != 0) {
+ QGlyphRun &otherGlyphRun = otherNode->glyphRun;
+
+ QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
+ QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();
+
+ otherGlyphIndexes += glyphRun.glyphIndexes();
+
+ QVector<QPointF> glyphPositions = glyphRun.positions();
+ for (int j=0; j<glyphPositions.size(); ++j) {
+ otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
+ }
+
+ otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
+ otherGlyphRun.setPositions(otherGlyphPositions);
+
+ } else {
+ map.insert(key, node);
+ }
+ } else {
+ parentNode->addImage(node->boundingRect, node->image);
+ if (node->selectionState == BinaryTreeNode::Selected) {
+ QColor color = m_selectionColor;
+ color.setAlpha(128);
+ parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color));
+ }
+ }
+ }
+
+ // ...and add clip nodes and glyphs to tree.
+ QHash<KeyType, BinaryTreeNode *>::const_iterator it = map.constBegin();
+ while (it != map.constEnd()) {
+
+ BinaryTreeNode *node = it.value();
+
+ QSGClipNode *clipNode = node->clipNode;
+ if (clipNode != 0 && clipNode->parent() == 0 )
+ parentNode->appendChildNode(clipNode);
+
+ QColor color = node->selectionState == BinaryTreeNode::Selected
+ ? m_selectedTextColor
+ : node->color;
+
+ parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
+
+ ++it;
+ }
+ }
+}
+
+void QQuickTextNode::mergeFormats(QTextLayout *textLayout,
+ QVarLengthArray<QTextLayout::FormatRange> *mergedFormats)
+{
+ Q_ASSERT(mergedFormats != 0);
+ if (textLayout == 0)
+ return;
+
+ QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+ for (int i=0; i<additionalFormats.size(); ++i) {
+ QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
+ if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
+ || additionalFormat.format.hasProperty(QTextFormat::BackgroundBrush)) {
+ // Merge overlapping formats
+ if (!mergedFormats->isEmpty()) {
+ QTextLayout::FormatRange *lastFormat = mergedFormats->data() + mergedFormats->size() - 1;
+
+ if (additionalFormat.start < lastFormat->start + lastFormat->length) {
+ QTextLayout::FormatRange *mergedRange = 0;
+
+ int length = additionalFormat.length;
+ if (additionalFormat.start > lastFormat->start) {
+ lastFormat->length = additionalFormat.start - lastFormat->start;
+ length -= lastFormat->length;
+
+ mergedFormats->append(QTextLayout::FormatRange());
+ mergedRange = mergedFormats->data() + mergedFormats->size() - 1;
+ lastFormat = mergedFormats->data() + mergedFormats->size() - 2;
+ } else {
+ mergedRange = lastFormat;
+ }
+
+ mergedRange->format = lastFormat->format;
+ mergedRange->format.merge(additionalFormat.format);
+ mergedRange->start = additionalFormat.start;
+
+ int end = qMin(additionalFormat.start + additionalFormat.length,
+ lastFormat->start + lastFormat->length);
+
+ mergedRange->length = end - mergedRange->start;
+ length -= mergedRange->length;
+
+ additionalFormat.start = end;
+ additionalFormat.length = length;
+ }
+ }
+
+ if (additionalFormat.length > 0)
+ mergedFormats->append(additionalFormat);
+ }
+ }
+
+}
+
+namespace {
+
+ class ProtectedLayoutAccessor: public QAbstractTextDocumentLayout
+ {
+ public:
+ inline QTextCharFormat formatAccessor(int pos)
+ {
+ return format(pos);
+ }
+ };
+
+}
+
+void QQuickTextNode::addImage(const QRectF &rect, const QImage &image)
+{
+ QSGImageNode *node = m_context->createImageNode();
+ QSGTexture *texture = m_context->createTexture(image);
+ m_textures.append(texture);
+ node->setTargetRect(rect);
+ node->setTexture(texture);
+ appendChildNode(node);
+ node->update();
+}
+
+void QQuickTextNode::addTextDocument(const QPointF &, QTextDocument *textDocument,
+ const QColor &textColor,
+ QQuickText::TextStyle style, const QColor &styleColor,
+ const QColor &selectionColor, const QColor &selectedTextColor,
+ int selectionStart, int selectionEnd)
+{
+ SelectionEngine engine;
+ engine.setTextColor(textColor);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+
+ QList<QTextFrame *> frames;
+ frames.append(textDocument->rootFrame());
+ while (!frames.isEmpty()) {
+ QTextFrame *textFrame = frames.takeFirst();
+ frames.append(textFrame->childFrames());
+
+ engine.addFrameDecorations(textDocument, textFrame);
+
+ if (textFrame->firstPosition() > textFrame->lastPosition()
+ && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
+ const int pos = textFrame->firstPosition() - 1;
+ ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(textDocument->documentLayout());
+ QTextCharFormat format = a->formatAccessor(pos);
+ QRectF rect = a->frameBoundingRect(textFrame);
+
+ QTextBlock block = textFrame->firstCursorPosition().block();
+ engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ engine.addTextObject(rect.topLeft(), format, BinaryTreeNode::Unselected, textDocument,
+ pos, textFrame->frameFormat().position());
+ } else {
+ QTextFrame::iterator it = textFrame->begin();
+
+ while (!it.atEnd()) {
+ Q_ASSERT(!engine.currentLine().isValid());
+
+ QTextBlock block = it.currentBlock();
+ int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
+ int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
+
+ QVarLengthArray<QTextLayout::FormatRange> colorChanges;
+ mergeFormats(block.layout(), &colorChanges);
+
+ QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft();
+ if (QTextList *textList = block.textList()) {
+ QPointF pos = blockPosition;
+ QTextLayout *layout = block.layout();
+ if (layout->lineCount() > 0) {
+ QTextLine firstLine = layout->lineAt(0);
+ Q_ASSERT(firstLine.isValid());
+
+ engine.setCurrentLine(firstLine);
+
+ QRectF textRect = firstLine.naturalTextRect();
+ pos += textRect.topLeft();
+ if (block.textDirection() == Qt::RightToLeft)
+ pos.rx() += textRect.width();
+
+ const QTextCharFormat charFormat = block.charFormat();
+ QFont font(charFormat.font());
+ QFontMetricsF fontMetrics(font);
+ QTextListFormat listFormat = textList->format();
+
+ QString listItemBullet;
+ switch (listFormat.style()) {
+ case QTextListFormat::ListCircle:
+ listItemBullet = QChar(0x25E6); // White bullet
+ break;
+ case QTextListFormat::ListSquare:
+ listItemBullet = QChar(0x25AA); // Black small square
+ break;
+ case QTextListFormat::ListDecimal:
+ case QTextListFormat::ListLowerAlpha:
+ case QTextListFormat::ListUpperAlpha:
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman:
+ listItemBullet = textList->itemText(block);
+ break;
+ default:
+ listItemBullet = QChar(0x2022); // Black bullet
+ break;
+ };
+
+ QSizeF size(fontMetrics.width(listItemBullet), fontMetrics.height());
+ qreal xoff = fontMetrics.width(QLatin1Char(' '));
+ if (block.textDirection() == Qt::LeftToRight)
+ xoff = -xoff - size.width();
+ engine.setPosition(pos + QPointF(xoff, 0));
+
+ QTextLayout layout;
+ layout.setFont(font);
+ layout.setText(listItemBullet); // Bullet
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setPosition(QPointF(0, 0));
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ for (int i=0; i<glyphRuns.size(); ++i)
+ engine.addUnselectedGlyphs(glyphRuns.at(i));
+ }
+ }
+
+ int textPos = block.position();
+ QTextBlock::iterator blockIterator = block.begin();
+ while (!blockIterator.atEnd()) {
+ QTextFragment fragment = blockIterator.fragment();
+ QString text = fragment.text();
+ if (text.isEmpty())
+ continue;
+
+ QTextCharFormat charFormat = fragment.charFormat();
+ engine.setPosition(blockPosition);
+ if (text.contains(QChar::ObjectReplacementCharacter)) {
+ QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
+ if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
+ BinaryTreeNode::SelectionState selectionState =
+ (selectionStart < textPos + text.length()
+ && selectionEnd >= textPos)
+ ? BinaryTreeNode::Selected
+ : BinaryTreeNode::Unselected;
+
+ engine.addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos);
+ }
+ textPos += text.length();
+ } else {
+ if (charFormat.foreground().style() != Qt::NoBrush)
+ engine.setTextColor(charFormat.foreground().color());
+ else
+ engine.setTextColor(textColor);
+
+ int fragmentEnd = textPos + fragment.length();
+ if (preeditPosition >= 0
+ && preeditPosition >= textPos
+ && preeditPosition < fragmentEnd) {
+ fragmentEnd += preeditLength;
+ }
+
+ while (textPos < fragmentEnd) {
+ int blockRelativePosition = textPos - block.position();
+ QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
+ if (!engine.currentLine().isValid()
+ || line.lineNumber() != engine.currentLine().lineNumber()) {
+ engine.setCurrentLine(line);
+ }
+
+ Q_ASSERT(line.textLength() > 0);
+ int lineEnd = line.textStart() + block.position() + line.textLength();
+
+ int len = qMin(lineEnd - textPos, fragmentEnd - textPos);
+ Q_ASSERT(len > 0);
+
+ int currentStepEnd = textPos + len;
+
+ engine.addGlyphsForRanges(colorChanges,
+ textPos - block.position(),
+ currentStepEnd - block.position(),
+ selectionStart - block.position(),
+ selectionEnd - block.position());
+
+ textPos = currentStepEnd;
+ }
+ }
+
+ ++blockIterator;
+ }
+
+ engine.setCurrentLine(QTextLine()); // Reset current line because the text layout changed
+ ++it;
+ }
+ }
+ }
+
+ engine.addToSceneGraph(this, style, styleColor);
+}
+
+void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
+ QQuickText::TextStyle style, const QColor &styleColor,
+ const QColor &selectionColor, const QColor &selectedTextColor,
+ int selectionStart, int selectionEnd)
+{
+ SelectionEngine engine;
+ engine.setTextColor(color);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setPosition(position);
+
+ int preeditLength = textLayout->preeditAreaText().length();
+ int preeditPosition = textLayout->preeditAreaPosition();
+
+ QVarLengthArray<QTextLayout::FormatRange> colorChanges;
+ mergeFormats(textLayout, &colorChanges);
+
+ for (int i=0; i<textLayout->lineCount(); ++i) {
+ QTextLine line = textLayout->lineAt(i);
+
+ int start = line.textStart();
+ int length = line.textLength();
+ int end = start + length;
+
+ if (preeditPosition >= 0
+ && preeditPosition >= start
+ && preeditPosition < end) {
+ end += preeditLength;
+ }
+
+ engine.setCurrentLine(line);
+ engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
+ }
+
+ engine.addToSceneGraph(this, style, styleColor);
+}
+
+void QQuickTextNode::deleteContent()
+{
+ while (firstChild() != 0)
+ delete firstChild();
+ m_cursorNode = 0;
+}
+
+#if 0
+void QQuickTextNode::updateNodes()
+{
+ return;
+ deleteContent();
+ if (m_text.isEmpty())
+ return;
+
+ if (m_usePixmapCache) {
+ // ### gunnar: port properly
+// QPixmap pixmap = generatedPixmap();
+// if (pixmap.isNull())
+// return;
+
+// QSGImageNode *pixmapNode = m_context->createImageNode();
+// pixmapNode->setRect(pixmap.rect());
+// pixmapNode->setSourceRect(pixmap.rect());
+// pixmapNode->setOpacity(m_opacity);
+// pixmapNode->setClampToEdge(true);
+// pixmapNode->setLinearFiltering(m_linearFiltering);
+
+// appendChildNode(pixmapNode);
+ } else {
+ if (m_text.isEmpty())
+ return;
+
+ // Implement styling by drawing text several times at slight shifts. shiftForStyle
+ // contains the sequence of shifted positions at which to draw the text. All except
+ // the last will be drawn with styleColor.
+ QList<QPointF> shiftForStyle;
+ switch (m_textStyle) {
+ case OutlineTextStyle:
+ // ### Should be made faster by implementing outline material
+ shiftForStyle << QPointF(-1, 0);
+ shiftForStyle << QPointF(0, -1);
+ shiftForStyle << QPointF(1, 0);
+ shiftForStyle << QPointF(0, 1);
+ break;
+ case SunkenTextStyle:
+ shiftForStyle << QPointF(0, -1);
+ break;
+ case RaisedTextStyle:
+ shiftForStyle << QPointF(0, 1);
+ break;
+ default:
+ break;
+ }
+
+ shiftForStyle << QPointF(0, 0); // Regular position
+ while (!shiftForStyle.isEmpty()) {
+ QPointF shift = shiftForStyle.takeFirst();
+
+ // Use styleColor for all but last shift
+ if (m_richText) {
+ QColor overrideColor = shiftForStyle.isEmpty() ? QColor() : m_styleColor;
+
+ QTextFrame *textFrame = m_textDocument->rootFrame();
+ QPointF p = m_textDocument->documentLayout()->frameBoundingRect(textFrame).topLeft();
+
+ QTextFrame::iterator it = textFrame->begin();
+ while (!it.atEnd()) {
+ addTextBlock(shift + p, it.currentBlock(), overrideColor);
+ ++it;
+ }
+ } else {
+ addTextLayout(shift, m_textLayout, shiftForStyle.isEmpty()
+ ? m_color
+ : m_styleColor);
+ }
+ }
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
new file mode 100644
index 0000000000..a519322160
--- /dev/null
+++ b/src/quick/items/qquicktextnode_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKTEXTNODE_P_H
+#define QQUICKTEXTNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+#include "qquicktext_p.h"
+#include <qglyphrun.h>
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qtextlayout.h>
+#include <QtCore/qvarlengtharray.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGGlyphNode;
+class QTextBlock;
+class QColor;
+class QTextDocument;
+class QSGContext;
+class QRawFont;
+class QSGSimpleRectNode;
+class QSGClipNode;
+class QSGTexture;
+
+class QQuickTextNode : public QSGTransformNode
+{
+public:
+ enum Decoration {
+ NoDecoration = 0x0,
+ Underline = 0x1,
+ Overline = 0x2,
+ StrikeOut = 0x4,
+ Background = 0x8
+ };
+ Q_DECLARE_FLAGS(Decorations, Decoration)
+
+ QQuickTextNode(QSGContext *);
+ ~QQuickTextNode();
+
+ static bool isComplexRichText(QTextDocument *);
+
+ void deleteContent();
+ void addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color = QColor(),
+ QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
+ const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
+ int selectionStart = -1, int selectionEnd = -1);
+ void addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &color = QColor(),
+ QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
+ const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
+ int selectionStart = -1, int selectionEnd = -1);
+
+ void setCursor(const QRectF &rect, const QColor &color);
+ QSGSimpleRectNode *cursorNode() const { return m_cursorNode; }
+
+ QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
+ QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(),
+ QSGNode *parentNode = 0);
+ void addImage(const QRectF &rect, const QImage &image);
+
+private:
+ void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
+
+ QSGContext *m_context;
+ QSGSimpleRectNode *m_cursorNode;
+ QList<QSGTexture *> m_textures;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKTEXTNODE_P_H
diff --git a/src/declarative/items/qquicktranslate.cpp b/src/quick/items/qquicktranslate.cpp
index 7347cb0624..7347cb0624 100644
--- a/src/declarative/items/qquicktranslate.cpp
+++ b/src/quick/items/qquicktranslate.cpp
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
new file mode 100644
index 0000000000..ccfbb4c4e3
--- /dev/null
+++ b/src/quick/items/qquicktranslate_p.h
@@ -0,0 +1,160 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKTRANSLATE_P_H
+#define QQUICKTRANSLATE_P_H
+
+#include "qquickitem.h"
+
+#include <QtGui/qmatrix4x4.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTranslatePrivate;
+class Q_AUTOTEST_EXPORT QQuickTranslate : public QQuickTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+
+public:
+ QQuickTranslate(QObject *parent = 0);
+ ~QQuickTranslate();
+
+ qreal x() const;
+ void setX(qreal);
+
+ qreal y() const;
+ void setY(qreal);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void xChanged();
+ void yChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickTranslate)
+ Q_DISABLE_COPY(QQuickTranslate)
+};
+
+class QQuickScalePrivate;
+class Q_AUTOTEST_EXPORT QQuickScale : public QQuickTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged)
+ Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged)
+ Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged)
+public:
+ QQuickScale(QObject *parent = 0);
+ ~QQuickScale();
+
+ QVector3D origin() const;
+ void setOrigin(const QVector3D &point);
+
+ qreal xScale() const;
+ void setXScale(qreal);
+
+ qreal yScale() const;
+ void setYScale(qreal);
+
+ qreal zScale() const;
+ void setZScale(qreal);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void xScaleChanged();
+ void yScaleChanged();
+ void zScaleChanged();
+ void scaleChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickScale)
+};
+
+class QQuickRotationPrivate;
+class Q_AUTOTEST_EXPORT QQuickRotation : public QQuickTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+ Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
+public:
+ QQuickRotation(QObject *parent = 0);
+ ~QQuickRotation();
+
+ QVector3D origin() const;
+ void setOrigin(const QVector3D &point);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ QVector3D axis() const;
+ void setAxis(const QVector3D &axis);
+ void setAxis(Qt::Axis axis);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void angleChanged();
+ void axisChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickRotation)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickTranslate)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
new file mode 100644
index 0000000000..8c7db60195
--- /dev/null
+++ b/src/quick/items/qquickview.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickview.h"
+#include "qquickview_p.h"
+
+#include "qquickcanvas_p.h"
+#include "qquickitem_p.h"
+#include "qquickitemchangelistener_p.h"
+
+#include <private/qdeclarativedebugtrace_p.h>
+#include <private/qdeclarativeinspectorservice_p.h>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <private/qdeclarativeengine_p.h>
+#include <QtCore/qbasictimer.h>
+
+
+QT_BEGIN_NAMESPACE
+
+void QQuickViewPrivate::init()
+{
+ Q_Q(QQuickView);
+
+ engine.setIncubationController(q->incubationController());
+
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ QDeclarativeInspectorService::instance()->addView(q);
+}
+
+QQuickViewPrivate::QQuickViewPrivate()
+ : root(0), component(0), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0)
+{
+}
+
+QQuickViewPrivate::~QQuickViewPrivate()
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ QDeclarativeInspectorService::instance()->removeView(q_func());
+
+ delete root;
+}
+
+void QQuickViewPrivate::execute()
+{
+ Q_Q(QQuickView);
+ if (root) {
+ delete root;
+ root = 0;
+ }
+ if (component) {
+ delete component;
+ component = 0;
+ }
+ if (!source.isEmpty()) {
+ component = new QDeclarativeComponent(&engine, source, q);
+ if (!component->isLoading()) {
+ q->continueExecute();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
+ q, SLOT(continueExecute()));
+ }
+ }
+}
+
+void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QQuickView);
+ if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) {
+ // wait for both width and height to be changed
+ resizetimer.start(0,q);
+ }
+ QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+/*!
+ \class QQuickView
+ \since QtQuick 2.0
+ \brief The QQuickView class provides a window for displaying a Qt Quick user interface.
+
+ \inmodule QtQuick
+
+ This is a convenience subclass of QQuickCanvas which
+ will automatically load and display a QML scene when given the URL of the main source file. Alternatively,
+ you can instantiate your own objects using QDeclarativeComponent and place them in a manually setup QQuickCanvas.
+
+ Typical usage:
+
+ \code
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
+ view->show();
+ \endcode
+
+ To receive errors related to loading and executing QML with QQuickView,
+ you can connect to the statusChanged() signal and monitor for QQuickView::Error.
+ The errors are available via QQuickView::errors().
+
+ \sa {Using QML Bindings in C++ Applications}
+*/
+
+
+/*! \fn void QQuickView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+*/
+
+/*! \fn void QQuickView::statusChanged(QQuickView::Status status)
+ This signal is emitted when the component's current \a status changes.
+*/
+
+/*! \fn void QQuickView::initialSizeChanged(QSize size)
+ \internal
+*/
+
+/*!
+ \fn QQuickView::QQuickView(QWindow *parent)
+
+ Constructs a QQuickView with the given \a parent.
+*/
+QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
+: QQuickCanvas(*(new QQuickViewPrivate), parent)
+{
+ setWindowFlags(f);
+ d_func()->init();
+}
+
+/*!
+ \fn QQuickView::QQuickView(const QUrl &source, QWidget *parent)
+
+ Constructs a QQuickView with the given QML \a source and \a parent.
+*/
+QQuickView::QQuickView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
+: QQuickCanvas(*(new QQuickViewPrivate), parent)
+{
+ setWindowFlags(f);
+ d_func()->init();
+ setSource(source);
+}
+
+QQuickView::~QQuickView()
+{
+}
+
+/*! \property QQuickView::source
+ \brief The URL of the source of the QML component.
+
+ Changing this property causes the QML component to be reloaded.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ */
+
+/*!
+ Sets the source to the \a url, loads the QML component and instantiates it.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Calling this methods multiple times with the same url will result
+ in the QML being reloaded.
+ */
+void QQuickView::setSource(const QUrl& url)
+{
+ Q_D(QQuickView);
+ d->source = url;
+ d->execute();
+}
+
+/*!
+ Returns the source URL, if set.
+
+ \sa setSource()
+ */
+QUrl QQuickView::source() const
+{
+ Q_D(const QQuickView);
+ return d->source;
+}
+
+/*!
+ Returns a pointer to the QDeclarativeEngine used for instantiating
+ QML Components.
+ */
+QDeclarativeEngine* QQuickView::engine() const
+{
+ Q_D(const QQuickView);
+ return const_cast<QDeclarativeEngine *>(&d->engine);
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QDeclarativeContext. QDeclarativeContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QDeclarativeEngine.
+ */
+QDeclarativeContext* QQuickView::rootContext() const
+{
+ Q_D(const QQuickView);
+ return d->engine.rootContext();
+}
+
+/*!
+ \enum QQuickView::Status
+ Specifies the loading status of the QQuickView.
+
+ \value Null This QQuickView has no source set.
+ \value Ready This QQuickView has loaded and created the QML component.
+ \value Loading This QQuickView is loading network data.
+ \value Error One or more errors has occurred. Call errors() to retrieve a list
+ of errors.
+*/
+
+/*! \enum QQuickView::ResizeMode
+
+ This enum specifies how to resize the view.
+
+ \value SizeViewToRootObject The view resizes with the root item in the QML.
+ \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
+*/
+
+/*!
+ \property QQuickView::status
+ The component's current \l{QQuickView::Status} {status}.
+*/
+
+QQuickView::Status QQuickView::status() const
+{
+ Q_D(const QQuickView);
+ if (!d->component)
+ return QQuickView::Null;
+
+ return QQuickView::Status(d->component->status());
+}
+
+/*!
+ Return the list of errors that occurred during the last compile or create
+ operation. When the status is not Error, an empty list is returned.
+*/
+QList<QDeclarativeError> QQuickView::errors() const
+{
+ Q_D(const QQuickView);
+ if (d->component)
+ return d->component->errors();
+ return QList<QDeclarativeError>();
+}
+
+/*!
+ \property QQuickView::resizeMode
+ \brief whether the view should resize the canvas contents
+
+ If this property is set to SizeViewToRootObject (the default), the view
+ resizes with the root item in the QML.
+
+ If this property is set to SizeRootObjectToView, the view will
+ automatically resize the root item.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item. Note though that
+ since QML may load dynamically, that size may change.
+*/
+
+void QQuickView::setResizeMode(ResizeMode mode)
+{
+ Q_D(QQuickView);
+ if (d->resizeMode == mode)
+ return;
+
+ if (d->root) {
+ if (d->resizeMode == SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
+ p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ }
+ }
+
+ d->resizeMode = mode;
+ if (d->root) {
+ d->initResize();
+ }
+}
+
+void QQuickViewPrivate::initResize()
+{
+ if (root) {
+ if (resizeMode == QQuickView::SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(root);
+ p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ }
+ updateSize();
+}
+
+void QQuickViewPrivate::updateSize()
+{
+ Q_Q(QQuickView);
+ if (!root)
+ return;
+
+ if (resizeMode == QQuickView::SizeViewToRootObject) {
+ QSize newSize = QSize(root->width(), root->height());
+ if (newSize.isValid() && newSize != q->size()) {
+ q->resize(newSize);
+ }
+ } else if (resizeMode == QQuickView::SizeRootObjectToView) {
+ if (!qFuzzyCompare(q->width(), root->width()))
+ root->setWidth(q->width());
+ if (!qFuzzyCompare(q->height(), root->height()))
+ root->setHeight(q->height());
+ }
+}
+
+QSize QQuickViewPrivate::rootObjectSize() const
+{
+ QSize rootObjectSize(0,0);
+ int widthCandidate = -1;
+ int heightCandidate = -1;
+ if (root) {
+ widthCandidate = root->width();
+ heightCandidate = root->height();
+ }
+ if (widthCandidate > 0) {
+ rootObjectSize.setWidth(widthCandidate);
+ }
+ if (heightCandidate > 0) {
+ rootObjectSize.setHeight(heightCandidate);
+ }
+ return rootObjectSize;
+}
+
+QQuickView::ResizeMode QQuickView::resizeMode() const
+{
+ Q_D(const QQuickView);
+ return d->resizeMode;
+}
+
+/*!
+ \internal
+ */
+void QQuickView::continueExecute()
+{
+ Q_D(QQuickView);
+ disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute()));
+
+ if (d->component->isError()) {
+ QList<QDeclarativeError> errorList = d->component->errors();
+ foreach (const QDeclarativeError &error, errorList) {
+ qWarning() << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if (d->component->isError()) {
+ QList<QDeclarativeError> errorList = d->component->errors();
+ foreach (const QDeclarativeError &error, errorList) {
+ qWarning() << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ d->setRootObject(obj);
+ emit statusChanged(status());
+}
+
+
+/*!
+ \internal
+*/
+void QQuickViewPrivate::setRootObject(QObject *obj)
+{
+ Q_Q(QQuickView);
+ if (root == obj)
+ return;
+ if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
+ root = sgItem;
+ sgItem->setParentItem(q->QQuickCanvas::rootItem());
+ } else {
+ qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
+ << endl
+ << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
+ << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
+ << endl
+ << "To load files with 'import QtQuick 1.0' with QML 2, specify:" << endl
+ << " QMLSCENE_IMPORT_NAME=quick1" << endl
+ << "on as an environment variable prior to launching the application." << endl
+ << endl
+ << "To load files with 'import Qt 4.7' with QML 2, specify:" << endl
+ << " QMLSCENE_IMPORT_NAME=qt" << endl
+ << "on as an environment variable prior to launching the application." << endl;
+ delete obj;
+ root = 0;
+ }
+ if (root) {
+ initialSize = rootObjectSize();
+ if ((resizeMode == QQuickView::SizeViewToRootObject || !q->width() || !q->height())
+ && initialSize != q->size()) {
+ q->resize(initialSize);
+ }
+ initResize();
+ }
+}
+
+/*!
+ \internal
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QQuickView::timerEvent(QTimerEvent* e)
+{
+ Q_D(QQuickView);
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ d->updateSize();
+ d->resizetimer.stop();
+ }
+}
+
+/*!
+ \internal
+ Preferred size follows the root object geometry.
+*/
+QSize QQuickView::sizeHint() const
+{
+ Q_D(const QQuickView);
+ QSize rootObjectSize = d->rootObjectSize();
+ if (rootObjectSize.isEmpty()) {
+ return size();
+ } else {
+ return rootObjectSize;
+ }
+}
+
+/*!
+ Returns the initial size of the root object
+*/
+QSize QQuickView::initialSize() const
+{
+ Q_D(const QQuickView);
+ return d->initialSize;
+}
+
+/*!
+ Returns the view's root \l {QQuickItem} {item}.
+ */
+QQuickItem *QQuickView::rootObject() const
+{
+ Q_D(const QQuickView);
+ return d->root;
+}
+
+/*!
+ \internal
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QQuickView::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QQuickView);
+ if (d->resizeMode == SizeRootObjectToView)
+ d->updateSize();
+
+ QQuickCanvas::resizeEvent(e);
+}
+
+void QQuickView::keyPressEvent(QKeyEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
+
+ QQuickCanvas::keyPressEvent(e);
+}
+
+void QQuickView::keyReleaseEvent(QKeyEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
+
+ QQuickCanvas::keyReleaseEvent(e);
+}
+
+void QQuickView::mouseMoveEvent(QMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QQuickCanvas::mouseMoveEvent(e);
+}
+
+void QQuickView::mousePressEvent(QMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QQuickCanvas::mousePressEvent(e);
+}
+
+void QQuickView::mouseReleaseEvent(QMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QQuickCanvas::mouseReleaseEvent(e);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
new file mode 100644
index 0000000000..3c637689d3
--- /dev/null
+++ b/src/quick/items/qquickview.h
@@ -0,0 +1,118 @@
+// Commit: 0b83a2161261be525f01359397ab1c8c34827749
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKVIEW_H
+#define QQUICKVIEW_H
+
+#include <QtQuick/qquickcanvas.h>
+#include <QtCore/qurl.h>
+#include <QtDeclarative/qdeclarativedebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+class QDeclarativeContext;
+class QDeclarativeError;
+class QQuickItem;
+
+class QQuickViewPrivate;
+class Q_QUICK_EXPORT QQuickView : public QQuickCanvas
+{
+ Q_OBJECT
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
+ Q_ENUMS(ResizeMode Status)
+public:
+ explicit QQuickView(QWindow *parent = 0, Qt::WindowFlags f = 0);
+ QQuickView(const QUrl &source, QWindow *parent = 0, Qt::WindowFlags f = 0);
+ virtual ~QQuickView();
+
+ QUrl source() const;
+
+ QDeclarativeEngine* engine() const;
+ QDeclarativeContext* rootContext() const;
+
+ QQuickItem *rootObject() const;
+
+ enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ QList<QDeclarativeError> errors() const;
+
+ QSize sizeHint() const;
+ QSize initialSize() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl&);
+
+Q_SIGNALS:
+ void statusChanged(QQuickView::Status);
+
+private Q_SLOTS:
+ void continueExecute();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void timerEvent(QTimerEvent*);
+
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+private:
+ Q_DISABLE_COPY(QQuickView)
+ Q_DECLARE_PRIVATE(QQuickView)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKVIEW_H
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
new file mode 100644
index 0000000000..dbc02be094
--- /dev/null
+++ b/src/quick/items/qquickview_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKVIEW_P_H
+#define QQUICKVIEW_P_H
+
+#include "qquickview.h"
+
+#include <QtCore/qurl.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qpointer.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include "qquickcanvas_p.h"
+
+#include "qquickitemchangelistener_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeContext;
+class QDeclarativeError;
+class QQuickItem;
+class QDeclarativeComponent;
+
+class QQuickViewPrivate : public QQuickCanvasPrivate,
+ public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickView)
+public:
+ static QQuickViewPrivate* get(QQuickView *view) { return view->d_func(); }
+ static const QQuickViewPrivate* get(const QQuickView *view) { return view->d_func(); }
+
+ QQuickViewPrivate();
+ ~QQuickViewPrivate();
+
+ void execute();
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void initResize();
+ void updateSize();
+ void setRootObject(QObject *);
+
+ void init();
+
+ QSize rootObjectSize() const;
+
+ QPointer<QQuickItem> root;
+
+ QUrl source;
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent *component;
+ QBasicTimer resizetimer;
+
+ QQuickView::ResizeMode resizeMode;
+ QSize initialSize;
+ QElapsedTimer frameTimer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQUICKVIEW_P_H
diff --git a/src/declarative/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp
index 25baee6e29..25baee6e29 100644
--- a/src/declarative/items/qquickvisualadaptormodel.cpp
+++ b/src/quick/items/qquickvisualadaptormodel.cpp
diff --git a/src/declarative/items/qquickvisualadaptormodel_p.h b/src/quick/items/qquickvisualadaptormodel_p.h
index 31eba503ea..31eba503ea 100644
--- a/src/declarative/items/qquickvisualadaptormodel_p.h
+++ b/src/quick/items/qquickvisualadaptormodel_p.h
diff --git a/src/declarative/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
index 649ca6f96b..649ca6f96b 100644
--- a/src/declarative/items/qquickvisualdatamodel.cpp
+++ b/src/quick/items/qquickvisualdatamodel.cpp
diff --git a/src/quick/items/qquickvisualdatamodel_p.h b/src/quick/items/qquickvisualdatamodel_p.h
new file mode 100644
index 0000000000..9e5e3a4511
--- /dev/null
+++ b/src/quick/items/qquickvisualdatamodel_p.h
@@ -0,0 +1,239 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKVISUALDATAMODEL_P_H
+#define QQUICKVISUALDATAMODEL_P_H
+
+#include <private/qdeclarativelistcompositor_p.h>
+#include <private/qquickvisualitemmodel_p.h>
+
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qv8engine_p.h>
+
+QT_BEGIN_HEADER
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeChangeSet;
+class QDeclarativeComponent;
+class QDeclarativePackage;
+class QDeclarativeV8Function;
+class QQuickVisualDataGroup;
+class QQuickVisualDataModelAttached;
+class QQuickVisualDataModelPrivate;
+
+
+class Q_QUICK_EXPORT QQuickVisualDataModel : public QQuickVisualModel, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickVisualDataModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
+ Q_PROPERTY(QQuickVisualDataGroup *items READ items CONSTANT)
+ Q_PROPERTY(QQuickVisualDataGroup *persistedItems READ persistedItems CONSTANT)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickVisualDataGroup> groups READ groups CONSTANT)
+ Q_PROPERTY(QObject *parts READ parts CONSTANT)
+ Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+ Q_INTERFACES(QDeclarativeParserStatus)
+public:
+ QQuickVisualDataModel();
+ QQuickVisualDataModel(QDeclarativeContext *, QObject *parent=0);
+ virtual ~QQuickVisualDataModel();
+
+ void classBegin();
+ void componentComplete();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ QVariant rootIndex() const;
+ void setRootIndex(const QVariant &root);
+
+ Q_INVOKABLE QVariant modelIndex(int idx) const;
+ Q_INVOKABLE QVariant parentModelIndex() const;
+
+ int count() const;
+ bool isValid() const { return delegate() != 0; }
+ QQuickItem *item(int index, bool asynchronous=false);
+ ReleaseFlags release(QQuickItem *item);
+ virtual QString stringValue(int index, const QString &role);
+ virtual void setWatchedRoles(QList<QByteArray> roles);
+
+ int indexOf(QQuickItem *item, QObject *objectContext) const;
+
+ QString filterGroup() const;
+ void setFilterGroup(const QString &group);
+ void resetFilterGroup();
+
+ QQuickVisualDataGroup *items();
+ QQuickVisualDataGroup *persistedItems();
+ QDeclarativeListProperty<QQuickVisualDataGroup> groups();
+ QObject *parts();
+
+ bool event(QEvent *);
+
+ static QQuickVisualDataModelAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void filterGroupChanged();
+ void defaultGroupsChanged();
+ void rootIndexChanged();
+
+private Q_SLOTS:
+ void _q_itemsChanged(int index, int count);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_modelReset(int oldCount, int newCount);
+private:
+ Q_DISABLE_COPY(QQuickVisualDataModel)
+};
+
+class QQuickVisualDataGroupPrivate;
+class Q_AUTOTEST_EXPORT QQuickVisualDataGroup : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
+public:
+ QQuickVisualDataGroup(QObject *parent = 0);
+ QQuickVisualDataGroup(const QString &name, QQuickVisualDataModel *model, int compositorType, QObject *parent = 0);
+ ~QQuickVisualDataGroup();
+
+ QString name() const;
+ void setName(const QString &name);
+
+ int count() const;
+
+ bool defaultInclude() const;
+ void setDefaultInclude(bool include);
+
+ Q_INVOKABLE QDeclarativeV8Handle get(int index);
+ Q_INVOKABLE QObject *create(int index);
+
+public Q_SLOTS:
+ void remove(QDeclarativeV8Function *);
+ void addGroups(QDeclarativeV8Function *);
+ void removeGroups(QDeclarativeV8Function *);
+ void setGroups(QDeclarativeV8Function *);
+ void move(QDeclarativeV8Function *);
+
+Q_SIGNALS:
+ void countChanged();
+ void nameChanged();
+ void defaultIncludeChanged();
+ void changed(const QDeclarativeV8Handle &removed, const QDeclarativeV8Handle &inserted);
+private:
+ Q_DECLARE_PRIVATE(QQuickVisualDataGroup)
+};
+
+class QQuickVisualDataModelCacheItem;
+class QQuickVisualDataModelAttachedMetaObject;
+class QQuickVisualDataModelAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickVisualDataModel *model READ model NOTIFY modelChanged)
+ Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
+public:
+ QQuickVisualDataModelAttached(QObject *parent)
+ : QObject(parent)
+ , m_cacheItem(0)
+ , m_previousGroups(0)
+ , m_modelChanged(false)
+ {}
+ ~QQuickVisualDataModelAttached() { attachedProperties.remove(parent()); }
+
+ void setCacheItem(QQuickVisualDataModelCacheItem *item);
+
+ QQuickVisualDataModel *model() const;
+
+ QStringList groups() const;
+ void setGroups(const QStringList &groups);
+
+ void emitChanges();
+
+ static QQuickVisualDataModelAttached *properties(QObject *obj)
+ {
+ QQuickVisualDataModelAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QQuickVisualDataModelAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+Q_SIGNALS:
+ void modelChanged();
+ void groupsChanged();
+
+public:
+ QQuickVisualDataModelCacheItem *m_cacheItem;
+ int m_previousGroups;
+ int m_previousIndex[QDeclarativeListCompositor::MaximumGroupCount];
+ bool m_modelChanged;
+
+ static QHash<QObject*, QQuickVisualDataModelAttached*> attachedProperties;
+
+ friend class QQuickVisualDataModelAttachedMetaObject;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickVisualDataModel)
+QML_DECLARE_TYPEINFO(QQuickVisualDataModel, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickVisualDataGroup)
+
+QT_END_HEADER
+
+#endif // QQUICKVISUALDATAMODEL_P_H
diff --git a/src/declarative/items/qquickvisualitemmodel.cpp b/src/quick/items/qquickvisualitemmodel.cpp
index 78c4f8868b..78c4f8868b 100644
--- a/src/declarative/items/qquickvisualitemmodel.cpp
+++ b/src/quick/items/qquickvisualitemmodel.cpp
diff --git a/src/quick/items/qquickvisualitemmodel_p.h b/src/quick/items/qquickvisualitemmodel_p.h
new file mode 100644
index 0000000000..c00f841572
--- /dev/null
+++ b/src/quick/items/qquickvisualitemmodel_p.h
@@ -0,0 +1,174 @@
+// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QQUICKVISUALITEMMODEL_P_H
+#define QQUICKVISUALITEMMODEL_P_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QDeclarativeChangeSet;
+
+class Q_QUICK_EXPORT QQuickVisualModel : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ virtual ~QQuickVisualModel() {}
+
+ enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
+ Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
+
+ virtual int count() const = 0;
+ virtual bool isValid() const = 0;
+ virtual QQuickItem *item(int index, bool asynchronous=false) = 0;
+ virtual ReleaseFlags release(QQuickItem *item) = 0;
+ virtual QString stringValue(int, const QString &) = 0;
+ virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
+
+ virtual int indexOf(QQuickItem *item, QObject *objectContext) const = 0;
+
+Q_SIGNALS:
+ void countChanged();
+ void modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+ void createdItem(int index, QQuickItem *item);
+ void initItem(int index, QQuickItem *item);
+ void destroyingItem(QQuickItem *item);
+
+protected:
+ QQuickVisualModel(QObjectPrivate &dd, QObject *parent = 0)
+ : QObject(dd, parent) {}
+
+private:
+ Q_DISABLE_COPY(QQuickVisualModel)
+};
+
+class QQuickVisualItemModelAttached;
+class QQuickVisualItemModelPrivate;
+class Q_QUICK_EXPORT QQuickVisualItemModel : public QQuickVisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickVisualItemModel)
+
+ Q_PROPERTY(QDeclarativeListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
+ Q_CLASSINFO("DefaultProperty", "children")
+
+public:
+ QQuickVisualItemModel(QObject *parent=0);
+ virtual ~QQuickVisualItemModel() {}
+
+ virtual int count() const;
+ virtual bool isValid() const;
+ virtual QQuickItem *item(int index, bool asynchronous=false);
+ virtual ReleaseFlags release(QQuickItem *item);
+ virtual QString stringValue(int index, const QString &role);
+ virtual void setWatchedRoles(QList<QByteArray>) {}
+
+ virtual int indexOf(QQuickItem *item, QObject *objectContext) const;
+
+ QDeclarativeListProperty<QQuickItem> children();
+
+ static QQuickVisualItemModelAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void childrenChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickVisualItemModel)
+};
+
+class QQuickVisualItemModelAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickVisualItemModelAttached(QObject *parent)
+ : QObject(parent), m_index(0) {}
+ ~QQuickVisualItemModelAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const { return m_index; }
+ void setIndex(int idx) {
+ if (m_index != idx) {
+ m_index = idx;
+ emit indexChanged();
+ }
+ }
+
+ static QQuickVisualItemModelAttached *properties(QObject *obj) {
+ QQuickVisualItemModelAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QQuickVisualItemModelAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+Q_SIGNALS:
+ void indexChanged();
+
+public:
+ int m_index;
+
+ static QHash<QObject*, QQuickVisualItemModelAttached*> attachedProperties;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickVisualModel)
+QML_DECLARE_TYPE(QQuickVisualItemModel)
+QML_DECLARE_TYPEINFO(QQuickVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QQUICKVISUALITEMMODEL_P_H
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
new file mode 100644
index 0000000000..726ea055d8
--- /dev/null
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qquickwindowmodule_p.h"
+#include <QtQuick/QQuickCanvas>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickWindowModule::defineModule()
+{
+ const char* uri = "QtQuick.Window";
+
+ qmlRegisterType<QQuickCanvas>(uri, 2, 0, "Window");
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h
index ead15942b9..ead15942b9 100644
--- a/src/declarative/items/qquickwindowmodule_p.h
+++ b/src/quick/items/qquickwindowmodule_p.h
diff --git a/src/declarative/items/syncexcludes b/src/quick/items/syncexcludes
index ab7a374a5b..ab7a374a5b 100644
--- a/src/declarative/items/syncexcludes
+++ b/src/quick/items/syncexcludes
diff --git a/src/declarative/particles/particleresources/noise.png b/src/quick/particles/particleresources/noise.png
index 3c723e1a5a..3c723e1a5a 100644
--- a/src/declarative/particles/particleresources/noise.png
+++ b/src/quick/particles/particleresources/noise.png
Binary files differ
diff --git a/src/declarative/particles/particles.pri b/src/quick/particles/particles.pri
index 3a40a3b911..3a40a3b911 100644
--- a/src/declarative/particles/particles.pri
+++ b/src/quick/particles/particles.pri
diff --git a/src/declarative/particles/particles.qrc b/src/quick/particles/particles.qrc
index 344f9489a4..344f9489a4 100644
--- a/src/declarative/particles/particles.qrc
+++ b/src/quick/particles/particles.qrc
diff --git a/src/declarative/particles/qquickage.cpp b/src/quick/particles/qquickage.cpp
index a71b9e2088..a71b9e2088 100644
--- a/src/declarative/particles/qquickage.cpp
+++ b/src/quick/particles/qquickage.cpp
diff --git a/src/quick/particles/qquickage_p.h b/src/quick/particles/qquickage_p.h
new file mode 100644
index 0000000000..b3fd3c65f4
--- /dev/null
+++ b/src/quick/particles/qquickage_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 KILLAFFECTOR_H
+#define KILLAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAgeAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(int lifeLeft READ lifeLeft WRITE setLifeLeft NOTIFY lifeLeftChanged)
+ Q_PROPERTY(bool advancePosition READ advancePosition WRITE setAdvancePosition NOTIFY advancePositionChanged)
+
+public:
+ explicit QQuickAgeAffector(QQuickItem *parent = 0);
+
+ int lifeLeft() const
+ {
+ return m_lifeLeft;
+ }
+
+ bool advancePosition() const
+ {
+ return m_advancePosition;
+ }
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+signals:
+ void lifeLeftChanged(int arg);
+ void advancePositionChanged(bool arg);
+
+public slots:
+ void setLifeLeft(int arg)
+ {
+ if (m_lifeLeft != arg) {
+ m_lifeLeft = arg;
+ emit lifeLeftChanged(arg);
+ }
+ }
+
+ void setAdvancePosition(bool arg)
+ {
+ if (m_advancePosition != arg) {
+ m_advancePosition = arg;
+ emit advancePositionChanged(arg);
+ }
+ }
+
+private:
+ int m_lifeLeft;
+ bool m_advancePosition;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // KILLAFFECTOR_H
diff --git a/src/declarative/particles/qquickangledirection.cpp b/src/quick/particles/qquickangledirection.cpp
index 9ce422e8d1..9ce422e8d1 100644
--- a/src/declarative/particles/qquickangledirection.cpp
+++ b/src/quick/particles/qquickangledirection.cpp
diff --git a/src/quick/particles/qquickangledirection_p.h b/src/quick/particles/qquickangledirection_p.h
new file mode 100644
index 0000000000..c0de933c00
--- /dev/null
+++ b/src/quick/particles/qquickangledirection_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQuickANGLEDDIRECTION_H
+#define QQuickANGLEDDIRECTION_H
+#include "qquickdirection_p.h"
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAngleDirection : public QQuickDirection
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+ Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
+ Q_PROPERTY(qreal angleVariation READ angleVariation WRITE setAngleVariation NOTIFY angleVariationChanged)
+ Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
+public:
+ explicit QQuickAngleDirection(QObject *parent = 0);
+ const QPointF sample(const QPointF &from);
+ qreal angle() const
+ {
+ return m_angle;
+ }
+
+ qreal magnitude() const
+ {
+ return m_magnitude;
+ }
+
+ qreal angleVariation() const
+ {
+ return m_angleVariation;
+ }
+
+ qreal magnitudeVariation() const
+ {
+ return m_magnitudeVariation;
+ }
+
+signals:
+
+ void angleChanged(qreal arg);
+
+ void magnitudeChanged(qreal arg);
+
+ void angleVariationChanged(qreal arg);
+
+ void magnitudeVariationChanged(qreal arg);
+
+public slots:
+void setAngle(qreal arg)
+{
+ if (m_angle != arg) {
+ m_angle = arg;
+ emit angleChanged(arg);
+ }
+}
+
+void setMagnitude(qreal arg)
+{
+ if (m_magnitude != arg) {
+ m_magnitude = arg;
+ emit magnitudeChanged(arg);
+ }
+}
+
+void setAngleVariation(qreal arg)
+{
+ if (m_angleVariation != arg) {
+ m_angleVariation = arg;
+ emit angleVariationChanged(arg);
+ }
+}
+
+void setMagnitudeVariation(qreal arg)
+{
+ if (m_magnitudeVariation != arg) {
+ m_magnitudeVariation = arg;
+ emit magnitudeVariationChanged(arg);
+ }
+}
+
+private:
+qreal m_angle;
+qreal m_magnitude;
+qreal m_angleVariation;
+qreal m_magnitudeVariation;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // QQuickANGLEDDIRECTION_H
diff --git a/src/declarative/particles/qquickcumulativedirection.cpp b/src/quick/particles/qquickcumulativedirection.cpp
index 2f09ea4505..2f09ea4505 100644
--- a/src/declarative/particles/qquickcumulativedirection.cpp
+++ b/src/quick/particles/qquickcumulativedirection.cpp
diff --git a/src/quick/particles/qquickcumulativedirection_p.h b/src/quick/particles/qquickcumulativedirection_p.h
new file mode 100644
index 0000000000..cae491cafe
--- /dev/null
+++ b/src/quick/particles/qquickcumulativedirection_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQuickCUMULATIVEDIRECTION_P_H
+#define QQuickCUMULATIVEDIRECTION_P_H
+#include "qquickdirection_p.h"
+#include <QDeclarativeListProperty>
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCumulativeDirection : public QQuickDirection
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeListProperty<QQuickDirection> directions READ directions)
+ Q_CLASSINFO("DefaultProperty", "directions")
+public:
+ explicit QQuickCumulativeDirection(QObject *parent = 0);
+ QDeclarativeListProperty<QQuickDirection> directions();
+ const QPointF sample(const QPointF &from);
+private:
+ QList<QQuickDirection*> m_directions;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQuickCUMULATIVEDIRECTION_P_H
diff --git a/src/declarative/particles/qquickcustomaffector.cpp b/src/quick/particles/qquickcustomaffector.cpp
index 80e2eaf268..80e2eaf268 100644
--- a/src/declarative/particles/qquickcustomaffector.cpp
+++ b/src/quick/particles/qquickcustomaffector.cpp
diff --git a/src/quick/particles/qquickcustomaffector_p.h b/src/quick/particles/qquickcustomaffector_p.h
new file mode 100644
index 0000000000..740b0a6773
--- /dev/null
+++ b/src/quick/particles/qquickcustomaffector_p.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 CUSTOMAFFECTOR_H
+#define CUSTOMAFFECTOR_H
+
+#include <QObject>
+#include "qquickparticlesystem_p.h"
+#include "qquickparticleextruder_p.h"
+#include "qquickparticleaffector_p.h"
+#include "qquickdirection_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCustomAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(bool relative READ relative WRITE setRelative NOTIFY relativeChanged)
+ Q_PROPERTY(QQuickDirection *position READ position WRITE setPosition NOTIFY positionChanged RESET positionReset)
+ Q_PROPERTY(QQuickDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged RESET speedReset)
+ Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged RESET accelerationReset)
+
+public:
+ explicit QQuickCustomAffector(QQuickItem *parent = 0);
+ virtual void affectSystem(qreal dt);
+
+ QQuickDirection * position() const
+ {
+ return m_position;
+ }
+
+ QQuickDirection * speed() const
+ {
+ return m_speed;
+ }
+
+ QQuickDirection * acceleration() const
+ {
+ return m_acceleration;
+ }
+
+ void positionReset()
+ {
+ m_position = &m_nullVector;
+ }
+
+ void speedReset()
+ {
+ m_speed = &m_nullVector;
+ }
+
+ void accelerationReset()
+ {
+ m_acceleration = &m_nullVector;
+ }
+
+ bool relative() const
+ {
+ return m_relative;
+ }
+
+
+signals:
+ void affectParticles(QDeclarativeV8Handle particles, qreal dt);
+
+ void positionChanged(QQuickDirection * arg);
+
+ void speedChanged(QQuickDirection * arg);
+
+ void accelerationChanged(QQuickDirection * arg);
+
+ void relativeChanged(bool arg);
+
+public slots:
+ void setPosition(QQuickDirection * arg)
+ {
+ if (m_position != arg) {
+ m_position = arg;
+ emit positionChanged(arg);
+ }
+ }
+
+ void setSpeed(QQuickDirection * arg)
+ {
+ if (m_speed != arg) {
+ m_speed = arg;
+ emit speedChanged(arg);
+ }
+ }
+
+ void setAcceleration(QQuickDirection * arg)
+ {
+ if (m_acceleration != arg) {
+ m_acceleration = arg;
+ emit accelerationChanged(arg);
+ }
+ }
+
+ void setRelative(bool arg)
+ {
+ if (m_relative != arg) {
+ m_relative = arg;
+ emit relativeChanged(arg);
+ }
+ }
+
+protected:
+ bool isAffectConnected();
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+private:
+ void affectProperties(const QList<QQuickParticleData*> particles, qreal dt);
+ QQuickDirection * m_position;
+ QQuickDirection * m_speed;
+ QQuickDirection * m_acceleration;
+
+ QQuickDirection m_nullVector;
+ bool m_relative;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // CUSTOMAFFECTOR_H
diff --git a/src/quick/particles/qquickcustomparticle.cpp b/src/quick/particles/qquickcustomparticle.cpp
new file mode 100644
index 0000000000..e6f50c0ff6
--- /dev/null
+++ b/src/quick/particles/qquickcustomparticle.cpp
@@ -0,0 +1,596 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qquickcustomparticle_p.h"
+#include <QtQuick/private/qquickshadereffectmesh_p.h>
+#include <cstdlib>
+
+QT_BEGIN_NAMESPACE
+
+//Includes comments because the code isn't self explanatory
+static const char qt_particles_template_vertex_code[] =
+ "attribute highp vec2 qt_ParticlePos;\n"
+ "attribute highp vec2 qt_ParticleTex;\n"
+ "attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize\n"
+ "attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration\n"
+ "attribute highp float qt_ParticleR;\n"
+ "uniform highp mat4 qt_Matrix;\n"
+ "uniform highp float qt_Timestamp;\n"
+ "varying highp vec2 qt_TexCoord0;\n"
+ "void defaultMain() {\n"
+ " qt_TexCoord0 = qt_ParticleTex;\n"
+ " highp float size = qt_ParticleData.z;\n"
+ " highp float endSize = qt_ParticleData.w;\n"
+ " highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;\n"
+ " highp float currentSize = mix(size, endSize, t * t);\n"
+ " if (t < 0. || t > 1.)\n"
+ " currentSize = 0.;\n"
+ " highp vec2 pos = qt_ParticlePos\n"
+ " - currentSize / 2. + currentSize * qt_ParticleTex // adjust size\n"
+ " + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..\n"
+ " + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);\n"
+ " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
+ "}";
+static const char qt_particles_default_vertex_code[] =
+ "void main() { \n"
+ " defaultMain(); \n"
+ "}";
+
+static const char qt_particles_default_fragment_code[] =
+ "uniform sampler2D source; \n"
+ "varying highp vec2 qt_TexCoord0; \n"
+ "uniform lowp float qt_Opacity; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
+ "}";
+
+static QSGGeometry::Attribute PlainParticle_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
+ QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
+ QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
+ QSGGeometry::Attribute::create(4, 1, GL_FLOAT) // r
+};
+
+static QSGGeometry::AttributeSet PlainParticle_AttributeSet =
+{
+ 5, // Attribute Count
+ (2 + 2 + 4 + 4 + 1) * sizeof(float),
+ PlainParticle_Attributes
+};
+
+struct PlainVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ float r;
+};
+
+struct PlainVertices {
+ PlainVertex v1;
+ PlainVertex v2;
+ PlainVertex v3;
+ PlainVertex v4;
+};
+
+/*!
+ \qmlclass CustomParticle QQuickCustomParticle
+ \inqmlmodule QtQuick.Particles 2
+ \inherits ParticlePainter
+ \brief The CustomParticle element allows you to specify your own shader to paint particles.
+
+*/
+
+QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent)
+ : QQuickParticlePainter(parent)
+ , m_dirtyData(true)
+ , m_material(0)
+ , m_rootNode(0)
+{
+ setFlag(QQuickItem::ItemHasContents);
+}
+
+class QQuickShaderEffectMaterialObject : public QObject, public QQuickShaderEffectMaterial { };
+
+QQuickCustomParticle::~QQuickCustomParticle()
+{
+ if (m_material)
+ m_material->deleteLater();
+}
+
+void QQuickCustomParticle::componentComplete()
+{
+ reset();
+ QQuickParticlePainter::componentComplete();
+}
+
+
+//Trying to keep the shader conventions the same as in qsgshadereffectitem
+/*!
+ \qmlproperty string QtQuick.Particles2::CustomParticle::fragmentShader
+
+ This property holds the fragment shader's GLSL source code.
+ The default shader expects the texture coordinate to be passed from the
+ vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
+ sampler2D named "source".
+*/
+
+void QQuickCustomParticle::setFragmentShader(const QByteArray &code)
+{
+ if (m_source.fragmentCode.constData() == code.constData())
+ return;
+ m_source.fragmentCode = code;
+ if (isComponentComplete()) {
+ reset();
+ }
+ emit fragmentShaderChanged();
+}
+
+/*!
+ \qmlproperty string QtQuick.Particles2::CustomParticle::vertexShader
+
+ This property holds the vertex shader's GLSL source code.
+
+ The default shader passes the texture coordinate along to the fragment
+ shader as "varying highp vec2 qt_TexCoord0".
+
+ To aid writing a particle vertex shader, the following GLSL code is prepended
+ to your vertex shader:
+ \code
+ attribute highp vec2 qt_ParticlePos;
+ attribute highp vec2 qt_ParticleTex;
+ attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
+ attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration
+ attribute highp float qt_ParticleR;
+ uniform highp mat4 qt_Matrix;
+ uniform highp float qt_Timestamp;
+ varying highp vec2 qt_TexCoord0;
+ void defaultMain() {
+ qt_TexCoord0 = qt_ParticleTex;
+ highp float size = qt_ParticleData.z;
+ highp float endSize = qt_ParticleData.w;
+ highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
+ highp float currentSize = mix(size, endSize, t * t);
+ if (t < 0. || t > 1.)
+ currentSize = 0.;
+ highp vec2 pos = qt_ParticlePos
+ - currentSize / 2. + currentSize * qt_ParticleTex // adjust size
+ + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..
+ + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+ }
+ \endcode
+
+ defaultMain() is the same code as in the default shader, you can call this for basic
+ particle functions and then add additional variables for custom effects. Note that
+ the vertex shader for particles is responsible for simulating the movement of particles
+ over time, the particle data itself only has the starting position and spawn time.
+*/
+
+void QQuickCustomParticle::setVertexShader(const QByteArray &code)
+{
+ if (m_source.vertexCode.constData() == code.constData())
+ return;
+ m_source.vertexCode = code;
+ if (isComponentComplete()) {
+ reset();
+ }
+ emit vertexShaderChanged();
+}
+
+void QQuickCustomParticle::reset()
+{
+ disconnectPropertySignals();
+
+ m_source.attributeNames.clear();
+ m_source.uniformNames.clear();
+ m_source.respectsOpacity = false;
+ m_source.respectsMatrix = false;
+ m_source.className = metaObject()->className();
+
+ for (int i = 0; i < m_sources.size(); ++i) {
+ const SourceData &source = m_sources.at(i);
+ delete source.mapper;
+ if (source.item && source.item->parentItem() == this)
+ source.item->setParentItem(0);
+ }
+ m_sources.clear();
+
+ QQuickParticlePainter::reset();
+ m_pleaseReset = true;
+ update();
+}
+
+
+void QQuickCustomParticle::changeSource(int index)
+{
+ Q_ASSERT(index >= 0 && index < m_sources.size());
+ QVariant v = property(m_sources.at(index).name.constData());
+ setSource(v, index);
+}
+
+void QQuickCustomParticle::updateData()
+{
+ m_dirtyData = true;
+ update();
+}
+
+void QQuickCustomParticle::setSource(const QVariant &var, int index)
+{
+ Q_ASSERT(index >= 0 && index < m_sources.size());
+
+ SourceData &source = m_sources[index];
+
+ source.item = 0;
+ if (var.isNull()) {
+ return;
+ } else if (!qVariantCanConvert<QObject *>(var)) {
+ qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
+ return;
+ }
+
+ QObject *obj = qVariantValue<QObject *>(var);
+ source.item = qobject_cast<QQuickItem *>(obj);
+ if (!source.item || !source.item->isTextureProvider()) {
+ qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
+ source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
+ return;
+ }
+
+ // TODO: Copy better solution in QQuickShaderEffect when they find it.
+ // 'source.item' needs a canvas to get a scenegraph node.
+ // The easiest way to make sure it gets a canvas is to
+ // make it a part of the same item tree as 'this'.
+ if (source.item && source.item->parentItem() == 0) {
+ source.item->setParentItem(this);
+ source.item->setVisible(false);
+ }
+}
+
+void QQuickCustomParticle::disconnectPropertySignals()
+{
+ disconnect(this, 0, this, SLOT(updateData()));
+ for (int i = 0; i < m_sources.size(); ++i) {
+ SourceData &source = m_sources[i];
+ disconnect(this, 0, source.mapper, 0);
+ disconnect(source.mapper, 0, this, 0);
+ }
+}
+
+void QQuickCustomParticle::connectPropertySignals()
+{
+ QSet<QByteArray>::const_iterator it;
+ for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
+ int pi = metaObject()->indexOfProperty(it->constData());
+ if (pi >= 0) {
+ QMetaProperty mp = metaObject()->property(pi);
+ if (!mp.hasNotifySignal())
+ qWarning("QQuickCustomParticle: property '%s' does not have notification method!", it->constData());
+ QByteArray signalName("2");
+ signalName.append(mp.notifySignal().signature());
+ connect(this, signalName, this, SLOT(updateData()));
+ } else {
+ qWarning("QQuickCustomParticle: '%s' does not have a matching property!", it->constData());
+ }
+ }
+ for (int i = 0; i < m_sources.size(); ++i) {
+ SourceData &source = m_sources[i];
+ int pi = metaObject()->indexOfProperty(source.name.constData());
+ if (pi >= 0) {
+ QMetaProperty mp = metaObject()->property(pi);
+ QByteArray signalName("2");
+ signalName.append(mp.notifySignal().signature());
+ connect(this, signalName, source.mapper, SLOT(map()));
+ source.mapper->setMapping(this, i);
+ connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
+ } else {
+ qWarning("QQuickCustomParticle: '%s' does not have a matching source!", source.name.constData());
+ }
+ }
+}
+
+void QQuickCustomParticle::updateProperties()
+{
+ QByteArray vertexCode = m_source.vertexCode;
+ QByteArray fragmentCode = m_source.fragmentCode;
+ if (vertexCode.isEmpty())
+ vertexCode = qt_particles_default_vertex_code;
+ if (fragmentCode.isEmpty())
+ fragmentCode = qt_particles_default_fragment_code;
+ vertexCode = qt_particles_template_vertex_code + vertexCode;
+
+ m_source.attributeNames.clear();
+ m_source.attributeNames << "qt_ParticlePos"
+ << "qt_ParticleTex"
+ << "qt_ParticleData"
+ << "qt_ParticleVec"
+ << "qt_ParticleR";
+
+ lookThroughShaderCode(vertexCode);
+ lookThroughShaderCode(fragmentCode);
+
+ if (!m_source.respectsMatrix)
+ qWarning("QQuickCustomParticle: Missing reference to \'qt_Matrix\'.");
+ if (!m_source.respectsOpacity)
+ qWarning("QQuickCustomParticle: Missing reference to \'qt_Opacity\'.");
+
+ for (int i = 0; i < m_sources.size(); ++i) {
+ QVariant v = property(m_sources.at(i).name);
+ setSource(v, i);
+ }
+
+ connectPropertySignals();
+}
+
+void QQuickCustomParticle::lookThroughShaderCode(const QByteArray &code)
+{
+ // Regexp for matching attributes and uniforms.
+ // In human readable form: attribute|uniform [lowp|mediump|highp] <type> <name>
+ static QRegExp re(QLatin1String("\\b(attribute|uniform)\\b\\s*\\b(?:lowp|mediump|highp)?\\b\\s*\\b(\\w+)\\b\\s*\\b(\\w+)"));
+ Q_ASSERT(re.isValid());
+
+ int pos = -1;
+
+ QString wideCode = QString::fromLatin1(code.constData(), code.size());
+
+ while ((pos = re.indexIn(wideCode, pos + 1)) != -1) {
+ QByteArray decl = re.cap(1).toLatin1(); // uniform or attribute
+ QByteArray type = re.cap(2).toLatin1(); // type
+ QByteArray name = re.cap(3).toLatin1(); // variable name
+
+ if (decl == "attribute") {
+ if (!m_source.attributeNames.contains(name))
+ qWarning() << "Custom Particle: Unknown attribute " << name;
+ } else {
+ Q_ASSERT(decl == "uniform");//TODO: Shouldn't assert
+
+ if (name == "qt_Matrix") {
+ m_source.respectsMatrix = true;
+ } else if (name == "qt_Opacity") {
+ m_source.respectsOpacity = true;
+ } else if (name == "qt_Timestamp") {
+ //Not strictly necessary
+ } else {
+ m_source.uniformNames.insert(name);
+ if (type == "sampler2D") {
+ SourceData d;
+ d.mapper = new QSignalMapper;
+ d.name = name;
+ d.item = 0;
+ m_sources.append(d);
+ }
+ }
+ }
+ }
+}
+
+QSGNode *QQuickCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ Q_UNUSED(oldNode);
+ if (m_pleaseReset){
+
+ //delete m_material;//Shader effect item doesn't regen material?
+
+ delete m_rootNode;//Automatically deletes children
+ m_rootNode = 0;
+ m_nodes.clear();
+ m_pleaseReset = false;
+ m_dirtyData = false;
+ }
+
+ if (m_system && m_system->isRunning() && !m_system->isPaused()){
+ prepareNextFrame();
+ if (m_rootNode) {
+ update();
+ foreach (QSGGeometryNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyGeometry);//done in buildData?
+ }
+ }
+
+ return m_rootNode;
+}
+
+void QQuickCustomParticle::prepareNextFrame(){
+ if (!m_rootNode)
+ m_rootNode = buildCustomNodes();
+ if (!m_rootNode)
+ return;
+
+ m_lastTime = m_system->systemSync(this) / 1000.;
+ if (m_dirtyData || true)//Currently this is how we update timestamp... potentially over expensive.
+ buildData();
+}
+
+QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
+{
+#ifdef QT_OPENGL_ES_2
+ if (m_count * 4 > 0xffff) {
+ printf("CustomParticle: Too many particles... \n");
+ return 0;
+ }
+#endif
+
+ if (m_count <= 0) {
+ printf("CustomParticle: Too few particles... \n");
+ return 0;
+ }
+
+ updateProperties();
+
+ QQuickShaderEffectProgram s = m_source;
+ if (s.fragmentCode.isEmpty())
+ s.fragmentCode = qt_particles_default_fragment_code;
+ if (s.vertexCode.isEmpty())
+ s.vertexCode = qt_particles_default_vertex_code;
+
+ if (!m_material) {
+ m_material = new QQuickShaderEffectMaterialObject;
+ }
+
+ s.vertexCode = qt_particles_template_vertex_code + s.vertexCode;
+ m_material->setProgramSource(s);
+ foreach (const QString &str, m_groups){
+ int gIdx = m_system->groupIds[str];
+ int count = m_system->groupData[gIdx]->size();
+
+ QQuickShaderEffectNode* node = new QQuickShaderEffectNode();
+ m_nodes.insert(gIdx, node);
+
+ node->setMaterial(m_material);
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ //Create Particle Geometry
+ int vCount = count * 4;
+ int iCount = count * 6;
+ QSGGeometry *g = new QSGGeometry(PlainParticle_AttributeSet, vCount, iCount);
+ g->setDrawingMode(GL_TRIANGLES);
+ node->setGeometry(g);
+ PlainVertex *vertices = (PlainVertex *) g->vertexData();
+ for (int p=0; p < count; ++p) {
+ commit(gIdx, p);
+ vertices[0].tx = 0;
+ vertices[0].ty = 0;
+
+ vertices[1].tx = 1;
+ vertices[1].ty = 0;
+
+ vertices[2].tx = 0;
+ vertices[2].ty = 1;
+
+ vertices[3].tx = 1;
+ vertices[3].ty = 1;
+ vertices += 4;
+ }
+ quint16 *indices = g->indexDataAsUShort();
+ for (int i=0; i < count; ++i) {
+ int o = i * 4;
+ indices[0] = o;
+ indices[1] = o + 1;
+ indices[2] = o + 2;
+ indices[3] = o + 1;
+ indices[4] = o + 3;
+ indices[5] = o + 2;
+ indices += 6;
+ }
+ }
+ foreach (QQuickShaderEffectNode* node, m_nodes){
+ if (node == *(m_nodes.begin()))
+ continue;
+ (*(m_nodes.begin()))->appendChildNode(node);
+ }
+
+ return *(m_nodes.begin());
+}
+
+
+void QQuickCustomParticle::buildData()
+{
+ if (!m_rootNode)
+ return;
+ const QByteArray timestampName("qt_Timestamp");
+ QVector<QPair<QByteArray, QVariant> > values;
+ QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material->textureProviders();
+ for (int i = 0; i < oldTextures.size(); ++i) {
+ QSGTextureProvider *t = oldTextures.at(i).second;
+ if (t)
+ foreach (QQuickShaderEffectNode* node, m_nodes)
+ disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ }
+ for (int i = 0; i < m_sources.size(); ++i) {
+ const SourceData &source = m_sources.at(i);
+ QSGTextureProvider *t = source.item->textureProvider();
+ textures.append(qMakePair(source.name, t));
+ if (t)
+ foreach (QQuickShaderEffectNode* node, m_nodes)
+ connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
+ }
+ for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
+ it != m_source.uniformNames.end(); ++it) {
+ values.append(qMakePair(*it, property(*it)));
+ }
+ values.append(qMakePair(timestampName, QVariant(m_lastTime)));
+ m_material->setUniforms(values);
+ m_material->setTextureProviders(textures);
+ m_dirtyData = false;
+ foreach (QQuickShaderEffectNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyMaterial);
+}
+
+void QQuickCustomParticle::initialize(int gIdx, int pIdx)
+{
+ QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
+ datum->r = rand()/(qreal)RAND_MAX;
+}
+
+void QQuickCustomParticle::commit(int gIdx, int pIdx)
+{
+ if (m_nodes[gIdx] == 0)
+ return;
+
+ QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
+ PlainVertices *particles = (PlainVertices *) m_nodes[gIdx]->geometry()->vertexData();
+ PlainVertex *vertices = (PlainVertex *)&particles[pIdx];
+ for (int i=0; i<4; ++i) {
+ vertices[i].x = datum->x - m_systemOffset.x();
+ vertices[i].y = datum->y - m_systemOffset.y();
+ vertices[i].t = datum->t;
+ vertices[i].lifeSpan = datum->lifeSpan;
+ vertices[i].size = datum->size;
+ vertices[i].endSize = datum->endSize;
+ vertices[i].vx = datum->vx;
+ vertices[i].vy = datum->vy;
+ vertices[i].ax = datum->ax;
+ vertices[i].ay = datum->ay;
+ vertices[i].r = datum->r;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickcustomparticle_p.h b/src/quick/particles/qquickcustomparticle_p.h
new file mode 100644
index 0000000000..583e61fa39
--- /dev/null
+++ b/src/quick/particles/qquickcustomparticle_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 CUSTOM_PARTICLE_H
+#define CUSTOM_PARTICLE_H
+#include "qquickparticlepainter_p.h"
+#include <private/qquickshadereffectnode_p.h>
+#include <QSignalMapper>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGNode;
+struct PlainVertices;
+
+class QQuickShaderEffectMaterialObject;
+
+//Genealogy: Hybrid of UltraParticle and ShaderEffect
+class QQuickCustomParticle : public QQuickParticlePainter
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
+ Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
+
+public:
+ explicit QQuickCustomParticle(QQuickItem* parent=0);
+ ~QQuickCustomParticle();
+
+ QByteArray fragmentShader() const { return m_source.fragmentCode; }
+ void setFragmentShader(const QByteArray &code);
+
+ QByteArray vertexShader() const { return m_source.vertexCode; }
+ void setVertexShader(const QByteArray &code);
+public Q_SLOTS:
+ void updateData();
+ void changeSource(int);
+Q_SIGNALS:
+ void fragmentShaderChanged();
+ void vertexShaderChanged();
+protected:
+ virtual void initialize(int gIdx, int pIdx);
+ virtual void commit(int gIdx, int pIdx);
+
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void prepareNextFrame();
+ void setSource(const QVariant &var, int index);
+ void disconnectPropertySignals();
+ void connectPropertySignals();
+ void reset();
+ void resize(int oldCount, int newCount);
+ void updateProperties();
+ void lookThroughShaderCode(const QByteArray &code);
+ virtual void componentComplete();
+ QQuickShaderEffectNode *buildCustomNodes();
+ void performPendingResize();
+
+private:
+ void buildData();
+
+ bool m_dirtyData;
+ QQuickShaderEffectProgram m_source;
+ struct SourceData
+ {
+ QSignalMapper *mapper;
+ QPointer<QQuickItem> item;
+ QByteArray name;
+ };
+ QVector<SourceData> m_sources;
+ QQuickShaderEffectMaterialObject *m_material;
+ QQuickShaderEffectNode* m_rootNode;
+ QHash<int, QQuickShaderEffectNode*> m_nodes;
+ qreal m_lastTime;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //HEADER_GUARD
diff --git a/src/declarative/particles/qquickdirection.cpp b/src/quick/particles/qquickdirection.cpp
index babd35de9f..babd35de9f 100644
--- a/src/declarative/particles/qquickdirection.cpp
+++ b/src/quick/particles/qquickdirection.cpp
diff --git a/src/quick/particles/qquickdirection_p.h b/src/quick/particles/qquickdirection_p.h
new file mode 100644
index 0000000000..ecfb84d90f
--- /dev/null
+++ b/src/quick/particles/qquickdirection_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 VARYINGVECTOR_H
+#define VARYINGVECTOR_H
+
+#include <QObject>
+#include <QPointF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDirection : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QQuickDirection(QObject *parent = 0);
+
+ virtual const QPointF sample(const QPointF &from);
+signals:
+
+public slots:
+
+protected:
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // VARYINGVECTOR_H
diff --git a/src/declarative/particles/qquickellipseextruder.cpp b/src/quick/particles/qquickellipseextruder.cpp
index 479bbb4aa7..479bbb4aa7 100644
--- a/src/declarative/particles/qquickellipseextruder.cpp
+++ b/src/quick/particles/qquickellipseextruder.cpp
diff --git a/src/quick/particles/qquickellipseextruder_p.h b/src/quick/particles/qquickellipseextruder_p.h
new file mode 100644
index 0000000000..77c117a3d5
--- /dev/null
+++ b/src/quick/particles/qquickellipseextruder_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 ELLIPSEEXTRUDER_H
+#define ELLIPSEEXTRUDER_H
+#include "qquickparticleextruder_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickEllipseExtruder : public QQuickParticleExtruder
+{
+ Q_OBJECT
+ Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)//###Use base class? If it's still box
+public:
+ explicit QQuickEllipseExtruder(QObject *parent = 0);
+ virtual QPointF extrude(const QRectF &);
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
+
+ bool fill() const
+ {
+ return m_fill;
+ }
+
+signals:
+
+ void fillChanged(bool arg);
+
+public slots:
+
+ void setFill(bool arg)
+ {
+ if (m_fill != arg) {
+ m_fill = arg;
+ emit fillChanged(arg);
+ }
+ }
+private:
+ bool m_fill;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // ELLIPSEEXTRUDER_H
diff --git a/src/declarative/particles/qquickfriction.cpp b/src/quick/particles/qquickfriction.cpp
index c060deb95f..c060deb95f 100644
--- a/src/declarative/particles/qquickfriction.cpp
+++ b/src/quick/particles/qquickfriction.cpp
diff --git a/src/quick/particles/qquickfriction_p.h b/src/quick/particles/qquickfriction_p.h
new file mode 100644
index 0000000000..0eaed34783
--- /dev/null
+++ b/src/quick/particles/qquickfriction_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 FRICTIONAFFECTOR_H
+#define FRICTIONAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickFrictionAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal factor READ factor WRITE setFactor NOTIFY factorChanged)
+ Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged)
+public:
+ explicit QQuickFrictionAffector(QQuickItem *parent = 0);
+
+ qreal factor() const
+ {
+ return m_factor;
+ }
+
+ qreal threshold() const
+ {
+ return m_threshold;
+ }
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+
+signals:
+
+ void factorChanged(qreal arg);
+ void thresholdChanged(qreal arg);
+
+public slots:
+
+ void setFactor(qreal arg)
+ {
+ if (m_factor != arg) {
+ m_factor = arg;
+ emit factorChanged(arg);
+ }
+ }
+
+ void setThreshold(qreal arg)
+ {
+ if (m_threshold != arg) {
+ m_threshold = arg;
+ emit thresholdChanged(arg);
+ }
+ }
+
+private:
+ qreal m_factor;
+ qreal m_threshold;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // FRICTIONAFFECTOR_H
diff --git a/src/declarative/particles/qquickgravity.cpp b/src/quick/particles/qquickgravity.cpp
index fd2fb92a53..fd2fb92a53 100644
--- a/src/declarative/particles/qquickgravity.cpp
+++ b/src/quick/particles/qquickgravity.cpp
diff --git a/src/quick/particles/qquickgravity_p.h b/src/quick/particles/qquickgravity_p.h
new file mode 100644
index 0000000000..a9faf43349
--- /dev/null
+++ b/src/quick/particles/qquickgravity_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 GRAVITYAFFECTOR_H
+#define GRAVITYAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickGravityAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
+ Q_PROPERTY(qreal acceleration READ magnitude WRITE setAcceleration NOTIFY magnitudeChanged)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+public:
+ explicit QQuickGravityAffector(QQuickItem *parent = 0);
+ qreal magnitude() const
+ {
+ return m_magnitude;
+ }
+
+ qreal angle() const
+ {
+ return m_angle;
+ }
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+signals:
+
+ void magnitudeChanged(qreal arg);
+
+ void angleChanged(qreal arg);
+
+public slots:
+void setAcceleration(qreal arg)
+{
+ qWarning() << "Gravity::acceleration has been renamed Gravity::magnitude";
+ if (m_magnitude != arg) {
+ m_magnitude = arg;
+ m_needRecalc = true;
+ emit magnitudeChanged(arg);
+ }
+}
+
+void setMagnitude(qreal arg)
+{
+ if (m_magnitude != arg) {
+ m_magnitude = arg;
+ m_needRecalc = true;
+ emit magnitudeChanged(arg);
+ }
+}
+
+void setAngle(qreal arg)
+{
+ if (m_angle != arg) {
+ m_angle = arg;
+ m_needRecalc = true;
+ emit angleChanged(arg);
+ }
+}
+
+private:
+ qreal m_magnitude;
+ qreal m_angle;
+
+ bool m_needRecalc;
+ qreal m_dx;
+ qreal m_dy;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // GRAVITYAFFECTOR_H
diff --git a/src/declarative/particles/qquickgroupgoal.cpp b/src/quick/particles/qquickgroupgoal.cpp
index 1d8a3d980c..1d8a3d980c 100644
--- a/src/declarative/particles/qquickgroupgoal.cpp
+++ b/src/quick/particles/qquickgroupgoal.cpp
diff --git a/src/quick/particles/qquickgroupgoal_p.h b/src/quick/particles/qquickgroupgoal_p.h
new file mode 100644
index 0000000000..a24d89dfb5
--- /dev/null
+++ b/src/quick/particles/qquickgroupgoal_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 GROUPGOALAFFECTOR_H
+#define GROUPGOALAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickStochasticEngine;
+
+class QQuickGroupGoalAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
+ Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
+public:
+ explicit QQuickGroupGoalAffector(QQuickItem *parent = 0);
+
+ QString goalState() const
+ {
+ return m_goalState;
+ }
+
+ bool jump() const
+ {
+ return m_jump;
+ }
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+
+signals:
+
+ void goalStateChanged(QString arg);
+
+ void jumpChanged(bool arg);
+
+public slots:
+
+ void setGoalState(QString arg);
+
+ void setJump(bool arg)
+ {
+ if (m_jump != arg) {
+ m_jump = arg;
+ emit jumpChanged(arg);
+ }
+ }
+
+private:
+ QString m_goalState;
+ bool m_jump;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // GROUPGOALAFFECTOR_H
diff --git a/src/quick/particles/qquickimageparticle.cpp b/src/quick/particles/qquickimageparticle.cpp
new file mode 100644
index 0000000000..3453dd6ed3
--- /dev/null
+++ b/src/quick/particles/qquickimageparticle.cpp
@@ -0,0 +1,1804 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 <QtQuick/private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgtexturematerial.h>
+#include <QtQuick/qsgtexture.h>
+#include <QFile>
+#include "qquickimageparticle_p.h"
+#include "qquickparticleemitter_p.h"
+#include <private/qquicksprite_p.h>
+#include <private/qquickspriteengine_p.h>
+#include <QOpenGLFunctions>
+#include <QtQuick/qsgengine.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
+DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
+
+#ifndef QT_OPENGL_ES_2
+#define SHADER_DEFINES "#version 120\n"
+#else
+#define SHADER_DEFINES ""
+#endif
+
+//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
+#define UNIFORM_ARRAY_SIZE 64
+
+static const char vertexShaderCode[] =
+ "attribute highp vec2 vPos;\n"
+ "attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize\n"
+ "attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration\n"
+ "uniform highp float entry;\n"
+ "#ifdef COLOR\n"
+ "attribute lowp vec4 vColor;\n"
+ "#endif\n"
+ "#ifdef DEFORM\n"
+ "attribute highp vec2 vTex;\n"
+ "attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector\n"
+ "attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate\n"
+ "#endif\n"
+ "#ifdef SPRITE\n"
+ "attribute highp vec4 vAnimData;// interpolate(bool), duration, frameCount (this anim), timestamp (this anim)\n"
+ "attribute highp vec4 vAnimPos;//sheet x,y, width/height of this anim\n"
+ "uniform highp vec2 animSheetSize; //width/height of whole sheet\n"
+ "#endif\n"
+ "\n"
+ "uniform highp mat4 qt_Matrix;\n"
+ "uniform highp float timestamp;\n"
+ "#ifdef TABLE\n"
+ "varying lowp vec2 tt;//y is progress if Sprite mode\n"
+ "uniform highp float sizetable[64];\n"
+ "uniform highp float opacitytable[64];\n"
+ "#endif\n"
+ "#ifdef SPRITE\n"
+ "varying highp vec4 fTexS;\n"
+ "#else\n"
+ "#ifdef DEFORM\n"
+ "varying highp vec2 fTex;\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef COLOR\n"
+ "varying lowp vec4 fColor;\n"
+ "#else\n"
+ "varying lowp float fFade;\n"
+ "#endif\n"
+ "\n"
+ "\n"
+ "void main() {\n"
+ "\n"
+ " highp float t = (timestamp - vData.x) / vData.y;\n"
+ " if (t < 0. || t > 1.){\n"
+ "#ifdef DEFORM //Not point sprites\n"
+ " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);\n"
+ "#else\n"
+ " gl_PointSize = 0.;\n"
+ "#endif\n"
+ " return;\n"
+ " }\n"
+ "#ifdef SPRITE\n"
+ " //Calculate frame location in texture\n"
+ " highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);\n"
+ " tt.y = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;\n"
+ "\n"
+ " frameIndex = floor(frameIndex);\n"
+ " fTexS.xy = vec2(((frameIndex + vTex.x) * vAnimPos.z / animSheetSize.x), ((vAnimPos.y + vTex.y * vAnimPos.w) / animSheetSize.y));\n"
+ "\n"
+ " //Next frame is also passed, for interpolation\n"
+ " //### Should the next anim be precalculated to allow for interpolation there?\n"
+ " if (vAnimData.x == 1.0 && frameIndex != vAnimData.z - 1.)//Can't do it for the last frame though, this anim may not loop\n"
+ " frameIndex = mod(frameIndex+1., vAnimData.z);\n"
+ " fTexS.zw = vec2(((frameIndex + vTex.x) * vAnimPos.z / animSheetSize.x), ((vAnimPos.y + vTex.y * vAnimPos.w) / animSheetSize.y));\n"
+ "#else\n"
+ "#ifdef DEFORM\n"
+ " fTex = vTex;\n"
+ "#endif\n"
+ "#endif\n"
+ " highp float currentSize = mix(vData.z, vData.w, t * t);\n"
+ " lowp float fade = 1.;\n"
+ " highp float fadeIn = min(t * 10., 1.);\n"
+ " highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);\n"
+ "\n"
+ "#ifdef TABLE\n"
+ " currentSize = currentSize * sizetable[int(floor(t*64.))];\n"
+ " fade = fade * opacitytable[int(floor(t*64.))];\n"
+ "#endif\n"
+ "\n"
+ " if (entry == 1.)\n"
+ " fade = fade * fadeIn * fadeOut;\n"
+ " else if (entry == 2.)\n"
+ " currentSize = currentSize * fadeIn * fadeOut;\n"
+ "\n"
+ " if (currentSize <= 0.){\n"
+ "#ifdef DEFORM //Not point sprites\n"
+ " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);\n"
+ "#else\n"
+ " gl_PointSize = 0.;\n"
+ "#endif\n"
+ " return;\n"
+ " }\n"
+ " if (currentSize < 3.)//Sizes too small look jittery as they move\n"
+ " currentSize = 3.;\n"
+ "\n"
+ " highp vec2 pos;\n"
+ "#ifdef DEFORM\n"
+ " highp float rotation = vRotation.x + vRotation.y * t * vData.y;\n"
+ " if (vRotation.z == 1.0){\n"
+ " highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;\n"
+ " rotation += atan(curVel.y, curVel.x);\n"
+ " }\n"
+ " highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));\n"
+ " highp vec4 deform = vDeformVec * currentSize * (vTex.xxyy - 0.5);\n"
+ " highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;\n"
+ " rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));\n"
+ " /* The readable version:\n"
+ " highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);\n"
+ " highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);\n"
+ " highp vec2 xRotatedDeform;\n"
+ " xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;\n"
+ " xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;\n"
+ " highp vec2 yRotatedDeform;\n"
+ " yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;\n"
+ " yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;\n"
+ " */\n"
+ " pos = vPos\n"
+ " + rotatedDeform.xy\n"
+ " + rotatedDeform.zw\n"
+ " + vVec.xy * t * vData.y // apply speed\n"
+ " + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration\n"
+ "#else\n"
+ " pos = vPos\n"
+ " + vVec.xy * t * vData.y // apply speed vector..\n"
+ " + 0.5 * vVec.zw * pow(t * vData.y, 2.);\n"
+ " gl_PointSize = currentSize;\n"
+ "#endif\n"
+ " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
+ "\n"
+ "#ifdef COLOR\n"
+ " fColor = vColor * fade;\n"
+ "#else\n"
+ " fFade = fade;\n"
+ "#endif\n"
+ "#ifdef TABLE\n"
+ " tt.x = t;\n"
+ "#endif\n"
+ "}\n";
+
+static const char fragmentShaderCode[] =
+ "uniform sampler2D texture;\n"
+ "uniform lowp float qt_Opacity;\n"
+ "\n"
+ "#ifdef SPRITE\n"
+ "varying highp vec4 fTexS;\n"
+ "#else\n"
+ "#ifdef DEFORM //First non-pointsprite\n"
+ "varying highp vec2 fTex;\n"
+ "#endif\n"
+ "#endif\n"
+ "#ifdef COLOR\n"
+ "varying lowp vec4 fColor;\n"
+ "#else\n"
+ "varying lowp float fFade;\n"
+ "#endif\n"
+ "#ifdef TABLE\n"
+ "varying lowp vec2 tt;\n"
+ "uniform sampler2D colortable;\n"
+ "#endif\n"
+ "\n"
+ "void main() {\n"
+ "#ifdef SPRITE\n"
+ " gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)\n"
+ " * fColor\n"
+ " * texture2D(colortable, tt)\n"
+ " * qt_Opacity;\n"
+ "#else\n"
+ "#ifdef TABLE\n"
+ " gl_FragColor = texture2D(texture, fTex)\n"
+ " * fColor\n"
+ " * texture2D(colortable, tt)\n"
+ " * qt_Opacity;\n"
+ "#else\n"
+ "#ifdef DEFORM\n"
+ " gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;\n"
+ "#else\n"
+ "#ifdef COLOR\n"
+ " gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;\n"
+ "#else\n"
+ " gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);\n"
+ "#endif //COLOR\n"
+ "#endif //DEFORM\n"
+ "#endif //TABLE\n"
+ "#endif //SPRITE\n"
+ "}\n";
+
+const qreal CONV = 0.017453292519943295;
+class ImageMaterialData
+{
+ public:
+ ImageMaterialData()
+ : texture(0), colorTable(0)
+ {}
+
+ ~ImageMaterialData(){
+ delete texture;
+ delete colorTable;
+ }
+
+ QSGTexture *texture;
+ QSGTexture *colorTable;
+ float sizeTable[UNIFORM_ARRAY_SIZE];
+ float opacityTable[UNIFORM_ARRAY_SIZE];
+
+ qreal timestamp;
+ qreal entry;
+ QSizeF animSheetSize;
+};
+
+class TabledMaterialData : public ImageMaterialData {};
+class TabledMaterial : public QSGSimpleMaterialShader<TabledMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(TabledMaterial, TabledMaterialData)
+
+public:
+ TabledMaterial()
+ {
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vertexShaderCode;
+
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + fragmentShaderCode;
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<TabledMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ program()->setUniformValue("colortable", 1);
+ glFuncs = QOpenGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("opacitytable");
+ }
+
+ void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
+
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, UNIFORM_ARRAY_SIZE, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
+ }
+
+ int m_entry_id;
+ int m_timestamp_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QOpenGLFunctions* glFuncs;
+};
+
+class DeformableMaterialData : public ImageMaterialData {};
+class DeformableMaterial : public QSGSimpleMaterialShader<DeformableMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(DeformableMaterial, DeformableMaterialData)
+
+public:
+ DeformableMaterial()
+ {
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + vertexShaderCode;
+
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + fragmentShaderCode;
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QOpenGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_entry_id;
+ int m_timestamp_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QOpenGLFunctions* glFuncs;
+};
+
+class SpriteMaterialData : public ImageMaterialData {};
+class SpriteMaterial : public QSGSimpleMaterialShader<SpriteMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(SpriteMaterial, SpriteMaterialData)
+
+public:
+ SpriteMaterial()
+ {
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vertexShaderCode;
+
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + fragmentShaderCode;
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation" << "vAnimData" << "vAnimPos";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ program()->setUniformValue("colortable", 1);
+ glFuncs = QOpenGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_animsize_id = program()->uniformLocation("animSheetSize");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("opacitytable");
+ }
+
+ void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
+
+ // make sure we end by setting GL_TEXTURE0 as active texture
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_animsize_id, d->animSheetSize);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, 64, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
+ }
+
+ int m_timestamp_id;
+ int m_animsize_id;
+ int m_entry_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QOpenGLFunctions* glFuncs;
+};
+
+class ColoredMaterialData : public ImageMaterialData {};
+class ColoredMaterial : public QSGSimpleMaterialShader<ColoredMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(ColoredMaterial, ColoredMaterialData)
+
+public:
+ ColoredMaterial()
+ {
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + vertexShaderCode;
+
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + fragmentShaderCode;
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ void activate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::activate();
+#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ void deactivate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::deactivate();
+#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec" << "vColor";
+ }
+
+ void initialize() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QOpenGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_timestamp_id;
+ int m_entry_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QOpenGLFunctions* glFuncs;
+};
+
+class SimpleMaterialData : public ImageMaterialData {};
+class SimpleMaterial : public QSGSimpleMaterialShader<SimpleMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(SimpleMaterial, SimpleMaterialData)
+
+public:
+ SimpleMaterial()
+ {
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + vertexShaderCode;
+
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + fragmentShaderCode;
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ void activate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::activate();
+#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ void deactivate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::deactivate();
+#if !defined(QT_OPENGL_ES_2) && !defined(Q_OS_WIN)
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec";
+ }
+
+ void initialize() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QOpenGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_timestamp_id;
+ int m_entry_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QOpenGLFunctions* glFuncs;
+};
+
+void fillUniformArrayFromImage(float* array, const QImage& img, int size)
+{
+ if (img.isNull()){
+ for (int i=0; i<size; i++)
+ array[i] = 1.0;
+ return;
+ }
+ QImage scaled = img.scaled(size,1);
+ for (int i=0; i<size; i++)
+ array[i] = qAlpha(scaled.pixel(i,0))/255.0;
+}
+
+/*!
+ \qmlclass ImageParticle QQuickImageParticle
+ \inqmlmodule QtQuick.Particles 2
+ \inherits ParticlePainter
+ \brief The ImageParticle element visualizes logical particles using an image
+
+ This element renders a logical particle as an image. The image can be
+ \list
+ \o colorized
+ \o rotated
+ \o deformed
+ \o a sprite-based animation
+ \endlist
+
+ ImageParticles implictly share data on particles if multiple ImageParticles are painting
+ the same logical particle group. This is broken down along the four capabilities listed
+ above. So if one ImageParticle defines data for rendering the particles in one of those
+ capabilities, and the other does not, then both will draw the particles the same in that
+ aspect automatically. This is primarily useful when there is some random variation on
+ the particle which is supposed to stay with it when switching painters. If both ImageParticles
+ define how they should appear for that aspect, they diverge and each appears as it is defined.
+
+ This sharing of data happens behind the scenes based off of whether properties were implicitly or explicitly
+ set. One drawback of the current implementation is that it is only possible to reset the capabilities as a whole.
+ So if you explicity set an attribute affecting color, such as redVariation, and then reset it (by setting redVariation
+ to undefined), all color data will be reset and it will begin to have an implicit value of any shared color from
+ other ImageParticles.
+*/
+/*!
+ \qmlproperty url QtQuick.Particles2::ImageParticle::source
+
+ The source image to be used.
+
+ If the image is a sprite animation, use the sprite property instead.
+*/
+/*!
+ \qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
+
+ The sprite or sprites used to draw this particle.
+
+ Note that the sprite image will be scaled to a square based on the size of
+ the particle being rendered.
+*/
+/*!
+ \qmlproperty url QtQuick.Particles2::ImageParticle::colorTable
+
+ An image whose color will be used as a 1D texture to determine color over life. E.g. when
+ the particle is halfway through its lifetime, it will have the color specified halfway
+ across the image.
+
+ This color is blended with the color property and the color of the source image.
+*/
+/*!
+ \qmlproperty url QtQuick.Particles2::ImageParticle::sizeTable
+
+ An image whose opacity will be used as a 1D texture to determine size over life.
+
+ This property is expected to be removed shortly, in favor of custom easing curves to determine size over life.
+*/
+/*!
+ \qmlproperty url QtQuick.Particles2::ImageParticle::opacityTable
+
+ An image whose opacity will be used as a 1D texture to determine size over life.
+
+ This property is expected to be removed shortly, in favor of custom easing curves to determine opacity over life.
+*/
+/*!
+ \qmlproperty color QtQuick.Particles2::ImageParticle::color
+
+ If a color is specified, the provided image will be colorized with it.
+
+ Default is white (no change).
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::colorVariation
+
+ This number represents the color variation applied to individual particles.
+ Setting colorVariation is the same as setting redVariation, greenVariation,
+ and blueVariation to the same number.
+
+ Each channel can vary between particle by up to colorVariation from its usual color.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::redVariation
+ The variation in the red color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::greenVariation
+ The variation in the green color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::blueVariation
+ The variation in the blue color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::alpha
+ An alpha to be applied to the image. This value is multiplied by the value in
+ the image, and the value in the color property.
+
+ Particles have additive blending, so lower alpha on single particles leads
+ to stronger effects when multiple particles overlap.
+
+ Alpha is measured from 0.0 to 1.0.
+
+ Default is 1.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::alphaVariation
+ The variation in the alpha channel between particles.
+
+ Alpha is measured from 0.0 to 1.0.
+
+ Default is 0.0
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::rotation
+
+ If set the image will be rotated by this many degrees before it is drawn.
+
+ The particle coordinates are not transformed.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::rotationVariation
+
+ If set the rotation of individual particles will vary by up to this much
+ between particles.
+
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeed
+
+ If set particles will rotate at this speed in degrees/second.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeedVariation
+
+ If set the rotationSpeed of individual particles will vary by up to this much
+ between particles.
+
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::ImageParticle::autoRotation
+
+ If set to true then a rotation will be applied on top of the particles rotation, so
+ that it faces the direction of travel. So to face away from the direction of travel,
+ set autoRotation to true and rotation to 180.
+
+ Default is false
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::xVector
+
+ Allows you to deform the particle image when drawn. The rectangular image will
+ be deformed so that the horizontal sides are in the shape of this vector instead
+ of (1,0).
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::yVector
+
+ Allows you to deform the particle image when drawn. The rectangular image will
+ be deformed so that the vertical sides are in the shape of this vector instead
+ of (0,1).
+*/
+/*!
+ \qmlproperty EntryEffect QtQuick.Particles2::ImageParticle::entryEffect
+
+ This property provides basic and cheap entrance and exit effects for the particles.
+ For fine-grained control, see sizeTable and opacityTable.
+
+ Acceptable values are
+ \list
+ \o None: Particles just appear and disappear.
+ \o Fade: Particles fade in from 0 opacity at the start of their life, and fade out to 0 at the end.
+ \o Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end.
+ \endlist
+
+ Default value is Fade.
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::ImageParticle::spritesInterpolate
+
+ If set to true, sprite particles will interpolate between sprite frames each rendered frame, making
+ the sprites look smoother.
+
+ Default is true.
+*/
+
+
+QQuickImageParticle::QQuickImageParticle(QQuickItem* parent)
+ : QQuickParticlePainter(parent)
+ , m_color_variation(0.0)
+ , m_rootNode(0)
+ , m_material(0)
+ , m_alphaVariation(0.0)
+ , m_alpha(1.0)
+ , m_redVariation(0.0)
+ , m_greenVariation(0.0)
+ , m_blueVariation(0.0)
+ , m_rotation(0)
+ , m_rotationVariation(0)
+ , m_rotationSpeed(0)
+ , m_rotationSpeedVariation(0)
+ , m_autoRotation(false)
+ , m_xVector(0)
+ , m_yVector(0)
+ , m_spriteEngine(0)
+ , m_spritesInterpolate(true)
+ , m_explicitColor(false)
+ , m_explicitRotation(false)
+ , m_explicitDeformation(false)
+ , m_explicitAnimation(false)
+ , m_bloat(false)
+ , perfLevel(Unknown)
+ , m_lastLevel(Unknown)
+ , m_debugMode(false)
+ , m_entryEffect(Fade)
+{
+ setFlag(ItemHasContents);
+ m_debugMode = qmlParticlesDebug();
+}
+
+QQuickImageParticle::~QQuickImageParticle()
+{
+}
+
+QDeclarativeListProperty<QQuickSprite> QQuickImageParticle::sprites()
+{
+ return QDeclarativeListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
+}
+
+void QQuickImageParticle::setImage(const QUrl &image)
+{
+ if (image == m_image_name)
+ return;
+ m_image_name = image;
+ emit imageChanged();
+ reset();
+}
+
+
+void QQuickImageParticle::setColortable(const QUrl &table)
+{
+ if (table == m_colortable_name)
+ return;
+ m_colortable_name = table;
+ emit colortableChanged();
+ reset();
+}
+
+void QQuickImageParticle::setSizetable(const QUrl &table)
+{
+ if (table == m_sizetable_name)
+ return;
+ m_sizetable_name = table;
+ emit sizetableChanged();
+ reset();
+}
+
+void QQuickImageParticle::setOpacitytable(const QUrl &table)
+{
+ if (table == m_opacitytable_name)
+ return;
+ m_opacitytable_name = table;
+ emit opacitytableChanged();
+ reset();
+}
+
+void QQuickImageParticle::setColor(const QColor &color)
+{
+ if (color == m_color)
+ return;
+ m_color = color;
+ emit colorChanged();
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setColorVariation(qreal var)
+{
+ if (var == m_color_variation)
+ return;
+ m_color_variation = var;
+ emit colorVariationChanged();
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setAlphaVariation(qreal arg)
+{
+ if (m_alphaVariation != arg) {
+ m_alphaVariation = arg;
+ emit alphaVariationChanged(arg);
+ }
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setAlpha(qreal arg)
+{
+ if (m_alpha != arg) {
+ m_alpha = arg;
+ emit alphaChanged(arg);
+ }
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setRedVariation(qreal arg)
+{
+ if (m_redVariation != arg) {
+ m_redVariation = arg;
+ emit redVariationChanged(arg);
+ }
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setGreenVariation(qreal arg)
+{
+ if (m_greenVariation != arg) {
+ m_greenVariation = arg;
+ emit greenVariationChanged(arg);
+ }
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setBlueVariation(qreal arg)
+{
+ if (m_blueVariation != arg) {
+ m_blueVariation = arg;
+ emit blueVariationChanged(arg);
+ }
+ m_explicitColor = true;
+ if (perfLevel < Colored)
+ reset();
+}
+
+void QQuickImageParticle::setRotation(qreal arg)
+{
+ if (m_rotation != arg) {
+ m_rotation = arg;
+ emit rotationChanged(arg);
+ }
+ m_explicitRotation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setRotationVariation(qreal arg)
+{
+ if (m_rotationVariation != arg) {
+ m_rotationVariation = arg;
+ emit rotationVariationChanged(arg);
+ }
+ m_explicitRotation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setRotationSpeed(qreal arg)
+{
+ if (m_rotationSpeed != arg) {
+ m_rotationSpeed = arg;
+ emit rotationSpeedChanged(arg);
+ }
+ m_explicitRotation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setRotationSpeedVariation(qreal arg)
+{
+ if (m_rotationSpeedVariation != arg) {
+ m_rotationSpeedVariation = arg;
+ emit rotationSpeedVariationChanged(arg);
+ }
+ m_explicitRotation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setAutoRotation(bool arg)
+{
+ if (m_autoRotation != arg) {
+ m_autoRotation = arg;
+ emit autoRotationChanged(arg);
+ }
+ m_explicitRotation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setXVector(QQuickDirection* arg)
+{
+ if (m_xVector != arg) {
+ m_xVector = arg;
+ emit xVectorChanged(arg);
+ }
+ m_explicitDeformation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setYVector(QQuickDirection* arg)
+{
+ if (m_yVector != arg) {
+ m_yVector = arg;
+ emit yVectorChanged(arg);
+ }
+ m_explicitDeformation = true;
+ if (perfLevel < Deformable)
+ reset();
+}
+
+void QQuickImageParticle::setSpritesInterpolate(bool arg)
+{
+ if (m_spritesInterpolate != arg) {
+ m_spritesInterpolate = arg;
+ emit spritesInterpolateChanged(arg);
+ }
+}
+
+void QQuickImageParticle::setBloat(bool arg)
+{
+ if (m_bloat != arg) {
+ m_bloat = arg;
+ emit bloatChanged(arg);
+ }
+ if (perfLevel < 9999)
+ reset();
+}
+
+void QQuickImageParticle::setEntryEffect(EntryEffect arg)
+{
+ if (m_entryEffect != arg) {
+ m_entryEffect = arg;
+ if (m_material)
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ emit entryEffectChanged(arg);
+ }
+}
+
+void QQuickImageParticle::resetColor()
+{
+ m_explicitColor = false;
+ foreach (const QString &str, m_groups)
+ foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
+ if (d->colorOwner == this)
+ d->colorOwner = 0;
+ m_color = QColor();
+ m_color_variation = 0.0f;
+ m_redVariation = 0.0f;
+ m_blueVariation = 0.0f;
+ m_greenVariation = 0.0f;
+ m_alpha = 1.0f;
+ m_alphaVariation = 0.0f;
+}
+
+void QQuickImageParticle::resetRotation()
+{
+ m_explicitRotation = false;
+ foreach (const QString &str, m_groups)
+ foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
+ if (d->rotationOwner == this)
+ d->rotationOwner = 0;
+ m_rotation = 0;
+ m_rotationVariation = 0;
+ m_rotationSpeed = 0;
+ m_rotationSpeedVariation = 0;
+ m_autoRotation = false;
+}
+
+void QQuickImageParticle::resetDeformation()
+{
+ m_explicitDeformation = false;
+ foreach (const QString &str, m_groups)
+ foreach (QQuickParticleData* d, m_system->groupData[m_system->groupIds[str]]->data)
+ if (d->deformationOwner == this)
+ d->deformationOwner = 0;
+ if (m_xVector)
+ delete m_xVector;
+ if (m_yVector)
+ delete m_yVector;
+ m_xVector = 0;
+ m_yVector = 0;
+}
+
+void QQuickImageParticle::reset()
+{
+ QQuickParticlePainter::reset();
+ m_pleaseReset = true;
+ update();
+}
+
+void QQuickImageParticle::createEngine()
+{
+ if (m_spriteEngine)
+ delete m_spriteEngine;
+ if (m_sprites.count()) {
+ m_spriteEngine = new QQuickSpriteEngine(m_sprites, this);
+ connect(m_spriteEngine, SIGNAL(stateChanged(int)),
+ this, SLOT(spriteAdvance(int)));
+ m_explicitAnimation = true;
+ } else {
+ m_spriteEngine = 0;
+ m_explicitAnimation = false;
+ }
+ reset();
+}
+
+static QSGGeometry::Attribute SimpleParticle_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
+ QSGGeometry::Attribute::create(1, 4, GL_FLOAT), // Data
+ QSGGeometry::Attribute::create(2, 4, GL_FLOAT) // Vectors
+};
+
+static QSGGeometry::AttributeSet SimpleParticle_AttributeSet =
+{
+ 3, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float),
+ SimpleParticle_Attributes
+};
+
+static QSGGeometry::Attribute ColoredParticle_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
+ QSGGeometry::Attribute::create(1, 4, GL_FLOAT), // Data
+ QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Vectors
+ QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE), // Colors
+};
+
+static QSGGeometry::AttributeSet ColoredParticle_AttributeSet =
+{
+ 4, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float) + 4 * sizeof(uchar),
+ ColoredParticle_Attributes
+};
+
+static QSGGeometry::Attribute DeformableParticle_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
+ QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
+ QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // Colors
+ QSGGeometry::Attribute::create(5, 4, GL_FLOAT), // DeformationVectors
+ QSGGeometry::Attribute::create(6, 3, GL_FLOAT), // Rotation
+};
+
+static QSGGeometry::AttributeSet DeformableParticle_AttributeSet =
+{
+ 7, // Attribute Count
+ (2 + 2 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
+ DeformableParticle_Attributes
+};
+
+static QSGGeometry::Attribute SpriteParticle_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
+ QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data
+ QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors
+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // Colors
+ QSGGeometry::Attribute::create(5, 4, GL_FLOAT), // DeformationVectors
+ QSGGeometry::Attribute::create(6, 3, GL_FLOAT), // Rotation
+ QSGGeometry::Attribute::create(7, 4, GL_FLOAT), // Anim Data
+ QSGGeometry::Attribute::create(8, 4, GL_FLOAT) // Anim Pos
+};
+
+static QSGGeometry::AttributeSet SpriteParticle_AttributeSet =
+{
+ 9, // Attribute Count
+ (2 + 2 + 4 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
+ SpriteParticle_Attributes
+};
+
+void QQuickImageParticle::clearShadows()
+{
+ foreach (const QVector<QQuickParticleData*> data, m_shadowData)
+ qDeleteAll(data);
+ m_shadowData.clear();
+}
+
+//Only call if you need to, may initialize the whole array first time
+QQuickParticleData* QQuickImageParticle::getShadowDatum(QQuickParticleData* datum)
+{
+ QQuickParticleGroupData* gd = m_system->groupData[datum->group];
+ if (!m_shadowData.contains(datum->group)) {
+ QVector<QQuickParticleData*> data;
+ for (int i=0; i<gd->size(); i++){
+ QQuickParticleData* datum = new QQuickParticleData(m_system);
+ *datum = *(gd->data[i]);
+ data << datum;
+ }
+ m_shadowData.insert(datum->group, data);
+ }
+ //### If dynamic resize is added, remember to potentially resize the shadow data on out-of-bounds access request
+
+ return m_shadowData[datum->group][datum->index];
+}
+
+QSGGeometryNode* QQuickImageParticle::buildParticleNodes()
+{
+#ifdef QT_OPENGL_ES_2
+ if (m_count * 4 > 0xffff) {
+ printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort
+ return 0;
+ }
+#endif
+
+ if (count() <= 0)
+ return 0;
+
+ if (m_sprites.count() || m_bloat) {
+ perfLevel = Sprites;
+ } else if (!m_colortable_name.isEmpty() || !m_sizetable_name.isEmpty()
+ || !m_opacitytable_name.isEmpty()) {
+ perfLevel = Tabled;
+ } else if (m_autoRotation || m_rotation || m_rotationVariation
+ || m_rotationSpeed || m_rotationSpeedVariation
+ || m_xVector || m_yVector) {
+ perfLevel = Deformable;
+ } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid() || m_color_variation
+ || m_redVariation || m_blueVariation || m_greenVariation) {
+ perfLevel = Colored;
+ } else {
+ perfLevel = Simple;
+ }
+
+ foreach (const QString &str, m_groups){//For sharing higher levels, need to have highest used so it renders
+ int gIdx = m_system->groupIds[str];
+ foreach (QQuickParticlePainter* p, m_system->groupData[gIdx]->painters){
+ QQuickImageParticle* other = qobject_cast<QQuickImageParticle*>(p);
+ if (other){
+ if (other->perfLevel > perfLevel) {
+ if (other->perfLevel >= Tabled){//Deformable is the highest level needed for this, anything higher isn't shared (or requires your own sprite)
+ if (perfLevel < Deformable)
+ perfLevel = Deformable;
+ } else {
+ perfLevel = other->perfLevel;
+ }
+ } else if (other->perfLevel < perfLevel) {
+ other->reset();
+ }
+ }
+ }
+ }
+
+ if (perfLevel >= Colored && !m_color.isValid())
+ m_color = QColor(Qt::white);//Hidden default, but different from unset
+
+ QImage image;
+ if (perfLevel >= Sprites){
+ if (!m_spriteEngine) {
+ qWarning() << "ImageParticle: No sprite engine...";
+ return 0;
+ }
+ image = m_spriteEngine->assembledImage();
+ if (image.isNull())//Warning is printed in engine
+ return 0;
+ } else {
+ image = QImage(m_image_name.toLocalFile());
+ if (image.isNull()) {
+ printf("ImageParticle: loading image failed '%s'\n", qPrintable(m_image_name.toLocalFile()));
+ return 0;
+ }
+ }
+
+ clearShadows();
+ if (m_material)
+ m_material = 0;
+
+ //Setup material
+ QImage colortable;
+ QImage sizetable;
+ QImage opacitytable;
+ switch (perfLevel) {//Fallthrough intended
+ case Sprites:
+ m_material = SpriteMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->animSheetSize = QSizeF(image.size());
+ m_spriteEngine->setCount(m_count);
+ case Tabled:
+ if (!m_material)
+ m_material = TabledMaterial::createMaterial();
+ colortable = QImage(m_colortable_name.toLocalFile());
+ sizetable = QImage(m_sizetable_name.toLocalFile());
+ opacitytable = QImage(m_opacitytable_name.toLocalFile());
+ if (colortable.isNull()){
+ colortable = QImage(1,1,QImage::Format_ARGB32);
+ colortable.fill(Qt::white);
+ }
+ Q_ASSERT(!colortable.isNull());
+ getState<ImageMaterialData>(m_material)->colorTable = QSGPlainTexture::fromImage(colortable);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->sizeTable, sizetable, UNIFORM_ARRAY_SIZE);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->opacityTable, opacitytable, UNIFORM_ARRAY_SIZE);
+ case Deformable:
+ if (!m_material)
+ m_material = DeformableMaterial::createMaterial();
+ case Colored:
+ if (!m_material)
+ m_material = ColoredMaterial::createMaterial();
+ default://Also Simple
+ if (!m_material)
+ m_material = SimpleMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->texture = QSGPlainTexture::fromImage(image);
+ getState<ImageMaterialData>(m_material)->texture->setFiltering(QSGTexture::Linear);
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ m_material->setFlag(QSGMaterial::Blending);
+ }
+
+ foreach (const QString &str, m_groups){
+ int gIdx = m_system->groupIds[str];
+ int count = m_system->groupData[gIdx]->size();
+ QSGGeometryNode* node = new QSGGeometryNode();
+ node->setMaterial(m_material);
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ m_nodes.insert(gIdx, node);
+ m_idxStarts.insert(gIdx, m_lastIdxStart);
+ m_startsIdx.append(qMakePair<int,int>(m_lastIdxStart, gIdx));
+ m_lastIdxStart += count;
+
+ //Create Particle Geometry
+ int vCount = count * 4;
+ int iCount = count * 6;
+
+ QSGGeometry *g;
+ if (perfLevel == Sprites)
+ g = new QSGGeometry(SpriteParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Tabled)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Deformable)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Colored)
+ g = new QSGGeometry(ColoredParticle_AttributeSet, count, 0);
+ else //Simple
+ g = new QSGGeometry(SimpleParticle_AttributeSet, count, 0);
+
+ node->setGeometry(g);
+ if (perfLevel <= Colored){
+ g->setDrawingMode(GL_POINTS);
+ if (m_debugMode){
+ GLfloat pointSizeRange[2];
+ glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+ qDebug() << "Using point sprites, GL_ALIASED_POINT_SIZE_RANGE " <<pointSizeRange[0] << ":" << pointSizeRange[1];
+ }
+ }else
+ g->setDrawingMode(GL_TRIANGLES);
+
+ for (int p=0; p < count; ++p)
+ commit(gIdx, p);//commit sets geometry for the node, has its own perfLevel switch
+
+ if (perfLevel == Sprites)
+ initTexCoords<SpriteVertex>((SpriteVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Tabled)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Deformable)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+
+ if (perfLevel > Colored){
+ quint16 *indices = g->indexDataAsUShort();
+ for (int i=0; i < count; ++i) {
+ int o = i * 4;
+ indices[0] = o;
+ indices[1] = o + 1;
+ indices[2] = o + 2;
+ indices[3] = o + 1;
+ indices[4] = o + 3;
+ indices[5] = o + 2;
+ indices += 6;
+ }
+ }
+
+ }
+
+ foreach (QSGGeometryNode* node, m_nodes){
+ if (node == *(m_nodes.begin()))
+ node->setFlag(QSGGeometryNode::OwnsMaterial);//Root node owns the material for memory management purposes
+ else
+ (*(m_nodes.begin()))->appendChildNode(node);
+ }
+
+ return *(m_nodes.begin());
+}
+
+QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
+{
+ if (m_pleaseReset){
+ m_lastLevel = perfLevel;
+
+ delete m_rootNode;//Automatically deletes children, and SG manages material lifetime
+ m_rootNode = 0;
+ m_nodes.clear();
+
+ m_idxStarts.clear();
+ m_startsIdx.clear();
+ m_lastIdxStart = 0;
+
+ m_material = 0;
+
+ m_pleaseReset = false;
+ }
+
+ if (m_system && m_system->isRunning() && !m_system->isPaused()){
+ prepareNextFrame();
+ if (m_rootNode) {
+ update();
+ foreach (QSGGeometryNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyGeometry);
+ }
+ }
+
+ return m_rootNode;
+}
+
+void QQuickImageParticle::prepareNextFrame()
+{
+ if (m_rootNode == 0){//TODO: Staggered loading (as emitted)
+ m_rootNode = buildParticleNodes();
+ if (m_rootNode == 0)
+ return;
+ if (m_debugMode) {
+ qDebug() << "QQuickImageParticle Feature level: " << perfLevel;
+ qDebug() << "QQuickImageParticle Nodes: ";
+ int count = 0;
+ foreach (int i, m_nodes.keys()) {
+ qDebug() << "Group " << i << " (" << m_system->groupData[i]->size() << " particles)";
+ count += m_system->groupData[i]->size();
+ }
+ qDebug() << "Total count: " << count;
+ }
+ }
+ qint64 timeStamp = m_system->systemSync(this);
+
+ qreal time = timeStamp / 1000.;
+
+ switch (perfLevel){//Fall-through intended
+ case Sprites:
+ //Advance State
+ m_spriteEngine->updateSprites(timeStamp);
+ case Tabled:
+ case Deformable:
+ case Colored:
+ case Simple:
+ default: //Also Simple
+ getState<ImageMaterialData>(m_material)->timestamp = time;
+ break;
+ }
+
+ foreach (QSGGeometryNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyMaterial);
+}
+
+void QQuickImageParticle::spriteAdvance(int spriteIdx)
+{
+ if (!m_startsIdx.count())//Probably overly defensive
+ return;
+
+ int gIdx = -1;
+ int i;
+ for (i = 0; i<m_startsIdx.count(); i++) {
+ if (spriteIdx < m_startsIdx[i].first) {
+ gIdx = m_startsIdx[i-1].second;
+ break;
+ }
+ }
+ if (gIdx == -1)
+ gIdx = m_startsIdx[i-1].second;
+ int pIdx = spriteIdx - m_startsIdx[i-1].first;
+
+ QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
+ QQuickParticleData* d = (datum->animationOwner == this ? datum : getShadowDatum(datum));
+
+ d->animIdx = m_spriteEngine->spriteState(spriteIdx);
+ Vertices<SpriteVertex>* particles = (Vertices<SpriteVertex> *) m_nodes[gIdx]->geometry()->vertexData();
+ Vertices<SpriteVertex> &p = particles[pIdx];
+ d->animT = p.v1.animT = p.v2.animT = p.v3.animT = p.v4.animT = m_spriteEngine->spriteStart(spriteIdx)/1000.0;
+ d->frameCount = p.v1.frameCount = p.v2.frameCount = p.v3.frameCount = p.v4.frameCount = m_spriteEngine->spriteFrames(spriteIdx);
+ d->frameDuration = p.v1.frameDuration = p.v2.frameDuration = p.v3.frameDuration = p.v4.frameDuration = m_spriteEngine->spriteDuration(spriteIdx);
+ d->animX = p.v1.animX = p.v2.animX = p.v3.animX = p.v4.animX = m_spriteEngine->spriteX(spriteIdx);
+ d->animY = p.v1.animY = p.v2.animY = p.v3.animY = p.v4.animY = m_spriteEngine->spriteY(spriteIdx);
+ d->animWidth = p.v1.animWidth = p.v2.animWidth = p.v3.animWidth = p.v4.animWidth = m_spriteEngine->spriteWidth(spriteIdx);
+ d->animHeight = p.v1.animHeight = p.v2.animHeight = p.v3.animHeight = p.v4.animHeight = m_spriteEngine->spriteHeight(spriteIdx);
+}
+
+void QQuickImageParticle::reloadColor(const Color4ub &c, QQuickParticleData* d)
+{
+ d->color = c;
+ //TODO: get index for reload - or make function take an index
+}
+
+void QQuickImageParticle::initialize(int gIdx, int pIdx)
+{
+ Color4ub color;
+ QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
+ qreal redVariation = m_color_variation + m_redVariation;
+ qreal greenVariation = m_color_variation + m_greenVariation;
+ qreal blueVariation = m_color_variation + m_blueVariation;
+ int spriteIdx = 0;
+ if (m_spriteEngine) {
+ spriteIdx = m_idxStarts[gIdx] + datum->index;
+ if (spriteIdx >= m_spriteEngine->count())
+ m_spriteEngine->setCount(spriteIdx+1);
+ }
+
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;
+ switch (perfLevel){//Fall-through is intended on all of them
+ case Sprites:
+ // Initial Sprite State
+ if (m_explicitAnimation){
+ if (!datum->animationOwner)
+ datum->animationOwner = this;
+ QQuickParticleData* writeTo = (datum->animationOwner == this ? datum : getShadowDatum(datum));
+ writeTo->animT = writeTo->t;
+ //writeTo->animInterpolate = m_spritesInterpolate;
+ if (m_spriteEngine){
+ m_spriteEngine->start(spriteIdx);
+ writeTo->frameCount = m_spriteEngine->spriteFrames(spriteIdx);
+ writeTo->frameDuration = m_spriteEngine->spriteDuration(spriteIdx);
+ writeTo->animX = m_spriteEngine->spriteX(spriteIdx);
+ writeTo->animY = m_spriteEngine->spriteY(spriteIdx);
+ writeTo->animWidth = m_spriteEngine->spriteWidth(spriteIdx);
+ writeTo->animHeight = m_spriteEngine->spriteHeight(spriteIdx);
+ }else{
+ writeTo->frameCount = 1;
+ writeTo->frameDuration = 9999;
+ writeTo->animX = writeTo->animY = 0;
+ writeTo->animWidth = writeTo->animHeight = 1;
+ }
+ }
+ case Tabled:
+ case Deformable:
+ //Initial Rotation
+ if (m_explicitDeformation){
+ if (!datum->deformationOwner)
+ datum->deformationOwner = this;
+ if (m_xVector){
+ const QPointF &ret = m_xVector->sample(QPointF(datum->x, datum->y));
+ if (datum->deformationOwner == this) {
+ datum->xx = ret.x();
+ datum->xy = ret.y();
+ } else {
+ getShadowDatum(datum)->xx = ret.x();
+ getShadowDatum(datum)->xy = ret.y();
+ }
+ }
+ if (m_yVector){
+ const QPointF &ret = m_yVector->sample(QPointF(datum->x, datum->y));
+ if (datum->deformationOwner == this) {
+ datum->yx = ret.x();
+ datum->yy = ret.y();
+ } else {
+ getShadowDatum(datum)->yx = ret.x();
+ getShadowDatum(datum)->yy = ret.y();
+ }
+ }
+ }
+
+ if (m_explicitRotation){
+ if (!datum->rotationOwner)
+ datum->rotationOwner = this;
+ rotation =
+ (m_rotation + (m_rotationVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationVariation) ) * CONV;
+ rotationSpeed =
+ (m_rotationSpeed + (m_rotationSpeedVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationSpeedVariation) ) * CONV;
+ autoRotate = m_autoRotation?1.0:0.0;
+ if (datum->rotationOwner == this) {
+ datum->rotation = rotation;
+ datum->rotationSpeed = rotationSpeed;
+ datum->autoRotate = autoRotate;
+ } else {
+ getShadowDatum(datum)->rotation = rotation;
+ getShadowDatum(datum)->rotationSpeed = rotationSpeed;
+ getShadowDatum(datum)->autoRotate = autoRotate;
+ }
+ }
+ case Colored:
+ //Color initialization
+ // Particle color
+ if (m_explicitColor) {
+ if (!datum->colorOwner)
+ datum->colorOwner = this;
+ color.r = m_color.red() * (1 - redVariation) + rand() % 256 * redVariation;
+ color.g = m_color.green() * (1 - greenVariation) + rand() % 256 * greenVariation;
+ color.b = m_color.blue() * (1 - blueVariation) + rand() % 256 * blueVariation;
+ color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + rand() % 256 * m_alphaVariation;
+ if (datum->colorOwner == this)
+ datum->color = color;
+ else
+ getShadowDatum(datum)->color = color;
+ }
+ default:
+ break;
+ }
+}
+
+void QQuickImageParticle::commit(int gIdx, int pIdx)
+{
+ if (m_pleaseReset)
+ return;
+ QSGGeometryNode *node = m_nodes[gIdx];
+ if (!node)
+ return;
+ QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx];
+ node->setFlag(QSGNode::OwnsGeometry, false);
+ SpriteVertex *spriteVertices = (SpriteVertex *) node->geometry()->vertexData();
+ DeformableVertex *deformableVertices = (DeformableVertex *) node->geometry()->vertexData();
+ ColoredVertex *coloredVertices = (ColoredVertex *) node->geometry()->vertexData();
+ SimpleVertex *simpleVertices = (SimpleVertex *) node->geometry()->vertexData();
+ switch (perfLevel){//No automatic fall through intended on this one
+ case Sprites:
+ spriteVertices += pIdx*4;
+ for (int i=0; i<4; i++){
+ spriteVertices[i].x = datum->x - m_systemOffset.x();
+ spriteVertices[i].y = datum->y - m_systemOffset.y();
+ spriteVertices[i].t = datum->t;
+ spriteVertices[i].lifeSpan = datum->lifeSpan;
+ spriteVertices[i].size = datum->size;
+ spriteVertices[i].endSize = datum->endSize;
+ spriteVertices[i].vx = datum->vx;
+ spriteVertices[i].vy = datum->vy;
+ spriteVertices[i].ax = datum->ax;
+ spriteVertices[i].ay = datum->ay;
+ if (m_explicitDeformation && datum->deformationOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ spriteVertices[i].xx = shadow->xx;
+ spriteVertices[i].xy = shadow->xy;
+ spriteVertices[i].yx = shadow->yx;
+ spriteVertices[i].yy = shadow->yy;
+ } else {
+ spriteVertices[i].xx = datum->xx;
+ spriteVertices[i].xy = datum->xy;
+ spriteVertices[i].yx = datum->yx;
+ spriteVertices[i].yy = datum->yy;
+ }
+ if (m_explicitRotation && datum->rotationOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ spriteVertices[i].rotation = shadow->rotation;
+ spriteVertices[i].rotationSpeed = shadow->rotationSpeed;
+ spriteVertices[i].autoRotate = shadow->autoRotate;
+ } else {
+ spriteVertices[i].rotation = datum->rotation;
+ spriteVertices[i].rotationSpeed = datum->rotationSpeed;
+ spriteVertices[i].autoRotate = datum->autoRotate;
+ }
+ spriteVertices[i].animInterpolate = m_spritesInterpolate ? 1.0 : 0.0;//### Shadow? In particleData? Or uniform?
+ if (m_explicitAnimation && datum->animationOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ spriteVertices[i].frameDuration = shadow->frameDuration;
+ spriteVertices[i].frameCount = shadow->frameCount;
+ spriteVertices[i].animT = shadow->animT;
+ spriteVertices[i].animX = shadow->animX;
+ spriteVertices[i].animY = shadow->animY;
+ spriteVertices[i].animWidth = shadow->animWidth;
+ spriteVertices[i].animHeight = shadow->animHeight;
+ } else {
+ spriteVertices[i].frameDuration = datum->frameDuration;
+ spriteVertices[i].frameCount = datum->frameCount;
+ spriteVertices[i].animT = datum->animT;
+ spriteVertices[i].animX = datum->animX;
+ spriteVertices[i].animY = datum->animY;
+ spriteVertices[i].animWidth = datum->animWidth;
+ spriteVertices[i].animHeight = datum->animHeight;
+ }
+ if (m_explicitColor && datum->colorOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ spriteVertices[i].color.r = shadow->color.r;
+ spriteVertices[i].color.g = shadow->color.g;
+ spriteVertices[i].color.b = shadow->color.b;
+ spriteVertices[i].color.a = shadow->color.a;
+ } else {
+ spriteVertices[i].color.r = datum->color.r;
+ spriteVertices[i].color.g = datum->color.g;
+ spriteVertices[i].color.b = datum->color.b;
+ spriteVertices[i].color.a = datum->color.a;
+ }
+ }
+ break;
+ case Tabled: //Fall through until it has its own vertex class
+ case Deformable:
+ deformableVertices += pIdx*4;
+ for (int i=0; i<4; i++){
+ deformableVertices[i].x = datum->x - m_systemOffset.x();
+ deformableVertices[i].y = datum->y - m_systemOffset.y();
+ deformableVertices[i].t = datum->t;
+ deformableVertices[i].lifeSpan = datum->lifeSpan;
+ deformableVertices[i].size = datum->size;
+ deformableVertices[i].endSize = datum->endSize;
+ deformableVertices[i].vx = datum->vx;
+ deformableVertices[i].vy = datum->vy;
+ deformableVertices[i].ax = datum->ax;
+ deformableVertices[i].ay = datum->ay;
+ if (m_explicitDeformation && datum->deformationOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ deformableVertices[i].xx = shadow->xx;
+ deformableVertices[i].xy = shadow->xy;
+ deformableVertices[i].yx = shadow->yx;
+ deformableVertices[i].yy = shadow->yy;
+ } else {
+ deformableVertices[i].xx = datum->xx;
+ deformableVertices[i].xy = datum->xy;
+ deformableVertices[i].yx = datum->yx;
+ deformableVertices[i].yy = datum->yy;
+ }
+ if (m_explicitRotation && datum->rotationOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ deformableVertices[i].rotation = shadow->rotation;
+ deformableVertices[i].rotationSpeed = shadow->rotationSpeed;
+ deformableVertices[i].autoRotate = shadow->autoRotate;
+ } else {
+ deformableVertices[i].rotation = datum->rotation;
+ deformableVertices[i].rotationSpeed = datum->rotationSpeed;
+ deformableVertices[i].autoRotate = datum->autoRotate;
+ }
+ if (m_explicitColor && datum->colorOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ deformableVertices[i].color.r = shadow->color.r;
+ deformableVertices[i].color.g = shadow->color.g;
+ deformableVertices[i].color.b = shadow->color.b;
+ deformableVertices[i].color.a = shadow->color.a;
+ } else {
+ deformableVertices[i].color.r = datum->color.r;
+ deformableVertices[i].color.g = datum->color.g;
+ deformableVertices[i].color.b = datum->color.b;
+ deformableVertices[i].color.a = datum->color.a;
+ }
+ }
+ break;
+ case Colored:
+ coloredVertices += pIdx*1;
+ for (int i=0; i<1; i++){
+ coloredVertices[i].x = datum->x - m_systemOffset.x();
+ coloredVertices[i].y = datum->y - m_systemOffset.y();
+ coloredVertices[i].t = datum->t;
+ coloredVertices[i].lifeSpan = datum->lifeSpan;
+ coloredVertices[i].size = datum->size;
+ coloredVertices[i].endSize = datum->endSize;
+ coloredVertices[i].vx = datum->vx;
+ coloredVertices[i].vy = datum->vy;
+ coloredVertices[i].ax = datum->ax;
+ coloredVertices[i].ay = datum->ay;
+ if (m_explicitColor && datum->colorOwner != this) {
+ QQuickParticleData* shadow = getShadowDatum(datum);
+ coloredVertices[i].color.r = shadow->color.r;
+ coloredVertices[i].color.g = shadow->color.g;
+ coloredVertices[i].color.b = shadow->color.b;
+ coloredVertices[i].color.a = shadow->color.a;
+ } else {
+ coloredVertices[i].color.r = datum->color.r;
+ coloredVertices[i].color.g = datum->color.g;
+ coloredVertices[i].color.b = datum->color.b;
+ coloredVertices[i].color.a = datum->color.a;
+ }
+ }
+ break;
+ case Simple:
+ simpleVertices += pIdx*1;
+ for (int i=0; i<1; i++){
+ simpleVertices[i].x = datum->x - m_systemOffset.x();
+ simpleVertices[i].y = datum->y - m_systemOffset.y();
+ simpleVertices[i].t = datum->t;
+ simpleVertices[i].lifeSpan = datum->lifeSpan;
+ simpleVertices[i].size = datum->size;
+ simpleVertices[i].endSize = datum->endSize;
+ simpleVertices[i].vx = datum->vx;
+ simpleVertices[i].vy = datum->vy;
+ simpleVertices[i].ax = datum->ax;
+ simpleVertices[i].ay = datum->ay;
+ }
+ break;
+ default:
+ break;
+ }
+
+ node->setFlag(QSGNode::OwnsGeometry, true);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickimageparticle_p.h b/src/quick/particles/qquickimageparticle_p.h
new file mode 100644
index 0000000000..61c24ed836
--- /dev/null
+++ b/src/quick/particles/qquickimageparticle_p.h
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 ULTRAPARTICLE_H
+#define ULTRAPARTICLE_H
+#include "qquickparticlepainter_p.h"
+#include "qquickdirection_p.h"
+#include <QDeclarativeListProperty>
+#include <QtQuick/qsgsimplematerial.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class ImageMaterialData;
+class QSGGeometryNode;
+
+class QQuickSprite;
+class QQuickStochasticEngine;
+
+struct SimpleVertex {
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+};
+
+struct ColoredVertex {
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+};
+
+struct DeformableVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assumed that GPUs prefer floats to bools
+};
+
+struct SpriteVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assumed that GPUs prefer floats to bools
+ float animInterpolate;
+ float frameDuration;
+ float frameCount;
+ float animT;
+ float animX;
+ float animY;
+ float animWidth;
+ float animHeight;
+};
+
+template <typename Vertex>
+struct Vertices {
+ Vertex v1;
+ Vertex v2;
+ Vertex v3;
+ Vertex v4;
+};
+
+class QQuickImageParticle : public QQuickParticlePainter
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ image WRITE setImage NOTIFY imageChanged)
+ Q_PROPERTY(QUrl colorTable READ colortable WRITE setColortable NOTIFY colortableChanged)
+ Q_PROPERTY(QUrl sizeTable READ sizetable WRITE setSizetable NOTIFY sizetableChanged)
+ Q_PROPERTY(QUrl opacityTable READ opacitytable WRITE setOpacitytable NOTIFY opacitytableChanged)
+
+ //###Now just colorize - add a flag for 'solid' color particles(where the img is just a mask?)?
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged RESET resetColor)
+ //Stacks (added) with individual colorVariations
+ Q_PROPERTY(qreal colorVariation READ colorVariation WRITE setColorVariation NOTIFY colorVariationChanged RESET resetColor)
+ Q_PROPERTY(qreal redVariation READ redVariation WRITE setRedVariation NOTIFY redVariationChanged RESET resetColor)
+ Q_PROPERTY(qreal greenVariation READ greenVariation WRITE setGreenVariation NOTIFY greenVariationChanged RESET resetColor)
+ Q_PROPERTY(qreal blueVariation READ blueVariation WRITE setBlueVariation NOTIFY blueVariationChanged RESET resetColor)
+ //Stacks (multiplies) with the Alpha in the color, mostly here so you can use svg color names (which have full alpha)
+ Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged RESET resetColor)
+ Q_PROPERTY(qreal alphaVariation READ alphaVariation WRITE setAlphaVariation NOTIFY alphaVariationChanged RESET resetColor)
+
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged RESET resetRotation)
+ Q_PROPERTY(qreal rotationVariation READ rotationVariation WRITE setRotationVariation NOTIFY rotationVariationChanged RESET resetRotation)
+ Q_PROPERTY(qreal rotationSpeed READ rotationSpeed WRITE setRotationSpeed NOTIFY rotationSpeedChanged RESET resetRotation)
+ Q_PROPERTY(qreal rotationSpeedVariation READ rotationSpeedVariation WRITE setRotationSpeedVariation NOTIFY rotationSpeedVariationChanged RESET resetRotation)
+ //If true, then will face the direction of motion. Stacks with rotation, e.g. setting rotation
+ //to 180 will lead to facing away from the direction of motion
+ Q_PROPERTY(bool autoRotation READ autoRotation WRITE setAutoRotation NOTIFY autoRotationChanged RESET resetRotation)
+
+ //###Call i/j? Makes more sense to those with vector calculus experience, and I could even add the cirumflex in QML?
+ //xVector is the vector from the top-left point to the top-right point, and is multiplied by current size
+ Q_PROPERTY(QQuickDirection* xVector READ xVector WRITE setXVector NOTIFY xVectorChanged RESET resetDeformation)
+ //yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
+ Q_PROPERTY(QQuickDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged RESET resetDeformation)
+ Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
+ Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged)
+
+ Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
+ Q_PROPERTY(bool bloat READ bloat WRITE setBloat NOTIFY bloatChanged)//Just a debugging property to bypass optimizations
+ Q_ENUMS(EntryEffect)
+public:
+ explicit QQuickImageParticle(QQuickItem *parent = 0);
+ virtual ~QQuickImageParticle();
+
+
+ QDeclarativeListProperty<QQuickSprite> sprites();
+ QQuickStochasticEngine* spriteEngine() {return m_spriteEngine;}
+
+ enum EntryEffect {
+ None = 0,
+ Fade = 1,
+ Scale = 2
+ };
+
+ enum PerformanceLevel{//TODO: Expose?
+ Unknown = 0,
+ Simple,
+ Colored,
+ Deformable,
+ Tabled,
+ Sprites
+ };
+
+ QUrl image() const { return m_image_name; }
+ void setImage(const QUrl &image);
+
+ QUrl colortable() const { return m_colortable_name; }
+ void setColortable(const QUrl &table);
+
+ QUrl sizetable() const { return m_sizetable_name; }
+ void setSizetable (const QUrl &table);
+
+ QUrl opacitytable() const { return m_opacitytable_name; }
+ void setOpacitytable(const QUrl &table);
+
+ QColor color() const { return m_color; }
+ void setColor(const QColor &color);
+
+ qreal colorVariation() const { return m_color_variation; }
+ void setColorVariation(qreal var);
+
+ qreal alphaVariation() const { return m_alphaVariation; }
+
+ qreal alpha() const { return m_alpha; }
+
+ qreal redVariation() const { return m_redVariation; }
+
+ qreal greenVariation() const { return m_greenVariation; }
+
+ qreal blueVariation() const { return m_blueVariation; }
+
+ qreal rotation() const { return m_rotation; }
+
+ qreal rotationVariation() const { return m_rotationVariation; }
+
+ qreal rotationSpeed() const { return m_rotationSpeed; }
+
+ qreal rotationSpeedVariation() const { return m_rotationSpeedVariation; }
+
+ bool autoRotation() const { return m_autoRotation; }
+
+ QQuickDirection* xVector() const { return m_xVector; }
+
+ QQuickDirection* yVector() const { return m_yVector; }
+
+ bool spritesInterpolate() const { return m_spritesInterpolate; }
+
+ bool bloat() const { return m_bloat; }
+
+ EntryEffect entryEffect() const { return m_entryEffect; }
+
+ void resetColor();
+ void resetRotation();
+ void resetDeformation();
+
+signals:
+
+ void imageChanged();
+ void colortableChanged();
+ void sizetableChanged();
+ void opacitytableChanged();
+
+ void colorChanged();
+ void colorVariationChanged();
+
+ void alphaVariationChanged(qreal arg);
+
+ void alphaChanged(qreal arg);
+
+ void redVariationChanged(qreal arg);
+
+ void greenVariationChanged(qreal arg);
+
+ void blueVariationChanged(qreal arg);
+
+ void rotationChanged(qreal arg);
+
+ void rotationVariationChanged(qreal arg);
+
+ void rotationSpeedChanged(qreal arg);
+
+ void rotationSpeedVariationChanged(qreal arg);
+
+ void autoRotationChanged(bool arg);
+
+ void xVectorChanged(QQuickDirection* arg);
+
+ void yVectorChanged(QQuickDirection* arg);
+
+ void spritesInterpolateChanged(bool arg);
+
+ void bloatChanged(bool arg);
+
+ void entryEffectChanged(EntryEffect arg);
+
+public slots:
+ void reloadColor(const Color4ub &c, QQuickParticleData* d);
+ void setAlphaVariation(qreal arg);
+
+ void setAlpha(qreal arg);
+
+ void setRedVariation(qreal arg);
+
+ void setGreenVariation(qreal arg);
+
+ void setBlueVariation(qreal arg);
+
+ void setRotation(qreal arg);
+
+ void setRotationVariation(qreal arg);
+
+ void setRotationSpeed(qreal arg);
+
+ void setRotationSpeedVariation(qreal arg);
+
+ void setAutoRotation(bool arg);
+
+ void setXVector(QQuickDirection* arg);
+
+ void setYVector(QQuickDirection* arg);
+
+ void setSpritesInterpolate(bool arg);
+
+ void setBloat(bool arg);
+
+ void setEntryEffect(EntryEffect arg);
+
+protected:
+ void reset();
+ virtual void initialize(int gIdx, int pIdx);
+ virtual void commit(int gIdx, int pIdx);
+
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void prepareNextFrame();
+ QSGGeometryNode* buildParticleNodes();
+
+private slots:
+ void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
+
+ void spriteAdvance(int spriteIndex);
+private:
+ QUrl m_image_name;
+ QUrl m_colortable_name;
+ QUrl m_sizetable_name;
+ QUrl m_opacitytable_name;
+
+
+ QColor m_color;
+ qreal m_color_variation;
+
+ QSGGeometryNode *m_rootNode;
+ QHash<int, QSGGeometryNode *> m_nodes;
+ QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
+ QList<QPair<int, int> > m_startsIdx;//Same data, optimized for alternate retrieval
+
+ int m_lastIdxStart;
+ QSGMaterial *m_material;
+
+ // derived values...
+
+ qreal m_alphaVariation;
+ qreal m_alpha;
+ qreal m_redVariation;
+ qreal m_greenVariation;
+ qreal m_blueVariation;
+ qreal m_rotation;
+ qreal m_rotationVariation;
+ qreal m_rotationSpeed;
+ qreal m_rotationSpeedVariation;
+ bool m_autoRotation;
+ QQuickDirection* m_xVector;
+ QQuickDirection* m_yVector;
+
+ QList<QQuickSprite*> m_sprites;
+ QQuickSpriteEngine* m_spriteEngine;
+ bool m_spritesInterpolate;
+
+ bool m_explicitColor;
+ bool m_explicitRotation;
+ bool m_explicitDeformation;
+ bool m_explicitAnimation;
+ QHash<int, QVector<QQuickParticleData*> > m_shadowData;
+ void clearShadows();
+ QQuickParticleData* getShadowDatum(QQuickParticleData* datum);
+
+ bool m_bloat;
+ PerformanceLevel perfLevel;
+
+ PerformanceLevel m_lastLevel;
+ bool m_debugMode;
+
+ template<class Vertex>
+ void initTexCoords(Vertex* v, int count){
+ Vertex* end = v + count;
+ while (v < end){
+ v[0].tx = 0;
+ v[0].ty = 0;
+
+ v[1].tx = 1;
+ v[1].ty = 0;
+
+ v[2].tx = 0;
+ v[2].ty = 1;
+
+ v[3].tx = 1;
+ v[3].ty = 1;
+
+ v += 4;
+ }
+ }
+
+ template<class MaterialData>
+ MaterialData* getState(QSGMaterial* m){
+ return static_cast<QSGSimpleMaterial<MaterialData> *>(m)->state();
+ }
+ EntryEffect m_entryEffect;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // ULTRAPARTICLE_H
diff --git a/src/quick/particles/qquickitemparticle.cpp b/src/quick/particles/qquickitemparticle.cpp
new file mode 100644
index 0000000000..14ca085469
--- /dev/null
+++ b/src/quick/particles/qquickitemparticle.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qquickitemparticle_p.h"
+#include <private/qquickvisualitemmodel_p.h>
+#include <QtQuick/qsgnode.h>
+#include <QTimer>
+#include <QDeclarativeComponent>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass ItemParticle QQuickItemParticle
+ \inqmlmodule QtQuick.Particles 2
+ \inherits ParticlePainter
+ \brief The ItemParticle element allows you to specify your own delegate to paint particles.
+
+*/
+
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::freeze(Item item)
+
+ Suspends the flow of time for the logical particle which item represents, allowing you to control its movement.
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::unfreeze(Item item)
+
+ Restarts the flow of time for the logical particle which item represents, allowing it to be moved by the particle system again.
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::take(Item item, bool prioritize)
+
+ Asks the ItemParticle to take over control of item. It will be emitted when there is a logical particle available.
+
+ By default items form a queue when waiting for a logical particle, but if prioritize is true then it will go immediately to the
+ head of the queue.
+*/
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::give(Item item)
+
+ Orders the ItemParticle to give you control of the item. It will cease controlling it and the item will lose its association to the logical particle.
+*/
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ItemParticle::fade
+
+ If true, the item will automatically be faded in and out
+ at the ends of its lifetime. If false, you will have to
+ implement any entry effect yourself.
+
+ Default is true.
+*/
+/*!
+ \qmlproperty Component QtQuick.Particles2::ItemParticle::delegate
+
+ An instance of the delegate will be created for every logical
+ particle, and moved along with it.
+*/
+
+QQuickItemParticle::QQuickItemParticle(QQuickItem *parent) :
+ QQuickParticlePainter(parent), m_fade(true), m_delegate(0)
+{
+ setFlag(QQuickItem::ItemHasContents);
+ QTimer* manageDelegates = new QTimer(this);//TODO: don't leak
+ connect(manageDelegates, SIGNAL(timeout()),
+ this, SLOT(tick()));
+ manageDelegates->setInterval(16);
+ manageDelegates->setSingleShot(false);
+ manageDelegates->start();
+}
+
+
+void QQuickItemParticle::freeze(QQuickItem* item)
+{
+ m_stasis << item;
+}
+
+
+void QQuickItemParticle::unfreeze(QQuickItem* item)
+{
+ m_stasis.remove(item);
+}
+
+void QQuickItemParticle::take(QQuickItem *item, bool prioritize)
+{
+ if (prioritize)
+ m_pendingItems.push_front(item);
+ else
+ m_pendingItems.push_back(item);
+}
+
+void QQuickItemParticle::give(QQuickItem *item)
+{
+ //TODO: This
+ Q_UNUSED(item);
+}
+
+void QQuickItemParticle::initialize(int gIdx, int pIdx)
+{
+ m_loadables << m_system->groupData[gIdx]->data[pIdx];//defer to other thread
+}
+
+void QQuickItemParticle::commit(int, int)
+{
+}
+
+void QQuickItemParticle::tick()
+{
+ foreach (QQuickItem* item, m_deletables){
+ if (m_fade)
+ item->setOpacity(0.);
+ item->setVisible(false);
+ QQuickItemParticleAttached* mpa;
+ if ((mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(item))))
+ mpa->detach();//reparent as well?
+ //TODO: Delete iff we created it
+ m_activeCount--;
+ }
+ m_deletables.clear();
+
+ foreach (QQuickParticleData* d, m_loadables){
+ if (m_stasis.contains(d->delegate))
+ qWarning() << "Current model particles prefers overwrite:false";
+ //remove old item from the particle that is dying to make room for this one
+ if (d->delegate)
+ m_deletables << d->delegate;
+ d->delegate = 0;
+ if (!m_pendingItems.isEmpty()){
+ d->delegate = m_pendingItems.front();
+ m_pendingItems.pop_front();
+ }else if (m_delegate){
+ d->delegate = qobject_cast<QQuickItem*>(m_delegate->create(qmlContext(this)));
+ }
+ if (d->delegate && d){//###Data can be zero if creating an item leads to a reset - this screws things up.
+ d->delegate->setX(d->curX() - d->delegate->width()/2);//TODO: adjust for system?
+ d->delegate->setY(d->curY() - d->delegate->height()/2);
+ QQuickItemParticleAttached* mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(d->delegate));
+ if (mpa){
+ mpa->m_mp = this;
+ mpa->attach();
+ }
+ d->delegate->setParentItem(this);
+ if (m_fade)
+ d->delegate->setOpacity(0.);
+ d->delegate->setVisible(false);//Will be set to true when we prepare the next frame
+ m_activeCount++;
+ }
+ }
+ m_loadables.clear();
+}
+
+void QQuickItemParticle::reset()
+{
+ QQuickParticlePainter::reset();
+ //TODO: Cleanup items?
+ m_loadables.clear();
+ //deletables?
+}
+
+
+QSGNode* QQuickItemParticle::updatePaintNode(QSGNode* n, UpdatePaintNodeData* d)
+{
+ //Dummy update just to get painting tick
+ if (m_pleaseReset){
+ m_pleaseReset = false;
+ reset();
+ }
+ prepareNextFrame();
+
+ update();//Get called again
+ if (n)
+ n->markDirty(QSGNode::DirtyMaterial);
+ return QQuickItem::updatePaintNode(n,d);
+}
+
+void QQuickItemParticle::prepareNextFrame()
+{
+ if (!m_system)
+ return;
+ qint64 timeStamp = m_system->systemSync(this);
+ qreal curT = timeStamp/1000.0;
+ qreal dt = curT - m_lastT;
+ m_lastT = curT;
+ if (!m_activeCount)
+ return;
+
+ //TODO: Size, better fade?
+ foreach (const QString &str, m_groups){
+ int gIdx = m_system->groupIds[str];
+ int count = m_system->groupData[gIdx]->size();
+
+ for (int i=0; i<count; i++){
+ QQuickParticleData* data = m_system->groupData[gIdx]->data[i];
+ QQuickItem* item = data->delegate;
+ if (!item)
+ continue;
+ qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
+ if (m_stasis.contains(item)) {
+ data->t += dt;//Stasis effect
+ continue;
+ }
+ if (t >= 1.0){//Usually happens from load
+ m_deletables << item;
+ data->delegate = 0;
+ }else{//Fade
+ data->delegate->setVisible(true);
+ if (m_fade){
+ qreal o = 1.;
+ if (t<0.2)
+ o = t*5;
+ if (t>0.8)
+ o = (1-t)*5;
+ item->setOpacity(o);
+ }
+ }
+ item->setX(data->curX() - item->width()/2 - m_systemOffset.x());
+ item->setY(data->curY() - item->height()/2 - m_systemOffset.y());
+ }
+ }
+}
+
+QQuickItemParticleAttached *QQuickItemParticle::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickItemParticleAttached(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickitemparticle_p.h b/src/quick/particles/qquickitemparticle_p.h
new file mode 100644
index 0000000000..33d2bcfb4b
--- /dev/null
+++ b/src/quick/particles/qquickitemparticle_p.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 ITEMPARTICLE_H
+#define ITEMPARTICLE_H
+#include "qquickparticlepainter_p.h"
+#include <QPointer>
+#include <QSet>
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickVisualDataModel;
+class QQuickItemParticleAttached;
+
+class QQuickItemParticle : public QQuickParticlePainter
+{
+ Q_OBJECT
+ Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged)
+ Q_PROPERTY(QDeclarativeComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+public:
+ explicit QQuickItemParticle(QQuickItem *parent = 0);
+
+ bool fade() const { return m_fade; }
+
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+ static QQuickItemParticleAttached *qmlAttachedProperties(QObject *object);
+ QDeclarativeComponent* delegate() const
+ {
+ return m_delegate;
+ }
+
+signals:
+ void fadeChanged();
+
+ void delegateChanged(QDeclarativeComponent* arg);
+
+public slots:
+ //TODO: Add a follow mode, where moving the delegate causes the logical particle to go with it?
+ void freeze(QQuickItem* item);
+ void unfreeze(QQuickItem* item);
+ void take(QQuickItem* item,bool prioritize=false);//take by modelparticle
+ void give(QQuickItem* item);//give from modelparticle
+
+ void setFade(bool arg){if (arg == m_fade) return; m_fade = arg; emit fadeChanged();}
+ void setDelegate(QDeclarativeComponent* arg)
+ {
+ if (m_delegate != arg) {
+ m_delegate = arg;
+ emit delegateChanged(arg);
+ }
+ }
+
+protected:
+ virtual void reset();
+ virtual void commit(int gIdx, int pIdx);
+ virtual void initialize(int gIdx, int pIdx);
+ void prepareNextFrame();
+private slots:
+ void tick();
+private:
+ QList<QQuickItem* > m_deletables;
+ QList< QQuickParticleData* > m_loadables;
+ bool m_fade;
+
+ QList<QQuickItem*> m_pendingItems;
+ QList<int> m_available;
+ QSet<QQuickItem*> m_stasis;
+ qreal m_lastT;
+ int m_activeCount;
+ QDeclarativeComponent* m_delegate;
+};
+
+class QQuickItemParticleAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickItemParticle* particle READ particle CONSTANT);
+public:
+ QQuickItemParticleAttached(QObject* parent)
+ : QObject(parent), m_mp(0)
+ {;}
+ QQuickItemParticle* particle() {return m_mp;}
+ void detach(){emit detached();}
+ void attach(){emit attached();}
+private:
+ QQuickItemParticle* m_mp;
+ friend class QQuickItemParticle;
+Q_SIGNALS:
+ void detached();
+ void attached();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QQuickItemParticle, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+#endif // ITEMPARTICLE_H
diff --git a/src/declarative/particles/qquicklineextruder.cpp b/src/quick/particles/qquicklineextruder.cpp
index 73413537cc..73413537cc 100644
--- a/src/declarative/particles/qquicklineextruder.cpp
+++ b/src/quick/particles/qquicklineextruder.cpp
diff --git a/src/declarative/particles/qquicklineextruder_p.h b/src/quick/particles/qquicklineextruder_p.h
index 8258b26043..8258b26043 100644
--- a/src/declarative/particles/qquicklineextruder_p.h
+++ b/src/quick/particles/qquicklineextruder_p.h
diff --git a/src/declarative/particles/qquickmaskextruder.cpp b/src/quick/particles/qquickmaskextruder.cpp
index f4850712f0..f4850712f0 100644
--- a/src/declarative/particles/qquickmaskextruder.cpp
+++ b/src/quick/particles/qquickmaskextruder.cpp
diff --git a/src/quick/particles/qquickmaskextruder_p.h b/src/quick/particles/qquickmaskextruder_p.h
new file mode 100644
index 0000000000..180bcf26e2
--- /dev/null
+++ b/src/quick/particles/qquickmaskextruder_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 MASKEXTRUDER_H
+#define MASKEXTRUDER_H
+#include "qquickparticleextruder_p.h"
+#include <QUrl>
+#include <QImage>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMaskExtruder : public QQuickParticleExtruder
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+public:
+ explicit QQuickMaskExtruder(QObject *parent = 0);
+ virtual QPointF extrude(const QRectF &);
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
+
+ QUrl source() const
+ {
+ return m_source;
+ }
+
+signals:
+
+ void sourceChanged(QUrl arg);
+
+public slots:
+
+ void setSource(QUrl arg)
+ {
+ if (m_source != arg) {
+ m_source = arg;
+ m_lastHeight = -1;//Trigger reset
+ m_lastWidth = -1;
+ emit sourceChanged(arg);
+ }
+ }
+private:
+ QUrl m_source;
+
+ void ensureInitialized(const QRectF &r);
+ int m_lastWidth;
+ int m_lastHeight;
+ QImage m_img;
+ QList<QPointF> m_mask;//TODO: More memory efficient datastructures
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // MASKEXTRUDER_H
diff --git a/src/declarative/particles/qquickparticleaffector.cpp b/src/quick/particles/qquickparticleaffector.cpp
index 5bfc699548..5bfc699548 100644
--- a/src/declarative/particles/qquickparticleaffector.cpp
+++ b/src/quick/particles/qquickparticleaffector.cpp
diff --git a/src/quick/particles/qquickparticleaffector_p.h b/src/quick/particles/qquickparticleaffector_p.h
new file mode 100644
index 0000000000..94eba70ae4
--- /dev/null
+++ b/src/quick/particles/qquickparticleaffector_p.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 PARTICLEAFFECTOR_H
+#define PARTICLEAFFECTOR_H
+
+#include <QObject>
+#include "qquickparticlesystem_p.h"
+#include "qquickparticleextruder_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticleAffector : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
+ Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
+ Q_PROPERTY(QStringList whenCollidingWith READ whenCollidingWith WRITE setWhenCollidingWith NOTIFY whenCollidingWithChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
+ Q_PROPERTY(QQuickParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
+
+public:
+ explicit QQuickParticleAffector(QQuickItem *parent = 0);
+ virtual void affectSystem(qreal dt);
+ virtual void reset(QQuickParticleData*);//As some store their own data per particle?
+ QQuickParticleSystem* system() const
+ {
+ return m_system;
+ }
+
+ QStringList groups() const
+ {
+ return m_groups;
+ }
+
+ bool enabled() const
+ {
+ return m_enabled;
+ }
+
+ bool onceOff() const
+ {
+ return m_onceOff;
+ }
+
+ QQuickParticleExtruder* shape() const
+ {
+ return m_shape;
+ }
+
+ QStringList whenCollidingWith() const
+ {
+ return m_whenCollidingWith;
+ }
+
+signals:
+
+ void systemChanged(QQuickParticleSystem* arg);
+
+ void groupsChanged(QStringList arg);
+
+ void enabledChanged(bool arg);
+
+ void onceChanged(bool arg);
+
+ void shapeChanged(QQuickParticleExtruder* arg);
+
+ void affected(qreal x, qreal y);
+
+ void whenCollidingWithChanged(QStringList arg);
+
+public slots:
+void setSystem(QQuickParticleSystem* arg)
+{
+ if (m_system != arg) {
+ m_system = arg;
+ m_system->registerParticleAffector(this);
+ emit systemChanged(arg);
+ }
+}
+
+void setGroups(QStringList arg)
+{
+ if (m_groups != arg) {
+ m_groups = arg;
+ m_updateIntSet = true;
+ emit groupsChanged(arg);
+ }
+}
+
+void setEnabled(bool arg)
+{
+ if (m_enabled != arg) {
+ m_enabled = arg;
+ emit enabledChanged(arg);
+ }
+}
+
+void setOnceOff(bool arg)
+{
+ if (m_onceOff != arg) {
+ m_onceOff = arg;
+ m_needsReset = true;
+ emit onceChanged(arg);
+ }
+}
+
+void setShape(QQuickParticleExtruder* arg)
+{
+ if (m_shape != arg) {
+ m_shape = arg;
+ emit shapeChanged(arg);
+ }
+}
+
+void setWhenCollidingWith(QStringList arg)
+{
+ if (m_whenCollidingWith != arg) {
+ m_whenCollidingWith = arg;
+ emit whenCollidingWithChanged(arg);
+ }
+}
+public slots:
+ void updateOffsets();
+
+protected:
+ friend class QQuickParticleSystem;
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+ bool m_needsReset:1;//### What is this really saving?
+ bool m_ignoresTime:1;
+ bool m_onceOff:1;
+ bool m_enabled:1;
+
+ QQuickParticleSystem* m_system;
+ QStringList m_groups;
+ bool activeGroup(int g);
+ bool shouldAffect(QQuickParticleData* datum);//Call to do the logic on whether it is affecting that datum
+ void postAffect(QQuickParticleData* datum);//Call to do the post-affect logic on particles which WERE affected(once off, needs reset, affected signal)
+ virtual void componentComplete();
+ QPointF m_offset;
+ bool isAffectedConnected();
+ static const qreal simulationDelta;
+ static const qreal simulationCutoff;
+private:
+ QSet<int> m_groupIds;
+ QSet<QPair<int, int> > m_onceOffed;
+ bool m_updateIntSet;
+
+ QQuickParticleExtruder* m_shape;
+
+ QStringList m_whenCollidingWith;
+
+ bool isColliding(QQuickParticleData* d);
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // PARTICLEAFFECTOR_H
diff --git a/src/declarative/particles/qquickparticleemitter.cpp b/src/quick/particles/qquickparticleemitter.cpp
index f227256f1b..f227256f1b 100644
--- a/src/declarative/particles/qquickparticleemitter.cpp
+++ b/src/quick/particles/qquickparticleemitter.cpp
diff --git a/src/quick/particles/qquickparticleemitter_p.h b/src/quick/particles/qquickparticleemitter_p.h
new file mode 100644
index 0000000000..bfdb63eef7
--- /dev/null
+++ b/src/quick/particles/qquickparticleemitter_p.h
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 PARTICLEEMITTER_H
+#define PARTICLEEMITTER_H
+
+#include <QtQuick/QQuickItem>
+#include <QDebug>
+#include "qquickparticlesystem_p.h"
+#include "qquickparticleextruder_p.h"
+#include "qquickdirection_p.h"
+
+#include <QList>
+#include <QPair>
+#include <QPointF>
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticleEmitter : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
+ Q_PROPERTY(QString group READ group WRITE setGroup NOTIFY groupChanged)
+ Q_PROPERTY(QQuickParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+
+ Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
+ Q_PROPERTY(int lifeSpan READ particleDuration WRITE setParticleDuration NOTIFY particleDurationChanged)
+ Q_PROPERTY(int lifeSpanVariation READ particleDurationVariation WRITE setParticleDurationVariation NOTIFY particleDurationVariationChanged)
+ Q_PROPERTY(int maximumEmitted READ maxParticleCount WRITE setMaxParticleCount NOTIFY maximumEmittedChanged)
+
+ Q_PROPERTY(qreal size READ particleSize WRITE setParticleSize NOTIFY particleSizeChanged)
+ Q_PROPERTY(qreal endSize READ particleEndSize WRITE setParticleEndSize NOTIFY particleEndSizeChanged)
+ Q_PROPERTY(qreal sizeVariation READ particleSizeVariation WRITE setParticleSizeVariation NOTIFY particleSizeVariationChanged)
+
+ Q_PROPERTY(QQuickDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
+ Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+ Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+
+ Q_ENUMS(Lifetime)
+public:
+ explicit QQuickParticleEmitter(QQuickItem *parent = 0);
+ virtual ~QQuickParticleEmitter();
+ virtual void emitWindow(int timeStamp);
+
+ enum Lifetime {
+ InfiniteLife = QQuickParticleSystem::maxLife
+ };
+
+ bool enabled() const
+ {
+ return m_enabled;
+ }
+
+ qreal particlesPerSecond() const
+ {
+ return m_particlesPerSecond;
+ }
+
+ int particleDuration() const
+ {
+ return m_particleDuration;
+ }
+
+ QQuickParticleSystem* system() const
+ {
+ return m_system;
+ }
+
+ QString group() const
+ {
+ return m_group;
+ }
+
+ int particleDurationVariation() const
+ {
+ return m_particleDurationVariation;
+ }
+
+ qreal speedFromMovement() const { return m_speed_from_movement; }
+ void setSpeedFromMovement(qreal s);
+ virtual void componentComplete();
+signals:
+ void emitParticles(QDeclarativeV8Handle particles);
+ void particlesPerSecondChanged(qreal);
+ void particleDurationChanged(int);
+ void enabledChanged(bool);
+
+ void systemChanged(QQuickParticleSystem* arg);
+
+ void groupChanged(QString arg);
+
+ void particleDurationVariationChanged(int arg);
+
+ void extruderChanged(QQuickParticleExtruder* arg);
+
+ void particleSizeChanged(qreal arg);
+
+ void particleEndSizeChanged(qreal arg);
+
+ void particleSizeVariationChanged(qreal arg);
+
+ void speedChanged(QQuickDirection * arg);
+
+ void accelerationChanged(QQuickDirection * arg);
+
+ void maximumEmittedChanged(int arg);
+ void particleCountChanged();
+
+ void speedFromMovementChanged();
+
+ void startTimeChanged(int arg);
+
+public slots:
+ void pulse(int milliseconds);
+ void burst(int num);
+ void burst(int num, qreal x, qreal y);
+
+ void setEnabled(bool arg);
+
+ void setParticlesPerSecond(qreal arg)
+ {
+ if (m_particlesPerSecond != arg) {
+ m_particlesPerSecond = arg;
+ emit particlesPerSecondChanged(arg);
+ }
+ }
+
+ void setParticleDuration(int arg)
+ {
+ if (m_particleDuration != arg) {
+ m_particleDuration = arg;
+ emit particleDurationChanged(arg);
+ }
+ }
+
+ void setSystem(QQuickParticleSystem* arg)
+ {
+ if (m_system != arg) {
+ m_system = arg;
+ m_system->registerParticleEmitter(this);
+ emit systemChanged(arg);
+ }
+ }
+
+ void setGroup(QString arg)
+ {
+ if (m_group != arg) {
+ m_group = arg;
+ emit groupChanged(arg);
+ }
+ }
+
+ void setParticleDurationVariation(int arg)
+ {
+ if (m_particleDurationVariation != arg) {
+ m_particleDurationVariation = arg;
+ emit particleDurationVariationChanged(arg);
+ }
+ }
+ void setExtruder(QQuickParticleExtruder* arg)
+ {
+ if (m_extruder != arg) {
+ m_extruder = arg;
+ emit extruderChanged(arg);
+ }
+ }
+
+ void setParticleSize(qreal arg)
+ {
+ if (m_particleSize != arg) {
+ m_particleSize = arg;
+ emit particleSizeChanged(arg);
+ }
+ }
+
+ void setParticleEndSize(qreal arg)
+ {
+ if (m_particleEndSize != arg) {
+ m_particleEndSize = arg;
+ emit particleEndSizeChanged(arg);
+ }
+ }
+
+ void setParticleSizeVariation(qreal arg)
+ {
+ if (m_particleSizeVariation != arg) {
+ m_particleSizeVariation = arg;
+ emit particleSizeVariationChanged(arg);
+ }
+ }
+
+ void setSpeed(QQuickDirection * arg)
+ {
+ if (m_speed != arg) {
+ m_speed = arg;
+ emit speedChanged(arg);
+ }
+ }
+
+ void setAcceleration(QQuickDirection * arg)
+ {
+ if (m_acceleration != arg) {
+ m_acceleration = arg;
+ emit accelerationChanged(arg);
+ }
+ }
+
+ void setMaxParticleCount(int arg);
+
+ void setStartTime(int arg)
+ {
+ if (m_startTime != arg) {
+ m_startTime = arg;
+ emit startTimeChanged(arg);
+ }
+ }
+
+ virtual void reset();
+public:
+ int particleCount() const;
+
+ QQuickParticleExtruder* extruder() const
+ {
+ return m_extruder;
+ }
+
+ qreal particleSize() const
+ {
+ return m_particleSize;
+ }
+
+ qreal particleEndSize() const
+ {
+ return m_particleEndSize;
+ }
+
+ qreal particleSizeVariation() const
+ {
+ return m_particleSizeVariation;
+ }
+
+ QQuickDirection * speed() const
+ {
+ return m_speed;
+ }
+
+ QQuickDirection * acceleration() const
+ {
+ return m_acceleration;
+ }
+
+ int maxParticleCount() const
+ {
+ return m_maxParticleCount;
+ }
+
+ int startTime() const
+ {
+ return m_startTime;
+ }
+
+protected:
+ qreal m_particlesPerSecond;
+ int m_particleDuration;
+ int m_particleDurationVariation;
+ bool m_enabled;
+ QQuickParticleSystem* m_system;
+ QString m_group;
+ QQuickParticleExtruder* m_extruder;
+ QQuickParticleExtruder* m_defaultExtruder;
+ QQuickParticleExtruder* effectiveExtruder();
+ QQuickDirection * m_speed;
+ QQuickDirection * m_acceleration;
+ qreal m_particleSize;
+ qreal m_particleEndSize;
+ qreal m_particleSizeVariation;
+
+ qreal m_speedFromMovement;
+ int m_startTime;
+ bool m_overwrite;
+
+ int m_pulseLeft;
+ QList<QPair<int, QPointF > > m_burstQueue;
+ int m_maxParticleCount;
+
+ //Used in default implementation, but might be useful
+ qreal m_speed_from_movement;
+
+ int m_emitCap;
+ bool m_reset_last;
+ qreal m_last_timestamp;
+ qreal m_last_emission;
+
+ QPointF m_last_emitter;
+ QPointF m_last_last_emitter;
+ QPointF m_last_last_last_emitter;
+
+ bool isEmitConnected();
+private:
+ QQuickDirection m_nullVector;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // PARTICLEEMITTER_H
diff --git a/src/declarative/particles/qquickparticleextruder.cpp b/src/quick/particles/qquickparticleextruder.cpp
index 8b25de26be..8b25de26be 100644
--- a/src/declarative/particles/qquickparticleextruder.cpp
+++ b/src/quick/particles/qquickparticleextruder.cpp
diff --git a/src/quick/particles/qquickparticleextruder_p.h b/src/quick/particles/qquickparticleextruder_p.h
new file mode 100644
index 0000000000..d1f7008a31
--- /dev/null
+++ b/src/quick/particles/qquickparticleextruder_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 PARTICLEEXTRUDER_H
+#define PARTICLEEXTRUDER_H
+
+#include <QObject>
+#include <QRectF>
+#include <QPointF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticleExtruder : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickParticleExtruder(QObject *parent = 0);
+ virtual QPointF extrude(const QRectF &);
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
+
+signals:
+public slots:
+protected:
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // PARTICLEEXTRUDER_H
diff --git a/src/declarative/particles/qquickparticlegroup.cpp b/src/quick/particles/qquickparticlegroup.cpp
index 5486339611..5486339611 100644
--- a/src/declarative/particles/qquickparticlegroup.cpp
+++ b/src/quick/particles/qquickparticlegroup.cpp
diff --git a/src/declarative/particles/qquickparticlegroup_p.h b/src/quick/particles/qquickparticlegroup_p.h
index 547e7fc597..547e7fc597 100644
--- a/src/declarative/particles/qquickparticlegroup_p.h
+++ b/src/quick/particles/qquickparticlegroup_p.h
diff --git a/src/declarative/particles/qquickparticlepainter.cpp b/src/quick/particles/qquickparticlepainter.cpp
index 812c4b86dc..812c4b86dc 100644
--- a/src/declarative/particles/qquickparticlepainter.cpp
+++ b/src/quick/particles/qquickparticlepainter.cpp
diff --git a/src/quick/particles/qquickparticlepainter_p.h b/src/quick/particles/qquickparticlepainter_p.h
new file mode 100644
index 0000000000..44aac3466f
--- /dev/null
+++ b/src/quick/particles/qquickparticlepainter_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 PARTICLE_H
+#define PARTICLE_H
+
+#include <QObject>
+#include <QDebug>
+#include <QPair>
+#include "qquickparticlesystem_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticlePainter : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
+ Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
+
+public:
+ explicit QQuickParticlePainter(QQuickItem *parent = 0);
+ //Data Interface to system
+ void load(QQuickParticleData*);
+ void reload(QQuickParticleData*);
+ void setCount(int c);
+ int count();
+ void performPendingCommits();//Called from updatePaintNode
+ QQuickParticleSystem* system() const
+ {
+ return m_system;
+ }
+
+
+ QStringList groups() const
+ {
+ return m_groups;
+ }
+
+signals:
+ void countChanged();
+ void systemChanged(QQuickParticleSystem* arg);
+
+ void groupsChanged(QStringList arg);
+
+public slots:
+ void setSystem(QQuickParticleSystem* arg);
+
+ void setGroups(QStringList arg)
+ {
+ if (m_groups != arg) {
+ m_groups = arg;
+ emit groupsChanged(arg);
+ }
+ }
+
+ void calcSystemOffset(bool resetPending = false);
+
+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.
+ ###Hunt down all cases where we do a complete reset for convenience and be more targeted
+ */
+ virtual void reset();
+
+ virtual void componentComplete();
+ virtual void initialize(int gIdx, int pIdx){//Called from main thread
+ Q_UNUSED(gIdx);
+ Q_UNUSED(pIdx);
+ }
+ virtual void commit(int gIdx, int pIdx){//Called in Render Thread
+ //###If you need to do something on size changed, check m_data size in this? Or we reset you every time?
+ Q_UNUSED(gIdx);
+ Q_UNUSED(pIdx);
+ }
+
+ QQuickParticleSystem* m_system;
+ friend class QQuickParticleSystem;
+ int m_count;
+ bool m_pleaseReset;//Used by subclasses, but it's a nice optimization to know when stuff isn't going to matter.
+ QStringList m_groups;
+ QPointF m_systemOffset;
+
+private:
+ QSet<QPair<int,int> > m_pendingCommits;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // PARTICLE_H
diff --git a/src/declarative/particles/qquickparticlesmodule.cpp b/src/quick/particles/qquickparticlesmodule.cpp
index 26439c4f50..26439c4f50 100644
--- a/src/declarative/particles/qquickparticlesmodule.cpp
+++ b/src/quick/particles/qquickparticlesmodule.cpp
diff --git a/src/quick/particles/qquickparticlesmodule_p.h b/src/quick/particles/qquickparticlesmodule_p.h
new file mode 100644
index 0000000000..e553b23558
--- /dev/null
+++ b/src/quick/particles/qquickparticlesmodule_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQuickPARTICLESMODULE_H
+#define QQuickPARTICLESMODULE_H
+
+#include <qdeclarative.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticlesModule
+{
+public:
+ static void defineModule();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QQuickPARTICLESMODULE_H
diff --git a/src/quick/particles/qquickparticlesystem.cpp b/src/quick/particles/qquickparticlesystem.cpp
new file mode 100644
index 0000000000..9df086a045
--- /dev/null
+++ b/src/quick/particles/qquickparticlesystem.cpp
@@ -0,0 +1,1106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qquickparticlesystem_p.h"
+#include <QtQuick/qsgnode.h>
+#include "qquickparticleemitter_p.h"
+#include "qquickparticleaffector_p.h"
+#include "qquickparticlepainter_p.h"
+#include <private/qquickspriteengine_p.h>
+#include <private/qquicksprite_p.h>
+#include "qquickv8particledata_p.h"
+#include "qquickparticlegroup_p.h"
+
+#include "qquicktrailemitter_p.h"//###For auto-follow on states, perhaps should be in emitter?
+#include <private/qdeclarativeengine_p.h>
+#include <cmath>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
+DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
+/*!
+ \qmlclass ParticleSystem QQuickParticleSystem
+ \inqmlmodule QtQuick.Particles 2
+ \brief The ParticleSystem brings together ParticlePainter, Emitter and Affector elements.
+
+*/
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ParticleSystem::running
+
+ If running is set to false, the particle system will stop the simulation. All particles
+ will be destroyed when the system is set to running again.
+
+ It can also be controlled with the start() and stop() methods.
+*/
+
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ParticleSystem::paused
+
+ If paused is set to true, the particle system will not advance the simulation. When
+ paused is set to false again, the simulation will resume from the same point it was
+ paused.
+
+ The simulation will automatically pause if it detects that there are no live particles
+ left, and unpause when new live particles are added.
+
+ It can also be controlled with the pause() and resume() methods.
+*/
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ParticleSystem::empty
+
+ empty is set to true when there are no live particles left in the system.
+
+ You can use this to pause the system, keeping it from spending any time updating,
+ but you will need to resume it in order for additional particles to be generated
+ by the system.
+
+ To kill all the particles in the system, use a Kill affector.
+*/
+
+/*!
+ \qmlproperty list<Sprite> QtQuick.Particles2::ParticleSystem::particleStates
+
+ You can define a sub-set of particle groups in this property in order to provide them
+ with stochastic state transitions.
+
+ Each QtQuick2::Sprite in this list is interpreted as corresponding to the particle group
+ with ths same name. Any transitions defined in these sprites will take effect on the particle
+ groups as well. Additionally TrailEmitters, Affectors and ParticlePainters definined
+ inside one of these sprites are automatically associated with the corresponding particle group.
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::pause
+
+ Pauses the simulation if it is running.
+
+ \sa resume, paused
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::resume
+
+ Resumes the simulation if it is paused.
+
+ \sa pause, paused
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::start
+
+ Starts the simulation if it has not already running.
+
+ \sa stop, restart, running
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::stop
+
+ Stops the simulation if it is running.
+
+ \sa start, restart, running
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::restart
+
+ Stops the simulation if it is running, and then starts it.
+
+ \sa stop, restart, running
+*/
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::reset
+
+ Discards all currently existing particles.
+
+*/
+const qreal EPSILON = 0.001;
+//Utility functions for when within 1ms is close enough
+bool timeEqualOrGreater(qreal a, qreal b)
+{
+ return (a+EPSILON >= b);
+}
+
+bool timeLess(qreal a, qreal b)
+{
+ return (a-EPSILON < b);
+}
+
+bool timeEqual(qreal a, qreal b)
+{
+ return (a+EPSILON > b) && (a-EPSILON < b);
+}
+
+int roundedTime(qreal a)
+{// in ms
+ return (int)qRound(a*1000.0);
+}
+
+QQuickParticleDataHeap::QQuickParticleDataHeap()
+ : m_data(0)
+{
+ m_data.reserve(1000);
+ clear();
+}
+
+void QQuickParticleDataHeap::grow() //###Consider automatic growth vs resize() calls from GroupData
+{
+ m_data.resize(1 << ++m_size);
+}
+
+void QQuickParticleDataHeap::insert(QQuickParticleData* data)
+{
+ insertTimed(data, roundedTime(data->t + data->lifeSpan));
+}
+
+void QQuickParticleDataHeap::insertTimed(QQuickParticleData* data, int time)
+{
+ //TODO: Optimize 0 lifespan (or already dead) case
+ if (m_lookups.contains(time)) {
+ m_data[m_lookups[time]].data << data;
+ return;
+ }
+ if (m_end == (1 << m_size))
+ grow();
+ m_data[m_end].time = time;
+ m_data[m_end].data.clear();
+ m_data[m_end].data.insert(data);
+ m_lookups.insert(time, m_end);
+ bubbleUp(m_end++);
+}
+
+int QQuickParticleDataHeap::top()
+{
+ if (m_end == 0)
+ return 1 << 30;
+ return m_data[0].time;
+}
+
+QSet<QQuickParticleData*> QQuickParticleDataHeap::pop()
+{
+ if (!m_end)
+ return QSet<QQuickParticleData*> ();
+ QSet<QQuickParticleData*> ret = m_data[0].data;
+ m_lookups.remove(m_data[0].time);
+ if (m_end == 1) {
+ --m_end;
+ } else {
+ m_data[0] = m_data[--m_end];
+ bubbleDown(0);
+ }
+ return ret;
+}
+
+void QQuickParticleDataHeap::clear()
+{
+ m_size = 0;
+ m_end = 0;
+ //m_size is in powers of two. So to start at 0 we have one allocated
+ m_data.resize(1);
+ m_lookups.clear();
+}
+
+bool QQuickParticleDataHeap::contains(QQuickParticleData* d)
+{
+ for (int i=0; i<m_end; i++)
+ if (m_data[i].data.contains(d))
+ return true;
+ return false;
+}
+
+void QQuickParticleDataHeap::swap(int a, int b)
+{
+ m_tmp = m_data[a];
+ m_data[a] = m_data[b];
+ m_data[b] = m_tmp;
+ m_lookups[m_data[a].time] = a;
+ m_lookups[m_data[b].time] = b;
+}
+
+void QQuickParticleDataHeap::bubbleUp(int idx)//tends to be called once
+{
+ if (!idx)
+ return;
+ int parent = (idx-1)/2;
+ if (m_data[idx].time < m_data[parent].time) {
+ swap(idx, parent);
+ bubbleUp(parent);
+ }
+}
+
+void QQuickParticleDataHeap::bubbleDown(int idx)//tends to be called log n times
+{
+ int left = idx*2 + 1;
+ if (left >= m_end)
+ return;
+ int lesser = left;
+ int right = idx*2 + 2;
+ if (right < m_end) {
+ if (m_data[left].time > m_data[right].time)
+ lesser = right;
+ }
+ if (m_data[idx].time > m_data[lesser].time) {
+ swap(idx, lesser);
+ bubbleDown(lesser);
+ }
+}
+
+QQuickParticleGroupData::QQuickParticleGroupData(int id, QQuickParticleSystem* sys):index(id),m_size(0),m_system(sys)
+{
+ initList();
+}
+
+QQuickParticleGroupData::~QQuickParticleGroupData()
+{
+ foreach (QQuickParticleData* d, data)
+ delete d;
+}
+
+int QQuickParticleGroupData::size()
+{
+ return m_size;
+}
+
+QString QQuickParticleGroupData::name()//### Worth caching as well?
+{
+ return m_system->groupIds.key(index);
+}
+
+void QQuickParticleGroupData::setSize(int newSize)
+{
+ if (newSize == m_size)
+ return;
+ Q_ASSERT(newSize > m_size);//XXX allow shrinking
+ data.resize(newSize);
+ for (int i=m_size; i<newSize; i++) {
+ data[i] = new QQuickParticleData(m_system);
+ data[i]->group = index;
+ data[i]->index = i;
+ reusableIndexes << i;
+ }
+ int delta = newSize - m_size;
+ m_size = newSize;
+ foreach (QQuickParticlePainter* p, painters)
+ p->setCount(p->count() + delta);
+}
+
+void QQuickParticleGroupData::initList()
+{
+ dataHeap.clear();
+}
+
+void QQuickParticleGroupData::kill(QQuickParticleData* d)
+{
+ Q_ASSERT(d->group == index);
+ d->lifeSpan = 0;//Kill off
+ foreach (QQuickParticlePainter* p, painters)
+ p->reload(d);
+ reusableIndexes << d->index;
+}
+
+QQuickParticleData* QQuickParticleGroupData::newDatum(bool respectsLimits)
+{
+ //recycle();//Extra recycler round to be sure?
+
+ while (!reusableIndexes.empty()) {
+ int idx = *(reusableIndexes.begin());
+ reusableIndexes.remove(idx);
+ if (data[idx]->stillAlive()) {// ### This means resurrection of 'dead' particles. Is that allowed?
+ prepareRecycler(data[idx]);
+ continue;
+ }
+ return data[idx];
+ }
+ if (respectsLimits)
+ return 0;
+
+ int oldSize = m_size;
+ setSize(oldSize + 10);//###+1,10%,+10? Choose something non-arbitrarily
+ reusableIndexes.remove(oldSize);
+ return data[oldSize];
+}
+
+bool QQuickParticleGroupData::recycle()
+{
+ while (dataHeap.top() <= m_system->timeInt) {
+ foreach (QQuickParticleData* datum, dataHeap.pop()) {
+ if (!datum->stillAlive()) {
+ reusableIndexes << datum->index;
+ } else {
+ prepareRecycler(datum); //ttl has been altered mid-way, put it back
+ }
+ }
+ }
+
+ //TODO: If the data is clear, gc (consider shrinking stack size)?
+ return reusableIndexes.count() == m_size;
+}
+
+void QQuickParticleGroupData::prepareRecycler(QQuickParticleData* d)
+{
+ if (d->lifeSpan*1000 < m_system->maxLife) {
+ dataHeap.insert(d);
+ } else {
+ while ((roundedTime(d->t) + 2*m_system->maxLife/3) <= m_system->timeInt)
+ d->extendLife(m_system->maxLife/3000.0);
+ dataHeap.insertTimed(d, roundedTime(d->t) + 2*m_system->maxLife/3);
+ }
+}
+
+QQuickParticleData::QQuickParticleData(QQuickParticleSystem* sys)
+ : group(0)
+ , e(0)
+ , system(sys)
+ , index(0)
+ , systemIndex(-1)
+ , colorOwner(0)
+ , rotationOwner(0)
+ , deformationOwner(0)
+ , animationOwner(0)
+ , v8Datum(0)
+{
+ x = 0;
+ y = 0;
+ t = -1;
+ lifeSpan = 0;
+ size = 0;
+ endSize = 0;
+ vx = 0;
+ vy = 0;
+ ax = 0;
+ ay = 0;
+ xx = 1;
+ xy = 0;
+ yx = 0;
+ yy = 1;
+ rotation = 0;
+ rotationSpeed = 0;
+ autoRotate = 0;
+ animIdx = 0;
+ frameDuration = 1;
+ frameCount = 1;
+ animT = -1;
+ animX = 0;
+ animY = 0;
+ animWidth = 1;
+ animHeight = 1;
+ color.r = 255;
+ color.g = 255;
+ color.b = 255;
+ color.a = 255;
+ r = 0;
+ delegate = 0;
+ modelIndex = -1;
+}
+
+QQuickParticleData::~QQuickParticleData()
+{
+ delete v8Datum;
+}
+
+void QQuickParticleData::clone(const QQuickParticleData& other)
+{
+ x = other.x;
+ y = other.y;
+ t = other.t;
+ lifeSpan = other.lifeSpan;
+ size = other.size;
+ endSize = other.endSize;
+ vx = other.vx;
+ vy = other.vy;
+ ax = other.ax;
+ ay = other.ay;
+ xx = other.xx;
+ xy = other.xy;
+ yx = other.yx;
+ yy = other.yy;
+ rotation = other.rotation;
+ rotationSpeed = other.rotationSpeed;
+ autoRotate = other.autoRotate;
+ animIdx = other.animIdx;
+ frameDuration = other.frameDuration;
+ frameCount = other.frameCount;
+ animT = other.animT;
+ animX = other.animX;
+ animY = other.animY;
+ animWidth = other.animWidth;
+ animHeight = other.animHeight;
+ color.r = other.color.r;
+ color.g = other.color.g;
+ color.b = other.color.b;
+ color.a = other.color.a;
+ r = other.r;
+ delegate = other.delegate;
+ modelIndex = other.modelIndex;
+
+ colorOwner = other.colorOwner;
+ rotationOwner = other.rotationOwner;
+ deformationOwner = other.deformationOwner;
+ animationOwner = other.animationOwner;
+}
+
+QDeclarativeV8Handle QQuickParticleData::v8Value()
+{
+ if (!v8Datum)
+ v8Datum = new QQuickV8ParticleData(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(system)), this);
+ return v8Datum->v8Value();
+}
+//sets the x accleration without affecting the instantaneous x velocity or position
+void QQuickParticleData::setInstantaneousAX(qreal ax)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ qreal vx = (this->vx + t*this->ax) - t*ax;
+ qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t;
+ qreal x = ex - t*vx - 0.5 * t*t*ax;
+
+ this->ax = ax;
+ this->vx = vx;
+ this->x = x;
+}
+
+//sets the x velocity without affecting the instantaneous x postion
+void QQuickParticleData::setInstantaneousVX(qreal vx)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ qreal evx = vx - t*this->ax;
+ qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t;
+ qreal x = ex - t*evx - 0.5 * t*t*this->ax;
+
+ this->vx = evx;
+ this->x = x;
+}
+
+//sets the instantaneous x postion
+void QQuickParticleData::setInstantaneousX(qreal x)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ this->x = x - t*this->vx - 0.5 * t*t*this->ax;
+}
+
+//sets the y accleration without affecting the instantaneous y velocity or position
+void QQuickParticleData::setInstantaneousAY(qreal ay)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ qreal vy = (this->vy + t*this->ay) - t*ay;
+ qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t;
+ qreal y = ey - t*vy - 0.5 * t*t*ay;
+
+ this->ay = ay;
+ this->vy = vy;
+ this->y = y;
+}
+
+//sets the y velocity without affecting the instantaneous y position
+void QQuickParticleData::setInstantaneousVY(qreal vy)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ qreal evy = vy - t*this->ay;
+ qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t;
+ qreal y = ey - t*evy - 0.5 * t*t*this->ay;
+
+ this->vy = evy;
+ this->y = y;
+}
+
+//sets the instantaneous Y position
+void QQuickParticleData::setInstantaneousY(qreal y)
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ this->y = y - t*this->vy - 0.5 * t*t*this->ay;
+}
+
+qreal QQuickParticleData::curX() const
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ return this->x + this->vx * t + 0.5 * this->ax * t * t;
+}
+
+qreal QQuickParticleData::curVX() const
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ return this->vx + t*this->ax;
+}
+
+qreal QQuickParticleData::curY() const
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ return y + vy * t + 0.5 * ay * t * t;
+}
+
+qreal QQuickParticleData::curVY() const
+{
+ qreal t = (system->timeInt / 1000.0) - this->t;
+ return vy + t*ay;
+}
+
+void QQuickParticleData::debugDump()
+{
+ qDebug() << "Particle" << systemIndex << group << "/" << index << stillAlive()
+ << "Pos: " << x << "," << y
+ << "Vel: " << vx << "," << vy
+ << "Acc: " << ax << "," << ay
+ << "Size: " << size << "," << endSize
+ << "Time: " << t << "," <<lifeSpan << ";" << (system->timeInt / 1000.0) ;
+}
+
+bool QQuickParticleData::stillAlive()
+{
+ if (!system)
+ return false;
+ return (t + lifeSpan - EPSILON) > ((qreal)system->timeInt/1000.0);
+}
+
+bool QQuickParticleData::alive()
+{
+ if (!system)
+ return false;
+ qreal st = ((qreal)system->timeInt/1000.0);
+ return (t + EPSILON) < st && (t + lifeSpan - EPSILON) > st;
+}
+
+float QQuickParticleData::curSize()
+{
+ if (!system || !lifeSpan)
+ return 0.0f;
+ return size + (endSize - size) * (1 - (lifeLeft() / lifeSpan));
+}
+
+float QQuickParticleData::lifeLeft()
+{
+ if (!system)
+ return 0.0f;
+ return (t + lifeSpan) - (system->timeInt/1000.0);
+}
+
+void QQuickParticleData::extendLife(float time)
+{
+ qreal newX = curX();
+ qreal newY = curY();
+ qreal newVX = curVX();
+ qreal newVY = curVY();
+
+ t += time;
+ animT += time;
+
+ qreal elapsed = (system->timeInt / 1000.0) - t;
+ qreal evy = newVY - elapsed*ay;
+ qreal ey = newY - elapsed*evy - 0.5 * elapsed*elapsed*ay;
+ qreal evx = newVX - elapsed*ax;
+ qreal ex = newX - elapsed*evx - 0.5 * elapsed*elapsed*ax;
+
+ x = ex;
+ vx = evx;
+ y = ey;
+ vy = evy;
+}
+
+QQuickParticleSystem::QQuickParticleSystem(QQuickItem *parent) :
+ QQuickItem(parent),
+ stateEngine(0),
+ m_running(true),
+ particleCount(0),
+ m_nextIndex(0),
+ m_componentComplete(false),
+ m_paused(false)
+{
+ connect(&m_painterMapper, SIGNAL(mapped(QObject*)),
+ this, SLOT(loadPainter(QObject*)));
+
+ m_debugMode = qmlParticlesDebug();
+}
+
+QQuickParticleSystem::~QQuickParticleSystem()
+{
+ foreach (QQuickParticleGroupData* gd, groupData)
+ delete gd;
+}
+
+void QQuickParticleSystem::initGroups()
+{
+ m_reusableIndexes.clear();
+ m_nextIndex = 0;
+
+ qDeleteAll(groupData);
+ groupData.clear();
+ groupIds.clear();
+
+ QQuickParticleGroupData* gd = new QQuickParticleGroupData(0, this);//Default group
+ groupData.insert(0,gd);
+ groupIds.insert(QString(), 0);
+ m_nextGroupId = 1;
+}
+
+void QQuickParticleSystem::registerParticlePainter(QQuickParticlePainter* p)
+{
+ //TODO: a way to Unregister emitters, painters and affectors
+ m_painters << QPointer<QQuickParticlePainter>(p);//###Set or uniqueness checking?
+ connect(p, SIGNAL(groupsChanged(QStringList)),
+ &m_painterMapper, SLOT(map()));
+ loadPainter(p);
+}
+
+void QQuickParticleSystem::registerParticleEmitter(QQuickParticleEmitter* e)
+{
+ m_emitters << QPointer<QQuickParticleEmitter>(e);//###How to get them out?
+ connect(e, SIGNAL(particleCountChanged()),
+ this, SLOT(emittersChanged()));
+ connect(e, SIGNAL(groupChanged(QString)),
+ this, SLOT(emittersChanged()));
+ emittersChanged();
+ e->reset();//Start, so that starttime factors appropriately
+}
+
+void QQuickParticleSystem::registerParticleAffector(QQuickParticleAffector* a)
+{
+ m_affectors << QPointer<QQuickParticleAffector>(a);
+}
+
+void QQuickParticleSystem::registerParticleGroup(QQuickParticleGroup* g)
+{
+ m_groups << QPointer<QQuickParticleGroup>(g);
+ createEngine();
+}
+
+void QQuickParticleSystem::setRunning(bool arg)
+{
+ if (m_running != arg) {
+ m_running = arg;
+ emit runningChanged(arg);
+ setPaused(false);
+ if (m_animation)//Not created until componentCompleted
+ m_running ? m_animation->start() : m_animation->stop();
+ reset();
+ }
+}
+
+void QQuickParticleSystem::setPaused(bool arg) {
+ if (m_paused != arg) {
+ m_paused = arg;
+ if (m_animation && m_animation->state() != QAbstractAnimation::Stopped)
+ m_paused ? m_animation->pause() : m_animation->resume();
+ if (!m_paused) {
+ foreach (QQuickParticlePainter *p, m_painters)
+ p->update();
+ }
+ emit pausedChanged(arg);
+ }
+}
+
+void QQuickParticleSystem::statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
+{
+ //Hooks up automatic state-associated stuff
+ QQuickParticleSystem* sys = qobject_cast<QQuickParticleSystem*>(prop->object->parent());
+ QQuickParticleGroup* group = qobject_cast<QQuickParticleGroup*>(prop->object);
+ if (!group || !sys || !value)
+ return;
+ stateRedirect(group, sys, value);
+}
+
+void QQuickParticleSystem::stateRedirect(QQuickParticleGroup* group, QQuickParticleSystem* sys, QObject *value)
+{
+ QStringList list;
+ list << group->name();
+ QQuickParticleAffector* a = qobject_cast<QQuickParticleAffector*>(value);
+ if (a) {
+ a->setParentItem(sys);
+ a->setGroups(list);
+ a->setSystem(sys);
+ return;
+ }
+ QQuickTrailEmitter* fe = qobject_cast<QQuickTrailEmitter*>(value);
+ if (fe) {
+ fe->setParentItem(sys);
+ fe->setFollow(group->name());
+ fe->setSystem(sys);
+ return;
+ }
+ QQuickParticleEmitter* e = qobject_cast<QQuickParticleEmitter*>(value);
+ if (e) {
+ e->setParentItem(sys);
+ e->setGroup(group->name());
+ e->setSystem(sys);
+ return;
+ }
+ QQuickParticlePainter* p = qobject_cast<QQuickParticlePainter*>(value);
+ if (p) {
+ p->setParentItem(sys);
+ p->setGroups(list);
+ p->setSystem(sys);
+ return;
+ }
+ qWarning() << value << " was placed inside a particle system state but cannot be taken into the particle system. It will be lost.";
+}
+
+void QQuickParticleSystem::componentComplete()
+
+{
+ QQuickItem::componentComplete();
+ m_componentComplete = true;
+ m_animation = new QQuickParticleSystemAnimation(this);
+ reset();//restarts animation as well
+}
+
+void QQuickParticleSystem::reset()
+{
+ if (!m_componentComplete)
+ return;
+
+ timeInt = 0;
+ //Clear guarded pointers which have been deleted
+ int cleared = 0;
+ cleared += m_emitters.removeAll(0);
+ cleared += m_painters.removeAll(0);
+ cleared += m_affectors.removeAll(0);
+
+ bySysIdx.resize(0);
+ initGroups();//Also clears all logical particles
+
+ if (!m_running)
+ return;
+
+ foreach (QQuickParticleEmitter* e, m_emitters)
+ e->reset();
+
+ emittersChanged();
+
+ foreach (QQuickParticlePainter *p, m_painters) {
+ loadPainter(p);
+ p->reset();
+ }
+
+ //### Do affectors need reset too?
+ if (m_animation) {//Animation is explicitly disabled in benchmarks
+ //reset restarts animation (if running)
+ if ((m_animation->state() == QAbstractAnimation::Running))
+ m_animation->stop();
+ m_animation->start();
+ if (m_paused)
+ m_animation->pause();
+ }
+
+ initialized = true;
+}
+
+
+void QQuickParticleSystem::loadPainter(QObject *p)
+{
+ if (!m_componentComplete)
+ return;
+
+ QQuickParticlePainter* painter = qobject_cast<QQuickParticlePainter*>(p);
+ Q_ASSERT(painter);//XXX
+ foreach (QQuickParticleGroupData* sg, groupData)
+ sg->painters.remove(painter);
+ int particleCount = 0;
+ if (painter->groups().isEmpty()) {//Uses default particle
+ QStringList def;
+ def << QString();
+ painter->setGroups(def);
+ particleCount += groupData[0]->size();
+ groupData[0]->painters << painter;
+ } else {
+ foreach (const QString &group, painter->groups()) {
+ if (group != QLatin1String("") && !groupIds[group]) {//new group
+ int id = m_nextGroupId++;
+ QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
+ groupIds.insert(group, id);
+ groupData.insert(id, gd);
+ }
+ particleCount += groupData[groupIds[group]]->size();
+ groupData[groupIds[group]]->painters << painter;
+ }
+ }
+ painter->setCount(particleCount);
+ painter->update();//Initial update here
+ return;
+}
+
+void QQuickParticleSystem::emittersChanged()
+{
+ if (!m_componentComplete)
+ return;
+
+ m_emitters.removeAll(0);
+
+
+ QList<int> previousSizes;
+ QList<int> newSizes;
+ for (int i=0; i<m_nextGroupId; i++) {
+ previousSizes << groupData[i]->size();
+ newSizes << 0;
+ }
+
+ foreach (QQuickParticleEmitter* e, m_emitters) {//Populate groups and set sizes.
+ if (!groupIds.contains(e->group())
+ || (!e->group().isEmpty() && !groupIds[e->group()])) {//or it was accidentally inserted by a failed lookup earlier
+ int id = m_nextGroupId++;
+ QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
+ groupIds.insert(e->group(), id);
+ groupData.insert(id, gd);
+ previousSizes << 0;
+ newSizes << 0;
+ }
+ newSizes[groupIds[e->group()]] += e->particleCount();
+ //###: Cull emptied groups?
+ }
+
+ //TODO: Garbage collection?
+ particleCount = 0;
+ for (int i=0; i<m_nextGroupId; i++) {
+ groupData[i]->setSize(qMax(newSizes[i], previousSizes[i]));
+ particleCount += groupData[i]->size();
+ }
+
+ if (m_debugMode)
+ qDebug() << "Particle system emitters changed. New particle count: " << particleCount;
+
+ if (particleCount > bySysIdx.size())//New datum requests haven't updated it
+ bySysIdx.resize(particleCount);
+
+ foreach (QQuickParticlePainter *p, m_painters)
+ loadPainter(p);
+
+ if (!m_groups.isEmpty())
+ createEngine();
+
+}
+
+void QQuickParticleSystem::createEngine()
+{
+ if (!m_componentComplete)
+ return;
+ if (stateEngine && m_debugMode)
+ qDebug() << "Resetting Existing Sprite Engine...";
+ //### Solve the losses if size/states go down
+ foreach (QQuickParticleGroup* group, m_groups) {
+ bool exists = false;
+ foreach (const QString &name, groupIds.keys())
+ if (group->name() == name)
+ exists = true;
+ if (!exists) {
+ int id = m_nextGroupId++;
+ QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
+ groupIds.insert(group->name(), id);
+ groupData.insert(id, gd);
+ }
+ }
+
+ if (m_groups.count()) {
+ //Reorder groups List so as to have the same order as groupData
+ QList<QQuickParticleGroup*> newList;
+ for (int i=0; i<m_nextGroupId; i++) {
+ bool exists = false;
+ QString name = groupData[i]->name();
+ foreach (QQuickParticleGroup* existing, m_groups) {
+ if (existing->name() == name) {
+ newList << existing;
+ exists = true;
+ }
+ }
+ if (!exists) {
+ newList << new QQuickParticleGroup(this);
+ newList.back()->setName(name);
+ }
+ }
+ m_groups = newList;
+ QList<QQuickStochasticState*> states;
+ foreach (QQuickParticleGroup* g, m_groups)
+ states << (QQuickStochasticState*)g;
+
+ if (!stateEngine)
+ stateEngine = new QQuickStochasticEngine(this);
+ stateEngine->setCount(particleCount);
+ stateEngine->m_states = states;
+
+ connect(stateEngine, SIGNAL(stateChanged(int)),
+ this, SLOT(particleStateChange(int)));
+
+ } else {
+ if (stateEngine)
+ delete stateEngine;
+ stateEngine = 0;
+ }
+
+}
+
+void QQuickParticleSystem::particleStateChange(int idx)
+{
+ moveGroups(bySysIdx[idx], stateEngine->curState(idx));
+}
+
+void QQuickParticleSystem::moveGroups(QQuickParticleData *d, int newGIdx)
+{
+ if (!d || newGIdx == d->group)
+ return;
+
+ QQuickParticleData* pd = newDatum(newGIdx, false, d->systemIndex);
+ if (!pd)
+ return;
+
+ pd->clone(*d);
+ finishNewDatum(pd);
+
+ d->systemIndex = -1;
+ groupData[d->group]->kill(d);
+}
+
+int QQuickParticleSystem::nextSystemIndex()
+{
+ if (!m_reusableIndexes.isEmpty()) {
+ int ret = *(m_reusableIndexes.begin());
+ m_reusableIndexes.remove(ret);
+ return ret;
+ }
+ if (m_nextIndex >= bySysIdx.size()) {
+ bySysIdx.resize(bySysIdx.size() < 10 ? 10 : bySysIdx.size()*1.1);//###+1,10%,+10? Choose something non-arbitrarily
+ if (stateEngine)
+ stateEngine->setCount(bySysIdx.size());
+
+ }
+ return m_nextIndex++;
+}
+
+QQuickParticleData* QQuickParticleSystem::newDatum(int groupId, bool respectLimits, int sysIndex)
+{
+ Q_ASSERT(groupId < groupData.count());//XXX shouldn't really be an assert
+
+ QQuickParticleData* ret = groupData[groupId]->newDatum(respectLimits);
+ if (!ret) {
+ return 0;
+ }
+ if (sysIndex == -1) {
+ if (ret->systemIndex == -1)
+ ret->systemIndex = nextSystemIndex();
+ } else {
+ if (ret->systemIndex != -1) {
+ if (stateEngine)
+ stateEngine->stop(ret->systemIndex);
+ m_reusableIndexes << ret->systemIndex;
+ bySysIdx[ret->systemIndex] = 0;
+ }
+ ret->systemIndex = sysIndex;
+ }
+ bySysIdx[ret->systemIndex] = ret;
+
+ if (stateEngine)
+ stateEngine->start(ret->systemIndex, ret->group);
+
+ m_empty = false;
+ return ret;
+}
+
+void QQuickParticleSystem::emitParticle(QQuickParticleData* pd)
+{// called from prepareNextFrame()->emitWindow - enforce?
+ //Account for relative emitter position
+ QPointF offset = this->mapFromItem(pd->e, QPointF(0, 0));
+ if (!offset.isNull()) {
+ pd->x += offset.x();
+ pd->y += offset.y();
+ }
+
+ finishNewDatum(pd);
+}
+
+void QQuickParticleSystem::finishNewDatum(QQuickParticleData *pd)
+{
+ Q_ASSERT(pd);
+ groupData[pd->group]->prepareRecycler(pd);
+
+ foreach (QQuickParticleAffector *a, m_affectors)
+ if (a && a->m_needsReset)
+ a->reset(pd);
+ foreach (QQuickParticlePainter* p, groupData[pd->group]->painters)
+ if (p)
+ p->load(pd);
+}
+
+void QQuickParticleSystem::updateCurrentTime( int currentTime )
+{
+ if (!initialized)
+ return;//error in initialization
+
+ //### Elapsed time never shrinks - may cause problems if left emitting for weeks at a time.
+ qreal dt = timeInt / 1000.;
+ timeInt = currentTime;
+ qreal time = timeInt / 1000.;
+ dt = time - dt;
+ needsReset.clear();
+
+ m_emitters.removeAll(0);
+ m_painters.removeAll(0);
+ m_affectors.removeAll(0);
+
+ bool oldClear = m_empty;
+ m_empty = true;
+ foreach (QQuickParticleGroupData* gd, groupData)//Recycle all groups and see if they're out of live particles
+ m_empty = gd->recycle() && m_empty;
+
+ if (stateEngine)
+ stateEngine->updateSprites(timeInt);
+
+ foreach (QQuickParticleEmitter* emitter, m_emitters)
+ emitter->emitWindow(timeInt);
+ foreach (QQuickParticleAffector* a, m_affectors)
+ a->affectSystem(dt);
+ foreach (QQuickParticleData* d, needsReset)
+ foreach (QQuickParticlePainter* p, groupData[d->group]->painters)
+ p->reload(d);
+
+ if (oldClear != m_empty)
+ emptyChanged(m_empty);
+}
+
+int QQuickParticleSystem::systemSync(QQuickParticlePainter* p)
+{
+ if (!m_running)
+ return 0;
+ if (!initialized)
+ return 0;//error in initialization
+ p->performPendingCommits();
+ return timeInt;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickparticlesystem_p.h b/src/quick/particles/qquickparticlesystem_p.h
new file mode 100644
index 0000000000..6a3403aa93
--- /dev/null
+++ b/src/quick/particles/qquickparticlesystem_p.h
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 PARTICLESYSTEM_H
+#define PARTICLESYSTEM_H
+
+#include <QtQuick/QQuickItem>
+#include <QElapsedTimer>
+#include <QVector>
+#include <QHash>
+#include <QPointer>
+#include <QSignalMapper>
+#include <private/qquicksprite_p.h>
+#include <QAbstractAnimation>
+#include <QtDeclarative/qdeclarative.h>
+#include <private/qv8engine_p.h> //For QDeclarativeV8Handle
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticleSystem;
+class QQuickParticleAffector;
+class QQuickParticleEmitter;
+class QQuickParticlePainter;
+class QQuickParticleData;
+class QQuickParticleSystemAnimation;
+class QQuickStochasticEngine;
+class QQuickSprite;
+class QQuickV8ParticleData;
+class QQuickParticleGroup;
+class QQuickImageParticle;
+
+struct QQuickParticleDataHeapNode{
+ int time;//in ms
+ QSet<QQuickParticleData*> data;//Set ptrs instead?
+};
+
+class QQuickParticleDataHeap {
+ //Idea is to do a binary heap, but which also stores a set of int,Node* so that if the int already exists, you can
+ //add it to the data* list. Pops return the whole list at once.
+public:
+ QQuickParticleDataHeap();
+ void insert(QQuickParticleData* data);
+ void insertTimed(QQuickParticleData* data, int time);
+
+ int top();
+
+ QSet<QQuickParticleData*> pop();
+
+ void clear();
+
+ bool contains(QQuickParticleData*);//O(n), for debugging purposes only
+private:
+ void grow();
+ void swap(int, int);
+ void bubbleUp(int);
+ void bubbleDown(int);
+ int m_size;
+ int m_end;
+ QQuickParticleDataHeapNode m_tmp;
+ QVector<QQuickParticleDataHeapNode> m_data;
+ QHash<int,int> m_lookups;
+};
+
+class Q_AUTOTEST_EXPORT QQuickParticleGroupData {
+public:
+ QQuickParticleGroupData(int id, QQuickParticleSystem* sys);
+ ~QQuickParticleGroupData();
+
+ int size();
+ QString name();
+
+ void setSize(int newSize);
+
+ int index;
+ QSet<QQuickParticlePainter*> painters;//TODO: What if they are dynamically removed?
+
+ //TODO: Refactor particle data list out into a separate class
+ QVector<QQuickParticleData*> data;
+ QQuickParticleDataHeap dataHeap;
+ QSet<int> reusableIndexes;
+ bool recycle(); //Force recycling round, returns true if all indexes are now reusable
+
+ void initList();
+ void kill(QQuickParticleData* d);
+
+ //After calling this, initialize, then call prepareRecycler(d)
+ QQuickParticleData* newDatum(bool respectsLimits);
+
+ //TODO: Find and clean up those that don't get added to the recycler (currently they get lost)
+ void prepareRecycler(QQuickParticleData* d);
+
+private:
+ int m_size;
+ QQuickParticleSystem* m_system;
+};
+
+struct Color4ub {
+ uchar r;
+ uchar g;
+ uchar b;
+ uchar a;
+};
+
+class Q_AUTOTEST_EXPORT QQuickParticleData {
+public:
+ //TODO: QObject like memory management (without the cost, just attached to system)
+ QQuickParticleData(QQuickParticleSystem* sys);
+ ~QQuickParticleData();
+
+ //Convenience functions for working backwards, because parameters are from the start of particle life
+ //If setting multiple parameters at once, doing the conversion yourself will be faster.
+
+ //sets the x accleration without affecting the instantaneous x velocity or position
+ void setInstantaneousAX(qreal ax);
+ //sets the x velocity without affecting the instantaneous x postion
+ void setInstantaneousVX(qreal vx);
+ //sets the instantaneous x postion
+ void setInstantaneousX(qreal x);
+ //sets the y accleration without affecting the instantaneous y velocity or position
+ void setInstantaneousAY(qreal ay);
+ //sets the y velocity without affecting the instantaneous y postion
+ void setInstantaneousVY(qreal vy);
+ //sets the instantaneous Y postion
+ void setInstantaneousY(qreal y);
+
+ //TODO: Slight caching?
+ qreal curX() const;
+ qreal curVX() const;
+ qreal curAX() const { return ax; }
+ qreal curY() const;
+ qreal curVY() const;
+ qreal curAY() const { return ay; }
+
+ int group;
+ QQuickParticleEmitter* e;//### Needed?
+ QQuickParticleSystem* system;
+ int index;
+ int systemIndex;
+
+ //General Position Stuff
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+
+ //Other stuff, now universally shared
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assume that GPUs prefer floats to bools
+ float animIdx;
+ float frameDuration;
+ float frameCount;
+ float animT;
+ float animX;
+ float animY;
+ float animWidth;
+ float animHeight;
+ float r;
+ QQuickItem* delegate;
+ int modelIndex;
+ float update;//Used by custom affectors
+
+ //Used by image particle
+ QQuickImageParticle* colorOwner;
+ QQuickImageParticle* rotationOwner;
+ QQuickImageParticle* deformationOwner;
+ QQuickImageParticle* animationOwner;
+
+ void debugDump();
+ bool stillAlive();//Only checks end, because usually that's all you need and it's a little faster.
+ bool alive();
+ float lifeLeft();
+ float curSize();
+ void clone(const QQuickParticleData& other);//Not =, leaves meta-data like index
+ QDeclarativeV8Handle v8Value();
+ void extendLife(float time);
+private:
+ QQuickV8ParticleData* v8Datum;
+};
+
+class Q_AUTOTEST_EXPORT QQuickParticleSystem : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
+
+public:
+ explicit QQuickParticleSystem(QQuickItem *parent = 0);
+ ~QQuickParticleSystem();
+
+ bool isRunning() const
+ {
+ return m_running;
+ }
+
+ int count(){ return particleCount; }
+
+ static const int maxLife = 600000;
+
+signals:
+
+ void systemInitialized();
+ void runningChanged(bool arg);
+ void pausedChanged(bool arg);
+ void emptyChanged(bool arg);
+
+public slots:
+ void start(){setRunning(true);}
+ void stop(){setRunning(false);}
+ void restart(){setRunning(false);setRunning(true);}
+ void pause(){setPaused(true);}
+ void resume(){setPaused(false);}
+
+ void reset();
+ void setRunning(bool arg);
+ void setPaused(bool arg);
+
+ virtual int duration() const { return -1; }
+
+
+protected:
+ //This one only once per frame (effectively)
+ void componentComplete();
+
+private slots:
+ void emittersChanged();
+ void loadPainter(QObject* p);
+ void createEngine(); //Not invoked by sprite engine, unlike Sprite uses
+ void particleStateChange(int idx);
+
+public:
+ //These can be called multiple times per frame, performance critical
+ void emitParticle(QQuickParticleData* p);
+ QQuickParticleData* newDatum(int groupId, bool respectLimits = true, int sysIdx = -1);
+ void finishNewDatum(QQuickParticleData*);
+ void moveGroups(QQuickParticleData *d, int newGIdx);
+ int nextSystemIndex();
+
+ //This one only once per painter per frame
+ int systemSync(QQuickParticlePainter* p);
+
+ //Data members here for ease of related class and auto-test usage. Not "public" API. TODO: d_ptrize
+ QSet<QQuickParticleData*> needsReset;
+ QVector<QQuickParticleData*> bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
+ QHash<QString, int> groupIds;
+ QHash<int, QQuickParticleGroupData*> groupData;
+ QQuickStochasticEngine* stateEngine;
+
+ //Also only here for auto-test usage
+ void updateCurrentTime( int currentTime );
+ QQuickParticleSystemAnimation* m_animation;
+ bool m_running;
+
+ int timeInt;
+ bool initialized;
+ int particleCount;
+
+ void registerParticlePainter(QQuickParticlePainter* p);
+ void registerParticleEmitter(QQuickParticleEmitter* e);
+ void registerParticleAffector(QQuickParticleAffector* a);
+ void registerParticleGroup(QQuickParticleGroup* g);
+
+ static void statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);
+ static void stateRedirect(QQuickParticleGroup* group, QQuickParticleSystem* sys, QObject *value);
+ bool isPaused() const
+ {
+ return m_paused;
+ }
+
+ bool isEmpty() const
+ {
+ return m_empty;
+ }
+
+private:
+ void initializeSystem();
+ void initGroups();
+ QList<QPointer<QQuickParticleEmitter> > m_emitters;
+ QList<QPointer<QQuickParticleAffector> > m_affectors;
+ QList<QPointer<QQuickParticlePainter> > m_painters;
+ QList<QPointer<QQuickParticlePainter> > m_syncList;
+ QList<QQuickParticleGroup*> m_groups;
+ int m_nextGroupId;
+ int m_nextIndex;
+ QSet<int> m_reusableIndexes;
+ bool m_componentComplete;
+
+ QSignalMapper m_painterMapper;
+ QSignalMapper m_emitterMapper;
+ bool m_paused;
+ bool m_debugMode;
+ bool m_allDead;
+ bool m_empty;
+};
+
+// Internally, this animation drives all the timing. Painters sync up in their updatePaintNode
+class QQuickParticleSystemAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+public:
+ QQuickParticleSystemAnimation(QQuickParticleSystem* system)
+ : QAbstractAnimation(static_cast<QObject*>(system)), m_system(system)
+ { }
+protected:
+ virtual void updateCurrentTime( int t )
+ {
+ m_system->updateCurrentTime(t);
+ }
+
+ virtual int duration() const
+ {
+ return -1;
+ }
+
+private:
+ QQuickParticleSystem* m_system;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // PARTICLESYSTEM_H
+
+
diff --git a/src/declarative/particles/qquickpointattractor.cpp b/src/quick/particles/qquickpointattractor.cpp
index d96458c8bb..d96458c8bb 100644
--- a/src/declarative/particles/qquickpointattractor.cpp
+++ b/src/quick/particles/qquickpointattractor.cpp
diff --git a/src/quick/particles/qquickpointattractor_p.h b/src/quick/particles/qquickpointattractor_p.h
new file mode 100644
index 0000000000..6c36b299bf
--- /dev/null
+++ b/src/quick/particles/qquickpointattractor_p.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 ATTRACTORAFFECTOR_H
+#define ATTRACTORAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAttractorAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
+ Q_PROPERTY(qreal pointX READ pointX WRITE setPointX NOTIFY pointXChanged)
+ Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged)
+ Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
+ Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
+ Q_ENUMS(AffectableParameters)
+ Q_ENUMS(Proportion)
+
+public:
+ enum Proportion{
+ Constant,
+ Linear,
+ Quadratic,
+ InverseLinear,
+ InverseQuadratic
+ };
+
+ enum AffectableParameters {
+ Position,
+ Velocity,
+ Acceleration
+ };
+
+ explicit QQuickAttractorAffector(QQuickItem *parent = 0);
+
+ qreal strength() const
+ {
+ return m_strength;
+ }
+
+ qreal pointX() const
+ {
+ return m_x;
+ }
+
+ qreal pointY() const
+ {
+ return m_y;
+ }
+
+ AffectableParameters affectedParameter() const
+ {
+ return m_physics;
+ }
+
+ Proportion proportionalToDistance() const
+ {
+ return m_proportionalToDistance;
+ }
+
+signals:
+
+ void strengthChanged(qreal arg);
+
+ void pointXChanged(qreal arg);
+
+ void pointYChanged(qreal arg);
+
+ void affectedParameterChanged(AffectableParameters arg);
+
+ void proportionalToDistanceChanged(Proportion arg);
+
+public slots:
+void setStrength(qreal arg)
+{
+ if (m_strength != arg) {
+ m_strength = arg;
+ emit strengthChanged(arg);
+ }
+}
+
+void setPointX(qreal arg)
+{
+ if (m_x != arg) {
+ m_x = arg;
+ emit pointXChanged(arg);
+ }
+}
+
+void setPointY(qreal arg)
+{
+ if (m_y != arg) {
+ m_y = arg;
+ emit pointYChanged(arg);
+ }
+}
+void setAffectedParameter(AffectableParameters arg)
+{
+ if (m_physics != arg) {
+ m_physics = arg;
+ emit affectedParameterChanged(arg);
+ }
+}
+
+void setProportionalToDistance(Proportion arg)
+{
+ if (m_proportionalToDistance != arg) {
+ m_proportionalToDistance = arg;
+ emit proportionalToDistanceChanged(arg);
+ }
+}
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+private:
+qreal m_strength;
+qreal m_x;
+qreal m_y;
+AffectableParameters m_physics;
+Proportion m_proportionalToDistance;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // ATTRACTORAFFECTOR_H
diff --git a/src/declarative/particles/qquickpointdirection.cpp b/src/quick/particles/qquickpointdirection.cpp
index 22c33d9f15..22c33d9f15 100644
--- a/src/declarative/particles/qquickpointdirection.cpp
+++ b/src/quick/particles/qquickpointdirection.cpp
diff --git a/src/quick/particles/qquickpointdirection_p.h b/src/quick/particles/qquickpointdirection_p.h
new file mode 100644
index 0000000000..1a6becda7a
--- /dev/null
+++ b/src/quick/particles/qquickpointdirection_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 POINTVECTOR_H
+#define POINTVECTOR_H
+#include "qquickdirection_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPointDirection : public QQuickDirection
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal xVariation READ xVariation WRITE setXVariation NOTIFY xVariationChanged)
+ Q_PROPERTY(qreal yVariation READ yVariation WRITE setYVariation NOTIFY yVariationChanged)
+public:
+ explicit QQuickPointDirection(QObject *parent = 0);
+ virtual const QPointF sample(const QPointF &from);
+ qreal x() const
+ {
+ return m_x;
+ }
+
+ qreal y() const
+ {
+ return m_y;
+ }
+
+ qreal xVariation() const
+ {
+ return m_xVariation;
+ }
+
+ qreal yVariation() const
+ {
+ return m_yVariation;
+ }
+
+signals:
+
+ void xChanged(qreal arg);
+
+ void yChanged(qreal arg);
+
+ void xVariationChanged(qreal arg);
+
+ void yVariationChanged(qreal arg);
+
+public slots:
+ void setX(qreal arg)
+ {
+ if (m_x != arg) {
+ m_x = arg;
+ emit xChanged(arg);
+ }
+ }
+
+ void setY(qreal arg)
+ {
+ if (m_y != arg) {
+ m_y = arg;
+ emit yChanged(arg);
+ }
+ }
+
+ void setXVariation(qreal arg)
+ {
+ if (m_xVariation != arg) {
+ m_xVariation = arg;
+ emit xVariationChanged(arg);
+ }
+ }
+
+ void setYVariation(qreal arg)
+ {
+ if (m_yVariation != arg) {
+ m_yVariation = arg;
+ emit yVariationChanged(arg);
+ }
+ }
+
+private:
+
+ qreal m_x;
+ qreal m_y;
+ qreal m_xVariation;
+ qreal m_yVariation;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // POINTVECTOR_H
diff --git a/src/declarative/particles/qquickrectangleextruder.cpp b/src/quick/particles/qquickrectangleextruder.cpp
index d840a08d5b..d840a08d5b 100644
--- a/src/declarative/particles/qquickrectangleextruder.cpp
+++ b/src/quick/particles/qquickrectangleextruder.cpp
diff --git a/src/quick/particles/qquickrectangleextruder_p.h b/src/quick/particles/qquickrectangleextruder_p.h
new file mode 100644
index 0000000000..13491b9501
--- /dev/null
+++ b/src/quick/particles/qquickrectangleextruder_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 RECTANGLEEXTRUDER_H
+#define RECTANGLEEXTRUDER_H
+
+#include "qquickparticleextruder_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickRectangleExtruder : public QQuickParticleExtruder
+{
+ Q_OBJECT
+ Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)
+
+public:
+ explicit QQuickRectangleExtruder(QObject *parent = 0);
+ virtual QPointF extrude(const QRectF &);
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
+ bool fill() const
+ {
+ return m_fill;
+ }
+
+signals:
+
+ void fillChanged(bool arg);
+
+public slots:
+
+ void setFill(bool arg)
+ {
+ if (m_fill != arg) {
+ m_fill = arg;
+ emit fillChanged(arg);
+ }
+ }
+protected:
+ bool m_fill;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // RectangleEXTRUDER_H
diff --git a/src/declarative/particles/qquickspritegoal.cpp b/src/quick/particles/qquickspritegoal.cpp
index 7c839dbf53..7c839dbf53 100644
--- a/src/declarative/particles/qquickspritegoal.cpp
+++ b/src/quick/particles/qquickspritegoal.cpp
diff --git a/src/quick/particles/qquickspritegoal_p.h b/src/quick/particles/qquickspritegoal_p.h
new file mode 100644
index 0000000000..3dc4cf88ca
--- /dev/null
+++ b/src/quick/particles/qquickspritegoal_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 SPRITEGOALAFFECTOR_H
+#define SPRITEGOALAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickStochasticEngine;
+
+class QQuickSpriteGoalAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
+ Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
+ Q_PROPERTY(bool systemStates READ systemStates WRITE setSystemStates NOTIFY systemStatesChanged)
+public:
+ explicit QQuickSpriteGoalAffector(QQuickItem *parent = 0);
+
+ QString goalState() const
+ {
+ return m_goalState;
+ }
+
+ bool jump() const
+ {
+ return m_jump;
+ }
+ bool systemStates() const
+ {
+ return m_systemStates;
+ }
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+signals:
+
+ void goalStateChanged(QString arg);
+
+ void jumpChanged(bool arg);
+
+ void systemStatesChanged(bool arg);
+
+public slots:
+
+void setGoalState(QString arg);
+
+void setJump(bool arg)
+{
+ if (m_jump != arg) {
+ m_jump = arg;
+ emit jumpChanged(arg);
+ }
+}
+
+void setSystemStates(bool arg)
+{
+ if (m_systemStates != arg) {
+ //TODO: GroupGoal was added (and this deprecated) Oct 4 - remove it in a few weeks.
+ qmlInfo(this) << "systemStates is deprecated and will be removed soon. Use GroupGoal instead.";
+ m_systemStates = arg;
+ emit systemStatesChanged(arg);
+ }
+}
+
+private:
+ void updateStateIndex(QQuickStochasticEngine* e);
+ QString m_goalState;
+ int m_goalIdx;
+ QQuickStochasticEngine* m_lastEngine;
+ bool m_jump;
+ bool m_systemStates;
+
+ bool m_notUsingEngine;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SPRITEGOALAFFECTOR_H
diff --git a/src/declarative/particles/qquicktargetdirection.cpp b/src/quick/particles/qquicktargetdirection.cpp
index eb2eb16c6e..eb2eb16c6e 100644
--- a/src/declarative/particles/qquicktargetdirection.cpp
+++ b/src/quick/particles/qquicktargetdirection.cpp
diff --git a/src/quick/particles/qquicktargetdirection_p.h b/src/quick/particles/qquicktargetdirection_p.h
new file mode 100644
index 0000000000..32b5cb0038
--- /dev/null
+++ b/src/quick/particles/qquicktargetdirection_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 DIRECTEDVECTOR_H
+#define DIRECTEDVECTOR_H
+#include "qquickdirection_p.h"
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickTargetDirection : public QQuickDirection
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal targetX READ targetX WRITE setTargetX NOTIFY targetXChanged)
+ Q_PROPERTY(qreal targetY READ targetY WRITE setTargetY NOTIFY targetYChanged)
+ //If targetItem is set, X/Y are ignored. Aims at middle of item, use variation for variation
+ Q_PROPERTY(QQuickItem* targetItem READ targetItem WRITE setTargetItem NOTIFY targetItemChanged)
+
+ Q_PROPERTY(qreal targetVariation READ targetVariation WRITE setTargetVariation NOTIFY targetVariationChanged)
+
+ //TODO: An enum would be better
+ Q_PROPERTY(bool proportionalMagnitude READ proportionalMagnitude WRITE setProportionalMagnitude NOTIFY proprotionalMagnitudeChanged)
+ Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged)
+ Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
+
+public:
+ explicit QQuickTargetDirection(QObject *parent = 0);
+ virtual const QPointF sample(const QPointF &from);
+
+ qreal targetX() const
+ {
+ return m_targetX;
+ }
+
+ qreal targetY() const
+ {
+ return m_targetY;
+ }
+
+ qreal targetVariation() const
+ {
+ return m_targetVariation;
+ }
+
+ qreal magnitude() const
+ {
+ return m_magnitude;
+ }
+
+ bool proportionalMagnitude() const
+ {
+ return m_proportionalMagnitude;
+ }
+
+ qreal magnitudeVariation() const
+ {
+ return m_magnitudeVariation;
+ }
+
+ QQuickItem* targetItem() const
+ {
+ return m_targetItem;
+ }
+
+signals:
+
+ void targetXChanged(qreal arg);
+
+ void targetYChanged(qreal arg);
+
+ void targetVariationChanged(qreal arg);
+
+ void magnitudeChanged(qreal arg);
+
+ void proprotionalMagnitudeChanged(bool arg);
+
+ void magnitudeVariationChanged(qreal arg);
+
+ void targetItemChanged(QQuickItem* arg);
+
+public slots:
+ void setTargetX(qreal arg)
+ {
+ if (m_targetX != arg) {
+ m_targetX = arg;
+ emit targetXChanged(arg);
+ }
+ }
+
+ void setTargetY(qreal arg)
+ {
+ if (m_targetY != arg) {
+ m_targetY = arg;
+ emit targetYChanged(arg);
+ }
+ }
+
+ void setTargetVariation(qreal arg)
+ {
+ if (m_targetVariation != arg) {
+ m_targetVariation = arg;
+ emit targetVariationChanged(arg);
+ }
+ }
+
+ void setMagnitude(qreal arg)
+ {
+ if (m_magnitude != arg) {
+ m_magnitude = arg;
+ emit magnitudeChanged(arg);
+ }
+ }
+
+ void setProportionalMagnitude(bool arg)
+ {
+ if (m_proportionalMagnitude != arg) {
+ m_proportionalMagnitude = arg;
+ emit proprotionalMagnitudeChanged(arg);
+ }
+ }
+
+ void setMagnitudeVariation(qreal arg)
+ {
+ if (m_magnitudeVariation != arg) {
+ m_magnitudeVariation = arg;
+ emit magnitudeVariationChanged(arg);
+ }
+ }
+
+ void setTargetItem(QQuickItem* arg)
+ {
+ if (m_targetItem != arg) {
+ m_targetItem = arg;
+ emit targetItemChanged(arg);
+ }
+ }
+
+private:
+ qreal m_targetX;
+ qreal m_targetY;
+ qreal m_targetVariation;
+ bool m_proportionalMagnitude;
+ qreal m_magnitude;
+ qreal m_magnitudeVariation;
+ QQuickItem *m_targetItem;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // DIRECTEDVECTOR_H
diff --git a/src/declarative/particles/qquicktrailemitter.cpp b/src/quick/particles/qquicktrailemitter.cpp
index 272a3ebf84..272a3ebf84 100644
--- a/src/declarative/particles/qquicktrailemitter.cpp
+++ b/src/quick/particles/qquicktrailemitter.cpp
diff --git a/src/quick/particles/qquicktrailemitter_p.h b/src/quick/particles/qquicktrailemitter_p.h
new file mode 100644
index 0000000000..871d8b1b69
--- /dev/null
+++ b/src/quick/particles/qquicktrailemitter_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 FOLLOWEMITTER_H
+#define FOLLOWEMITTER_H
+#include "qquickparticleemitter_p.h"
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTrailEmitter : public QQuickParticleEmitter
+{
+ Q_OBJECT
+ Q_PROPERTY(QString follow READ follow WRITE setFollow NOTIFY followChanged)
+ Q_PROPERTY(int emitRatePerParticle READ particlesPerParticlePerSecond WRITE setParticlesPerParticlePerSecond NOTIFY particlesPerParticlePerSecondChanged)
+
+ Q_PROPERTY(QQuickParticleExtruder* emitShape READ emissonShape WRITE setEmissionShape NOTIFY emissionShapeChanged)
+ Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
+ Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
+
+ Q_ENUMS(EmitSize)
+public:
+ enum EmitSize {
+ ParticleSize = -2//Anything less than 0 will do
+ };
+ explicit QQuickTrailEmitter(QQuickItem *parent = 0);
+ virtual void emitWindow(int timeStamp);
+ virtual void reset();
+
+ int particlesPerParticlePerSecond() const
+ {
+ return m_particlesPerParticlePerSecond;
+ }
+
+ qreal emitterXVariation() const
+ {
+ return m_emitterXVariation;
+ }
+
+ qreal emitterYVariation() const
+ {
+ return m_emitterYVariation;
+ }
+
+ QString follow() const
+ {
+ return m_follow;
+ }
+
+ QQuickParticleExtruder* emissonShape() const
+ {
+ return m_emissionExtruder;
+ }
+
+signals:
+ void emitFollowParticles(QDeclarativeV8Handle particles, QDeclarativeV8Handle followed);
+
+ void particlesPerParticlePerSecondChanged(int arg);
+
+ void emitterXVariationChanged(qreal arg);
+
+ void emitterYVariationChanged(qreal arg);
+
+ void followChanged(QString arg);
+
+ void emissionShapeChanged(QQuickParticleExtruder* arg);
+
+public slots:
+
+ void setParticlesPerParticlePerSecond(int arg)
+ {
+ if (m_particlesPerParticlePerSecond != arg) {
+ m_particlesPerParticlePerSecond = arg;
+ emit particlesPerParticlePerSecondChanged(arg);
+ }
+ }
+ void setEmitterXVariation(qreal arg)
+ {
+ if (m_emitterXVariation != arg) {
+ m_emitterXVariation = arg;
+ emit emitterXVariationChanged(arg);
+ }
+ }
+
+ void setEmitterYVariation(qreal arg)
+ {
+ if (m_emitterYVariation != arg) {
+ m_emitterYVariation = arg;
+ emit emitterYVariationChanged(arg);
+ }
+ }
+
+ void setFollow(QString arg)
+ {
+ if (m_follow != arg) {
+ m_follow = arg;
+ emit followChanged(arg);
+ }
+ }
+
+ void setEmissionShape(QQuickParticleExtruder* arg)
+ {
+ if (m_emissionExtruder != arg) {
+ m_emissionExtruder = arg;
+ emit emissionShapeChanged(arg);
+ }
+ }
+
+private slots:
+ void recalcParticlesPerSecond();
+
+private:
+ QSet<QQuickParticleData*> m_pending;
+ QVector<qreal> m_lastEmission;
+ int m_particlesPerParticlePerSecond;
+ qreal m_lastTimeStamp;
+ qreal m_emitterXVariation;
+ qreal m_emitterYVariation;
+ QString m_follow;
+ int m_followCount;
+ QQuickParticleExtruder* m_emissionExtruder;
+ QQuickParticleExtruder* m_defaultEmissionExtruder;
+ bool isEmitFollowConnected();
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // FOLLOWEMITTER_H
diff --git a/src/declarative/particles/qquickturbulence.cpp b/src/quick/particles/qquickturbulence.cpp
index 0afd827af1..0afd827af1 100644
--- a/src/declarative/particles/qquickturbulence.cpp
+++ b/src/quick/particles/qquickturbulence.cpp
diff --git a/src/quick/particles/qquickturbulence_p.h b/src/quick/particles/qquickturbulence_p.h
new file mode 100644
index 0000000000..b7eb7e662f
--- /dev/null
+++ b/src/quick/particles/qquickturbulence_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 TURBULENCEAFFECTOR_H
+#define TURBULENCEAFFECTOR_H
+#include "qquickparticleaffector_p.h"
+#include <QDeclarativeListProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticlePainter;
+
+class QQuickTurbulenceAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
+ Q_PROPERTY(QUrl noiseSource READ noiseSource WRITE setNoiseSource NOTIFY noiseSourceChanged)
+ public:
+ explicit QQuickTurbulenceAffector(QQuickItem *parent = 0);
+ ~QQuickTurbulenceAffector();
+ virtual void affectSystem(qreal dt);
+
+ qreal strength() const
+ {
+ return m_strength;
+ }
+
+ QUrl noiseSource() const
+ {
+ return m_noiseSource;
+ }
+signals:
+
+ void strengthChanged(qreal arg);
+
+ void noiseSourceChanged(QUrl arg);
+
+public slots:
+
+ void setStrength(qreal arg)
+ {
+ if (m_strength != arg) {
+ m_strength = arg;
+ emit strengthChanged(arg);
+ }
+ }
+
+ void setNoiseSource(QUrl arg)
+ {
+ if (m_noiseSource != arg) {
+ m_noiseSource = arg;
+ emit noiseSourceChanged(arg);
+ initializeGrid();
+ }
+ }
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+private:
+ void ensureInit();
+ void mapUpdate();
+ void initializeGrid();
+ qreal boundsRespectingField(int x, int y);
+ qreal m_strength;
+ qreal m_lastT;
+ int m_gridSize;
+ qreal** m_field;
+ QPointF** m_vectorField;
+ bool m_inited;
+ QUrl m_noiseSource;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // TURBULENCEAFFECTOR_H
diff --git a/src/declarative/particles/qquickv8particledata.cpp b/src/quick/particles/qquickv8particledata.cpp
index 80ce355cd7..80ce355cd7 100644
--- a/src/declarative/particles/qquickv8particledata.cpp
+++ b/src/quick/particles/qquickv8particledata.cpp
diff --git a/src/quick/particles/qquickv8particledata_p.h b/src/quick/particles/qquickv8particledata_p.h
new file mode 100644
index 0000000000..f94a987aac
--- /dev/null
+++ b/src/quick/particles/qquickv8particledata_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 QQuickV8PARTICLEDATA_H
+#define QQuickV8PARTICLEDATA_H
+
+#include <private/qv8engine_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQuickParticleData;
+class QQuickV8ParticleData {
+public:
+ QQuickV8ParticleData(QV8Engine*,QQuickParticleData*);
+ ~QQuickV8ParticleData();
+ QDeclarativeV8Handle v8Value();
+private:
+ v8::Persistent<v8::Object> m_v8Value;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/declarative/particles/qquickwander.cpp b/src/quick/particles/qquickwander.cpp
index dfbff36076..dfbff36076 100644
--- a/src/declarative/particles/qquickwander.cpp
+++ b/src/quick/particles/qquickwander.cpp
diff --git a/src/quick/particles/qquickwander_p.h b/src/quick/particles/qquickwander_p.h
new file mode 100644
index 0000000000..f8a28e57e4
--- /dev/null
+++ b/src/quick/particles/qquickwander_p.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 WANDERAFFECTOR_H
+#define WANDERAFFECTOR_H
+#include <QHash>
+#include "qquickparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+struct WanderData{
+ qreal x_vel;
+ qreal y_vel;
+ qreal x_peak;
+ qreal x_var;
+ qreal y_peak;
+ qreal y_var;
+};
+
+class QQuickWanderAffector : public QQuickParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal pace READ pace WRITE setPace NOTIFY paceChanged)
+ Q_PROPERTY(qreal xVariance READ xVariance WRITE setXVariance NOTIFY xVarianceChanged)
+ Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged)
+ Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
+ Q_ENUMS(AffectableParameters)
+
+public:
+ enum AffectableParameters {
+ Position,
+ Velocity,
+ Acceleration
+ };
+
+ explicit QQuickWanderAffector(QQuickItem *parent = 0);
+ ~QQuickWanderAffector();
+ virtual void reset(int systemIdx);
+
+ qreal xVariance() const
+ {
+ return m_xVariance;
+ }
+
+ qreal yVariance() const
+ {
+ return m_yVariance;
+ }
+
+ qreal pace() const
+ {
+ return m_pace;
+ }
+
+ AffectableParameters affectedParameter() const
+ {
+ return m_affectedParameter;
+ }
+
+protected:
+ virtual bool affectParticle(QQuickParticleData *d, qreal dt);
+signals:
+
+ void xVarianceChanged(qreal arg);
+
+ void yVarianceChanged(qreal arg);
+
+ void paceChanged(qreal arg);
+
+
+ void affectedParameterChanged(AffectableParameters arg);
+
+public slots:
+void setXVariance(qreal arg)
+{
+ if (m_xVariance != arg) {
+ m_xVariance = arg;
+ emit xVarianceChanged(arg);
+ }
+}
+
+void setYVariance(qreal arg)
+{
+ if (m_yVariance != arg) {
+ m_yVariance = arg;
+ emit yVarianceChanged(arg);
+ }
+}
+
+void setPace(qreal arg)
+{
+ if (m_pace != arg) {
+ m_pace = arg;
+ emit paceChanged(arg);
+ }
+}
+
+
+void setAffectedParameter(AffectableParameters arg)
+{
+ if (m_affectedParameter != arg) {
+ m_affectedParameter = arg;
+ emit affectedParameterChanged(arg);
+ }
+}
+
+private:
+ WanderData* getData(int idx);
+ QHash<int, WanderData*> m_wanderData;
+ qreal m_xVariance;
+ qreal m_yVariance;
+ qreal m_pace;
+ AffectableParameters m_affectedParameter;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // WANDERAFFECTOR_H
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
new file mode 100644
index 0000000000..f5839af583
--- /dev/null
+++ b/src/quick/qtquick2.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qtquick2_p.h"
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativeutilmodule_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include <private/qquickitemsmodule_p.h>
+#include <private/qquickparticlesmodule_p.h>
+#include <private/qquickwindowmodule_p.h>
+
+#include <private/qdeclarativeenginedebugservice_p.h>
+#include <private/qdeclarativedebugstatesdelegate_p.h>
+#include <private/qdeclarativebinding_p.h>
+#include <private/qdeclarativecontext_p.h>
+#include <QtQuick/private/qdeclarativepropertychanges_p.h>
+#include <QtQuick/private/qdeclarativestate_p.h>
+#include <qdeclarativeproperty.h>
+#include <QtCore/QWeakPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeQtQuick2DebugStatesDelegate : public QDeclarativeDebugStatesDelegate
+{
+public:
+ QDeclarativeQtQuick2DebugStatesDelegate();
+ virtual ~QDeclarativeQtQuick2DebugStatesDelegate();
+ virtual void buildStatesList(QDeclarativeContext *ctxt, bool cleanList);
+ virtual void updateBinding(QDeclarativeContext *context,
+ const QDeclarativeProperty &property,
+ const QVariant &expression, bool isLiteralValue,
+ const QString &fileName, int line,
+ bool *isBaseState);
+ virtual bool setBindingForInvalidProperty(QObject *object,
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue);
+ virtual void resetBindingForInvalidProperty(QObject *object,
+ const QString &propertyName);
+
+private:
+ void buildStatesList(QObject *obj);
+
+ QList<QWeakPointer<QDeclarativeState> > m_allStates;
+};
+
+QDeclarativeQtQuick2DebugStatesDelegate::QDeclarativeQtQuick2DebugStatesDelegate()
+{
+}
+
+QDeclarativeQtQuick2DebugStatesDelegate::~QDeclarativeQtQuick2DebugStatesDelegate()
+{
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QDeclarativeContext *ctxt, bool cleanList)
+{
+ if (cleanList)
+ m_allStates.clear();
+
+ QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ buildStatesList(ctxtPriv->instances.at(ii));
+ }
+
+ QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts;
+ while (child) {
+ buildStatesList(child->asQDeclarativeContext());
+ child = child->nextChild;
+ }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::buildStatesList(QObject *obj)
+{
+ if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
+ m_allStates.append(state);
+ }
+
+ QObjectList children = obj->children();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ buildStatesList(children.at(ii));
+ }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::updateBinding(QDeclarativeContext *context,
+ const QDeclarativeProperty &property,
+ const QVariant &expression, bool isLiteralValue,
+ const QString &fileName, int line,
+ bool *inBaseState)
+{
+ QObject *object = property.object();
+ QString propertyName = property.name();
+ foreach (QWeakPointer<QDeclarativeState> statePointer, m_allStates) {
+ if (QDeclarativeState *state = statePointer.data()) {
+ // here we assume that the revert list on itself defines the base state
+ if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
+ *inBaseState = false;
+
+ QDeclarativeBinding *newBinding = 0;
+ if (!isLiteralValue) {
+ newBinding = new QDeclarativeBinding(expression.toString(), object, context);
+ newBinding->setTarget(property);
+ newBinding->setNotifyOnValueChanged(true);
+ newBinding->setSourceLocation(fileName, line);
+ }
+
+ state->changeBindingInRevertList(object, propertyName, newBinding);
+
+ if (isLiteralValue)
+ state->changeValueInRevertList(object, propertyName, expression);
+ }
+ }
+ }
+}
+
+bool QDeclarativeQtQuick2DebugStatesDelegate::setBindingForInvalidProperty(QObject *object,
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue)
+{
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ if (isLiteralValue)
+ propertyChanges->changeValue(propertyName, expression);
+ else
+ propertyChanges->changeExpression(propertyName, expression.toString());
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void QDeclarativeQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *object, const QString &propertyName)
+{
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ propertyChanges->removeProperty(propertyName);
+ }
+}
+
+
+void QDeclarativeQtQuick2Module::defineModule()
+{
+ QDeclarativeUtilModule::defineModule();
+ QDeclarativeEnginePrivate::defineModule();
+ QQuickItemsModule::defineModule();
+ QQuickParticlesModule::defineModule();
+ QQuickWindowModule::defineModule();
+ QDeclarativeValueTypeFactory::registerValueTypes();
+
+ if (QDeclarativeEngineDebugService::isDebuggingEnabled()) {
+ QDeclarativeEngineDebugService::instance()->setStatesDelegate(
+ new QDeclarativeQtQuick2DebugStatesDelegate);
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/qtquick2_p.h b/src/quick/qtquick2_p.h
new file mode 100644
index 0000000000..4fa302dee6
--- /dev/null
+++ b/src/quick/qtquick2_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QTQUICK2_P_H
+#define QTQUICK2_P_H
+
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeQtQuick2Module
+{
+public:
+ static void defineModule();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTQUICK2_P_H
diff --git a/src/quick/qtquickglobal.h b/src/quick/qtquickglobal.h
new file mode 100644
index 0000000000..8619281f29
--- /dev/null
+++ b/src/quick/qtquickglobal.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QTQUICKGLOBAL_H
+#define QTQUICKGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+# if defined(QT_MAKEDLL) /* create a Qt DLL library */
+# if defined(QT_BUILD_QUICK_LIB)
+# define Q_QUICK_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICK_EXPORT Q_DECL_IMPORT
+# endif
+# elif defined(QT_DLL) /* use a Qt DLL library */
+# define Q_QUICK_EXPORT Q_DECL_IMPORT
+# endif
+#endif
+
+#if !defined(Q_QUICK_EXPORT)
+# if defined(QT_SHARED)
+# define Q_QUICK_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICK_EXPORT
+# endif
+#endif
+
+#endif // QTQUICKGLOBAL_H
diff --git a/src/quick/qtquickglobal_p.h b/src/quick/qtquickglobal_p.h
new file mode 100644
index 0000000000..6385645ead
--- /dev/null
+++ b/src/quick/qtquickglobal_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QTQUICKGLOBAL_P_H
+#define QTQUICKGLOBAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtquickglobal.h"
+
+#define Q_QUICK_PRIVATE_EXPORT Q_QUICK_EXPORT
+
+#endif // QTQUICKGLOBAL_P_H
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
new file mode 100644
index 0000000000..b445e84248
--- /dev/null
+++ b/src/quick/quick.pro
@@ -0,0 +1,47 @@
+load(qt_module)
+
+TARGET = QtQuick
+
+CONFIG += module
+CONFIG += dll warn_on
+MODULE_PRI = ../../modules/qt_quick.pri
+
+QT = core-private gui gui-private network v8-private declarative declarative-private
+
+DEFINES += QT_BUILD_QUICK_LIB QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
+win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
+solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+
+exists("qdeclarative_enable_gcov") {
+ QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
+ LIBS += -lgcov
+}
+
+load(qt_module_config)
+
+include(util/util.pri)
+include(scenegraph/scenegraph.pri)
+include(items/items.pri)
+include(particles/particles.pri)
+include(designer/designer.pri)
+
+HEADERS += \
+ qtquickglobal.h \
+ qtquickglobal_p.h \
+ qtquick2_p.h
+
+SOURCES += qtquick2.cpp
+
+mac {
+ # FIXME: this is a workaround for broken qmake logic in qtAddModule()
+ # This function refuses to use frameworks unless the framework exists on
+ # the filesystem at the time qmake is run, resulting in a build failure
+ # if QtQuick is qmaked before QtDeclarative is built and frameworks are
+ # in use. qtAddLibrary() contains correct logic to deal with this, so
+ # we'll explicitly call that for now.
+ load(qt)
+ LIBS -= -lQtDeclarative # in non-framework builds, these should be re-added
+ LIBS -= -lQtDeclarative_debug # within the qtAddLibrary if appropriate, so no
+ qtAddLibrary(QtDeclarative) # harm done :)
+}
+
diff --git a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp b/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp
index 56a6e0e5d9..56a6e0e5d9 100644
--- a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp
diff --git a/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h b/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h
new file mode 100644
index 0000000000..a4c2ffbdbc
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QMLRENDERER_H
+#define QMLRENDERER_H
+
+#include "qsgrenderer_p.h"
+
+#include <QtGui/private/qdatabuffer_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGDefaultRenderer : public QSGRenderer
+{
+ Q_OBJECT
+public:
+ class IndexGeometryNodePair : public QPair<int, QSGGeometryNode *>
+ {
+ public:
+ IndexGeometryNodePair(int i, QSGGeometryNode *n);
+ bool operator < (const IndexGeometryNodePair &other) const;
+ };
+
+
+ // Minimum heap.
+ class IndexGeometryNodePairHeap
+ {
+ public:
+ IndexGeometryNodePairHeap();
+ void insert(const IndexGeometryNodePair &x);
+ const IndexGeometryNodePair &top() const { return v.first(); }
+ IndexGeometryNodePair pop();
+ bool isEmpty() const { return v.isEmpty(); }
+ private:
+ static int parent(int i) { return (i - 1) >> 1; }
+ static int left(int i) { return (i << 1) | 1; }
+ static int right(int i) { return (i + 1) << 1; }
+ QDataBuffer<IndexGeometryNodePair> v;
+ };
+
+ QSGDefaultRenderer(QSGContext *context);
+
+ void render();
+
+ void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
+
+ void setSortFrontToBackEnabled(bool sort);
+ bool isSortFrontToBackEnabled() const;
+
+private:
+ void buildLists(QSGNode *node);
+ void renderNodes(const QDataBuffer<QSGGeometryNode *> &list);
+
+ const QSGClipNode *m_currentClip;
+ QSGMaterial *m_currentMaterial;
+ QSGMaterialShader *m_currentProgram;
+ const QMatrix4x4 *m_currentMatrix;
+ QMatrix4x4 m_renderOrderMatrix;
+ QDataBuffer<QSGGeometryNode *> m_opaqueNodes;
+ QDataBuffer<QSGGeometryNode *> m_transparentNodes;
+ QDataBuffer<QSGGeometryNode *> m_tempNodes;
+ IndexGeometryNodePairHeap m_heap;
+
+ bool m_rebuild_lists;
+ bool m_needs_sorting;
+ bool m_sort_front_to_back;
+ int m_currentRenderOrder;
+
+#ifdef QML_RUNTIME_TESTING
+ bool m_render_opaque_nodes;
+ bool m_render_alpha_nodes;
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLRENDERER_H
diff --git a/src/declarative/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index 8661c9af93..8661c9af93 100644
--- a/src/declarative/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h
new file mode 100644
index 0000000000..aea6f0b94b
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsggeometry.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt scene graph research project.
+**
+** $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 QSGGEOMETRY_H
+#define QSGGEOMETRY_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtGui/qopengl.h>
+#include <QRectF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGGeometryData;
+
+class Q_QUICK_EXPORT QSGGeometry
+{
+public:
+
+ struct Attribute
+ {
+ int position;
+ int tupleSize;
+ int type;
+
+ uint isVertexCoordinate : 1;
+ uint migrateYourCodeToUseTheCreateFunction: 31; // ### Remove before release
+
+ static Attribute create(int pos, int tupleSize, int primitiveType, bool isPosition = false);
+ };
+
+ struct AttributeSet {
+ int count;
+ int stride;
+ const Attribute *attributes;
+ };
+
+ struct Point2D {
+ float x, y;
+ void set(float nx, float ny) {
+ x = nx; y = ny;
+ }
+ };
+ struct TexturedPoint2D {
+ float x, y;
+ float tx, ty;
+ void set(float nx, float ny, float ntx, float nty) {
+ x = nx; y = ny; tx = ntx; ty = nty;
+ }
+ };
+ struct ColoredPoint2D {
+ float x, y;
+ unsigned char r, g, b, a;
+ void set(float nx, float ny, uchar nr, uchar ng, uchar nb, uchar na) {
+ x = nx; y = ny;
+ r = nr; g = ng, b = nb; a = na;
+ }
+ };
+
+ static const AttributeSet &defaultAttributes_Point2D();
+ static const AttributeSet &defaultAttributes_TexturedPoint2D();
+ static const AttributeSet &defaultAttributes_ColoredPoint2D();
+
+ enum DataPattern {
+ AlwaysUploadPattern = 0,
+ StreamPattern = 1,
+ DynamicPattern = 2,
+ StaticPattern = 3
+ };
+
+ QSGGeometry(const QSGGeometry::AttributeSet &attribs,
+ int vertexCount,
+ int indexCount = 0,
+ int indexType = GL_UNSIGNED_SHORT);
+ virtual ~QSGGeometry();
+
+ void setDrawingMode(GLenum mode);
+ inline GLenum drawingMode() const { return m_drawing_mode; }
+
+ void allocate(int vertexCount, int indexCount = 0);
+
+ int vertexCount() const { return m_vertex_count; }
+
+ void *vertexData() { return m_data; }
+ inline Point2D *vertexDataAsPoint2D();
+ inline TexturedPoint2D *vertexDataAsTexturedPoint2D();
+ inline ColoredPoint2D *vertexDataAsColoredPoint2D();
+
+ inline const void *vertexData() const { return m_data; }
+ inline const Point2D *vertexDataAsPoint2D() const;
+ inline const TexturedPoint2D *vertexDataAsTexturedPoint2D() const;
+ inline const ColoredPoint2D *vertexDataAsColoredPoint2D() const;
+
+ inline int indexType() const { return m_index_type; }
+
+ int indexCount() const { return m_index_count; }
+
+ void *indexData();
+ inline uint *indexDataAsUInt();
+ inline quint16 *indexDataAsUShort();
+
+ inline int sizeOfIndex() const;
+
+ const void *indexData() const;
+ inline const uint *indexDataAsUInt() const;
+ inline const quint16 *indexDataAsUShort() const;
+
+ inline int attributeCount() const { return m_attributes.count; }
+ inline const Attribute *attributes() const { return m_attributes.attributes; }
+ inline int sizeOfVertex() const { return m_attributes.stride; }
+
+ static void updateRectGeometry(QSGGeometry *g, const QRectF &rect);
+ static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect);
+
+ void setIndexDataPattern(DataPattern p);
+ DataPattern indexDataPattern() const { return (DataPattern) m_index_usage_pattern; }
+
+ void setVertexDataPattern(DataPattern p);
+ DataPattern vertexDataPattern() const { return (DataPattern) m_vertex_usage_pattern; }
+
+ void markIndexDataDirty();
+ void markVertexDataDirty();
+
+private:
+ friend class QSGGeometryData;
+
+ int m_drawing_mode;
+ int m_vertex_count;
+ int m_index_count;
+ int m_index_type;
+ const AttributeSet &m_attributes;
+ void *m_data;
+ int m_index_data_offset;
+
+ QSGGeometryData *m_server_data;
+
+ uint m_owns_data : 1;
+ uint m_index_usage_pattern : 2;
+ uint m_vertex_usage_pattern : 2;
+ uint m_dirty_index_data : 1;
+ uint m_dirty_vertex_data : 1;
+ uint m_reserved_bits : 27;
+
+ float m_prealloc[16];
+};
+
+inline uint *QSGGeometry::indexDataAsUInt()
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
+ return (uint *) indexData();
+}
+
+inline quint16 *QSGGeometry::indexDataAsUShort()
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
+ return (quint16 *) indexData();
+}
+
+inline const uint *QSGGeometry::indexDataAsUInt() const
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
+ return (uint *) indexData();
+}
+
+inline const quint16 *QSGGeometry::indexDataAsUShort() const
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
+ return (quint16 *) indexData();
+}
+
+inline QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 1);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ return (Point2D *) m_data;
+}
+
+inline QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
+ return (TexturedPoint2D *) m_data;
+}
+
+inline QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
+ return (ColoredPoint2D *) m_data;
+}
+
+inline const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 1);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ return (const Point2D *) m_data;
+}
+
+inline const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
+ return (const TexturedPoint2D *) m_data;
+}
+
+inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
+ return (const ColoredPoint2D *) m_data;
+}
+
+int QSGGeometry::sizeOfIndex() const
+{
+ if (m_index_type == GL_UNSIGNED_SHORT) return 2;
+ else if (m_index_type == GL_UNSIGNED_BYTE) return 1;
+ else if (m_index_type == GL_UNSIGNED_INT) return 4;
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGGEOMETRY_H
diff --git a/src/declarative/scenegraph/coreapi/qsggeometry_p.h b/src/quick/scenegraph/coreapi/qsggeometry_p.h
index ef2935ae4c..ef2935ae4c 100644
--- a/src/declarative/scenegraph/coreapi/qsggeometry_p.h
+++ b/src/quick/scenegraph/coreapi/qsggeometry_p.h
diff --git a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 36b50e89b6..36b50e89b6 100644
--- a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h
new file mode 100644
index 0000000000..d8411b4d88
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 MATERIAL_H
+#define MATERIAL_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <qopenglshaderprogram.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGMaterial;
+
+class Q_QUICK_EXPORT QSGMaterialShader
+{
+public:
+ class Q_QUICK_EXPORT RenderState {
+ public:
+ enum DirtyState
+ {
+ DirtyMatrix = 0x0001,
+ DirtyOpacity = 0x0002
+ };
+ Q_DECLARE_FLAGS(DirtyStates, DirtyState)
+
+ inline DirtyStates dirtyStates() const { return m_dirty; }
+
+ inline bool isMatrixDirty() const { return m_dirty & DirtyMatrix; }
+ inline bool isOpacityDirty() const { return m_dirty & DirtyOpacity; }
+
+ float opacity() const;
+ QMatrix4x4 combinedMatrix() const;
+ QMatrix4x4 modelViewMatrix() const;
+ QRect viewportRect() const;
+ QRect deviceRect() const;
+
+ QOpenGLContext *context() const;
+
+ private:
+ friend class QSGRenderer;
+ DirtyStates m_dirty;
+ const void *m_data;
+ };
+
+ QSGMaterialShader();
+
+ virtual void activate();
+ virtual void deactivate();
+ // First time a material is used, oldMaterial is null.
+ virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
+ virtual char const *const *attributeNames() const = 0; // Array must end with null.
+
+ inline QOpenGLShaderProgram *program() { return &m_program; }
+
+protected:
+
+ friend class QSGContext;
+
+ virtual void compile();
+ virtual void initialize() { }
+
+ virtual const char *vertexShader() const = 0;
+ virtual const char *fragmentShader() const = 0;
+
+private:
+ QOpenGLShaderProgram m_program;
+ void *m_reserved;
+};
+
+struct QSGMaterialType { };
+
+class Q_QUICK_EXPORT QSGMaterial
+{
+public:
+ enum Flag {
+ Blending = 0x0001
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QSGMaterial();
+ virtual ~QSGMaterial();
+
+ virtual QSGMaterialType *type() const = 0;
+ virtual QSGMaterialShader *createShader() const = 0;
+ virtual int compare(const QSGMaterial *other) const;
+
+ QSGMaterial::Flags flags() const { return m_flags; }
+ void setFlag(Flags flags, bool on = true);
+
+private:
+ Flags m_flags;
+ void *m_reserved;
+ Q_DISABLE_COPY(QSGMaterial)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGMaterial::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGMaterialShader::RenderState::DirtyStates)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
new file mode 100644
index 0000000000..2d6828323c
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -0,0 +1,1264 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgnode.h"
+#include "qsgrenderer_p.h"
+#include "qsgnodeupdater_p.h"
+#include "qsgmaterial.h"
+
+#include "limits.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_DEBUG
+static int qt_node_count = 0;
+
+static void qt_print_node_count()
+{
+ qDebug("Number of leaked nodes: %i", qt_node_count);
+ qt_node_count = -1;
+}
+#endif
+
+/*!
+ \class QSGNode
+ \brief The QSGNode class is the base class for all nodes in the scene graph.
+
+ \inmodule QtQuick
+
+ The QSGNode class can be used as a child container. Children are added with
+ the appendChildNode(), prependChildNode(), insertChildNodeBefore() and
+ insertChildNodeAfter(). Ordering of nodes is important as geometry nodes
+ will be rendered in the order they are added to the scene graph.
+ Actually, the scene may reorder nodes freely, but the resulting visual
+ order is still guaranteed.
+
+ If nodes change every frame, the preprocess() function can be used to
+ apply changes to a node for every frame its rendered. The use of preprocess()
+ must be explicitly enabled by setting the QSGNode::UsePreprocess flag
+ on the node.
+
+ The virtual isSubtreeBlocked() function can be used to disable a subtree all
+ together. Nodes in a blocked subtree will not be preprocessed() and not
+ rendered.
+
+ Anything related to QSGNode should happen on the scene graph rendering thread.
+ */
+
+QSGNode::QSGNode()
+ : m_parent(0)
+ , m_type(BasicNodeType)
+ , m_firstChild(0)
+ , m_lastChild(0)
+ , m_nextSibling(0)
+ , m_previousSibling(0)
+ , m_subtreeGeometryCount(0)
+ , m_nodeFlags(OwnedByParent)
+ , m_flags(0)
+{
+ init();
+}
+
+QSGNode::QSGNode(NodeType type)
+ : m_parent(0)
+ , m_type(type)
+ , m_firstChild(0)
+ , m_lastChild(0)
+ , m_nextSibling(0)
+ , m_previousSibling(0)
+ , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
+ , m_nodeFlags(OwnedByParent)
+ , m_flags(0)
+{
+ init();
+}
+
+void QSGNode::init()
+{
+#ifndef QT_NO_DEBUG
+ ++qt_node_count;
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_print_node_count);
+ atexit_registered = true;
+ }
+#endif
+}
+
+QSGNode::~QSGNode()
+{
+#ifndef QT_NO_DEBUG
+ --qt_node_count;
+ if (qt_node_count < 0)
+ qDebug("Node destroyed after qt_print_node_count() was called.");
+#endif
+ destroy();
+}
+
+
+/*!
+ \fn void QSGNode::preprocess()
+
+ Override this function to do processing on the node before it is rendered.
+
+ Preprocessing needs to be explicitly enabled by setting the flag
+ QSGNode::UsePreprocess. The flag needs to be set before the node is added
+ to the scene graph and will cause the preprocess() function to be called
+ for every frame the node is rendered.
+
+ The preprocess function is called before the update pass that propegates
+ opacity and transformations through the scene graph. That means that
+ functions like QSGOpacityNode::combinedOpacity() and
+ QSGTransformNode::combinedMatrix() will not contain up-to-date values.
+ If such values are changed during the preprocess, these changes will be
+ propegated through the scene graph before it is rendered.
+
+ \warning Beware of deleting nodes while they are being preprocessed. It is
+ possible, with a small performance hit, to delete a single node during its
+ own preprocess call. Deleting a subtree which has nodes that also use
+ preprocessing may result in a segmentation fault. This is done for
+ performance reasons.
+ */
+
+
+
+
+/*!
+ Returns whether this node and its subtree is available for use.
+
+ Blocked subtrees will not get their dirty states updated and they
+ will not be rendered.
+
+ The QSGOpacityNode will return a blocked subtree when accumulated opacity
+ is 0, for instance.
+ */
+
+bool QSGNode::isSubtreeBlocked() const
+{
+ return m_subtreeGeometryCount == 0;
+}
+
+/*!
+ \internal
+ Detaches the node from the scene graph and deletes any children it owns.
+
+ This function is called from QSGNode's and QSGRootNode's destructor. It
+ should not be called explicitly in user code. QSGRootNode needs to call
+ destroy() because destroy() calls removeChildNode() which in turn calls
+ markDirty() which type-casts the node to QSGRootNode. This type-cast is not
+ valid at the time QSGNode's destructor is called because the node will
+ already be partially destroyed at that point.
+*/
+
+void QSGNode::destroy()
+{
+ if (m_parent) {
+ m_parent->removeChildNode(this);
+ Q_ASSERT(m_parent == 0);
+ }
+ while (m_firstChild) {
+ QSGNode *child = m_firstChild;
+ removeChildNode(child);
+ Q_ASSERT(child->m_parent == 0);
+ if (child->flags() & OwnedByParent)
+ delete child;
+ }
+
+ Q_ASSERT(m_firstChild == 0 && m_lastChild == 0);
+}
+
+
+/*!
+ Prepends \a node to this node's the list of children.
+
+ Ordering of nodes is important as geometry nodes will be rendered in the
+ order they are added to the scene graph.
+ */
+
+void QSGNode::prependChildNode(QSGNode *node)
+{
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
+ Q_ASSERT_X(!node->m_parent, "QSGNode::prependChildNode", "QSGNode already has a parent");
+
+#ifndef QT_NO_DEBUG
+ if (node->type() == QSGNode::GeometryNodeType) {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
+ Q_ASSERT_X(g->material(), "QSGNode::prependChildNode", "QSGGeometryNode is missing material");
+ Q_ASSERT_X(g->geometry(), "QSGNode::prependChildNode", "QSGGeometryNode is missing geometry");
+ }
+#endif
+
+ if (m_firstChild)
+ m_firstChild->m_previousSibling = node;
+ else
+ m_lastChild = node;
+ node->m_nextSibling = m_firstChild;
+ m_firstChild = node;
+ node->m_parent = this;
+
+ node->markDirty(DirtyNodeAdded);
+}
+
+/*!
+ Appends \a node to this node's list of children.
+
+ Ordering of nodes is important as geometry nodes will be rendered in the
+ order they are added to the scene graph.
+ */
+
+void QSGNode::appendChildNode(QSGNode *node)
+{
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
+ Q_ASSERT_X(!node->m_parent, "QSGNode::appendChildNode", "QSGNode already has a parent");
+
+#ifndef QT_NO_DEBUG
+ if (node->type() == QSGNode::GeometryNodeType) {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
+ Q_ASSERT_X(g->material(), "QSGNode::appendChildNode", "QSGGeometryNode is missing material");
+ Q_ASSERT_X(g->geometry(), "QSGNode::appendChildNode", "QSGGeometryNode is missing geometry");
+ }
+#endif
+
+ if (m_lastChild)
+ m_lastChild->m_nextSibling = node;
+ else
+ m_firstChild = node;
+ node->m_previousSibling = m_lastChild;
+ m_lastChild = node;
+ node->m_parent = this;
+
+ node->markDirty(DirtyNodeAdded);
+}
+
+
+
+/*!
+ Inserts \a node to this node's list of children before the node specified with \a before.
+
+ Ordering of nodes is important as geometry nodes will be rendered in the
+ order they are added to the scene graph.
+ */
+
+void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
+{
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
+ Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeBefore", "QSGNode already has a parent");
+ Q_ASSERT_X(before && before->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
+
+#ifndef QT_NO_DEBUG
+ if (node->type() == QSGNode::GeometryNodeType) {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
+ Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing material");
+ Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing geometry");
+ }
+#endif
+
+ QSGNode *previous = before->m_previousSibling;
+ if (previous)
+ previous->m_nextSibling = node;
+ else
+ m_firstChild = node;
+ node->m_previousSibling = previous;
+ node->m_nextSibling = before;
+ before->m_previousSibling = node;
+ node->m_parent = this;
+
+ node->markDirty(DirtyNodeAdded);
+}
+
+
+
+/*!
+ Inserts \a node to this node's list of children after the node specified with \a after.
+
+ Ordering of nodes is important as geometry nodes will be rendered in the
+ order they are added to the scene graph.
+ */
+
+void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
+{
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
+ Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent");
+ Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
+
+#ifndef QT_NO_DEBUG
+ if (node->type() == QSGNode::GeometryNodeType) {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
+ Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing material");
+ Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing geometry");
+ }
+#endif
+
+ QSGNode *next = after->m_nextSibling;
+ if (next)
+ next->m_previousSibling = node;
+ else
+ m_lastChild = node;
+ node->m_nextSibling = next;
+ node->m_previousSibling = after;
+ after->m_nextSibling = node;
+ node->m_parent = this;
+
+ node->markDirty(DirtyNodeAdded);
+}
+
+
+
+/*!
+ Removes \a node from this node's list of children.
+ */
+
+void QSGNode::removeChildNode(QSGNode *node)
+{
+ //Q_ASSERT(m_children.contains(node));
+ Q_ASSERT(node->parent() == this);
+
+ QSGNode *previous = node->m_previousSibling;
+ QSGNode *next = node->m_nextSibling;
+ if (previous)
+ previous->m_nextSibling = next;
+ else
+ m_firstChild = next;
+ if (next)
+ next->m_previousSibling = previous;
+ else
+ m_lastChild = previous;
+ node->m_previousSibling = 0;
+ node->m_nextSibling = 0;
+
+ node->markDirty(DirtyNodeRemoved);
+ node->m_parent = 0;
+}
+
+
+/*!
+ Removes all child nodes from this node's list of children.
+ */
+
+void QSGNode::removeAllChildNodes()
+{
+ while (m_firstChild) {
+ QSGNode *node = m_firstChild;
+ m_firstChild = node->m_nextSibling;
+ node->m_nextSibling = 0;
+ if (m_firstChild)
+ m_firstChild->m_previousSibling = 0;
+ else
+ m_lastChild = 0;
+ node->markDirty(DirtyNodeRemoved);
+ node->m_parent = 0;
+ }
+}
+
+
+int QSGNode::childCount() const
+{
+ int count = 0;
+ QSGNode *n = m_firstChild;
+ while (n) {
+ ++count;
+ n = n->m_nextSibling;
+ }
+ return count;
+}
+
+
+QSGNode *QSGNode::childAtIndex(int i) const
+{
+ QSGNode *n = m_firstChild;
+ while (i && n) {
+ --i;
+ n = n->m_nextSibling;
+ }
+ return n;
+}
+
+
+/*!
+ Sets the flag \a f on this node if \a enabled is true;
+ otherwise clears the flag.
+
+ \sa flags()
+*/
+
+void QSGNode::setFlag(Flag f, bool enabled)
+{
+ if (enabled)
+ m_nodeFlags |= f;
+ else
+ m_nodeFlags &= ~f;
+}
+
+
+/*!
+ Sets the flags \a f on this node if \a enabled is true;
+ otherwise clears the flags.
+
+ \sa flags()
+*/
+
+void QSGNode::setFlags(Flags f, bool enabled)
+{
+ if (enabled)
+ m_nodeFlags |= f;
+ else
+ m_nodeFlags &= ~f;
+}
+
+
+
+/*!
+ Marks this node with the states in \a flags as dirty.
+
+ When a node is marked dirty, it recursively mark the parent chain
+ as dirty and notify all connected renderers that the has dirty states.
+ */
+
+void QSGNode::markDirty(DirtyFlags flags)
+{
+ m_flags |= (flags & DirtyPropagationMask);
+
+ DirtyFlags subtreeFlags = DirtyFlags((flags & DirtyPropagationMask) << 16);
+
+ int geometryCountDiff = 0;
+ if (flags & DirtyNodeAdded)
+ geometryCountDiff += m_subtreeGeometryCount;
+ if (flags & DirtyNodeRemoved)
+ geometryCountDiff -= m_subtreeGeometryCount;
+
+ QSGNode *p = m_parent;
+ while (p) {
+ p->m_flags |= subtreeFlags;
+ p->m_subtreeGeometryCount += geometryCountDiff;
+ if (p->type() == RootNodeType)
+ static_cast<QSGRootNode *>(p)->notifyNodeChange(this, flags);
+ p = p->m_parent;
+ }
+}
+
+
+
+/*!
+ \class QSGBasicGeometryNode
+ \brief The QSGBasicGeometryNode class serves as a baseclass for geometry based nodes
+
+ \inmodule QtQuick
+
+ The QSGBasicGeometryNode class should not be used by itself. It is only encapsulates
+ shared functionality between the QSGGeometryNode and QSGClipNode classes.
+ */
+
+
+/*!
+ Creates a new basic geometry node.
+ */
+QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
+ : QSGNode(type)
+ , m_geometry(0)
+ , m_matrix(0)
+ , m_clip_list(0)
+{
+}
+
+
+/*!
+ Deletes this QSGBasicGeometryNode.
+
+ If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
+ geometry object it is pointing to. This flag is not set by default.
+ */
+
+QSGBasicGeometryNode::~QSGBasicGeometryNode()
+{
+ if (flags() & OwnsGeometry)
+ delete m_geometry;
+}
+
+
+/*!
+ \fn QSGGeometry *QSGBasicGeometryNode::geometry() const
+
+ Returns this node's geometry.
+
+ The geometry is null by default.
+ */
+
+
+/*!
+ Sets the geometry of this node to \a geometry.
+
+ If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
+ geometry object it is pointing to. This flag is not set by default.
+ */
+
+void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
+{
+ if (flags() & OwnsGeometry)
+ delete m_geometry;
+ m_geometry = geometry;
+ markDirty(DirtyGeometry);
+}
+
+
+
+/*!
+ \class QSGGeometryNode
+ \brief The QSGGeometryNode class is used for all rendered content in the scene graph.
+
+ \inmodule QtQuick
+
+ The QSGGeometryNode consists of geometry and material. The geometry defines the mesh,
+ the vertices and their structure, to be drawn. The Material defines how the shape is
+ filled.
+
+ A geometry node must have both geometry and a normal material before it is added to
+ the scene graph.
+
+ The geometry node supports two types of materials, the opaqueMaterial and the normal
+ material. The opaqueMaterial is used when the accumulated scene graph opacity at the
+ time of rendering is 1. The primary usecase is to special case opaque rendering
+ to avoid an extra operation in the fragment shader can have significant performance
+ impact on embedded graphics chips. The opaque material is optional.
+
+ */
+
+
+/*!
+ Creates a new geometry node without geometry and material.
+ */
+
+QSGGeometryNode::QSGGeometryNode()
+ : QSGBasicGeometryNode(GeometryNodeType)
+ , m_render_order(0)
+ , m_material(0)
+ , m_opaque_material(0)
+ , m_opacity(1)
+{
+}
+
+
+/*!
+ Deletes this geometry node.
+
+ The flags QSGNode::OwnsMaterial, QSGNode::OwnsOpaqueMaterial and
+ QSGNode::OwnsGeometry decides weither the geometry node should also
+ delete the materials and geometry. By default, these flags are disabled.
+ */
+
+QSGGeometryNode::~QSGGeometryNode()
+{
+ if (flags() & OwnsMaterial)
+ delete m_material;
+ if (flags() & OwnsOpaqueMaterial)
+ delete m_opaque_material;
+}
+
+
+
+/*!
+ \fn int QSGGeometryNode::renderOrder() const
+
+ Returns the render order of this geometry node.
+
+ \internal
+ */
+
+
+/*!
+ Sets the render order of this node to be \a order.
+
+ GeometryNodes are rendered in an order that visually looks like
+ low order nodes are rendered prior to high order nodes. For opaque
+ geometry there is little difference as z-testing will handle
+ the discard, but for translucent objects, the rendering should
+ normally be specified in the order of back-to-front.
+
+ The default render order is 0.
+
+ \internal
+ */
+void QSGGeometryNode::setRenderOrder(int order)
+{
+ m_render_order = order;
+}
+
+
+
+/*!
+ Sets the material of this geometry node to \a material.
+
+ Geometry nodes must have a material before they can be added to the
+ scene graph.
+ */
+void QSGGeometryNode::setMaterial(QSGMaterial *material)
+{
+ if (flags() & OwnsMaterial)
+ delete m_material;
+ m_material = material;
+#ifndef QT_NO_DEBUG
+ if (m_material != 0 && m_opaque_material == m_material)
+ qWarning("QSGGeometryNode: using same material for both opaque and translucent");
+#endif
+ markDirty(DirtyMaterial);
+}
+
+
+
+/*!
+ Sets the opaque material of this geometry to \a material.
+
+ The opaque material will be preferred by the renderer over the
+ default material, as returned by the material() function, if
+ it is not null and the geometry item has an inherited opacity of
+ 1.
+
+ The opaqueness refers to scene graph opacity, the material is still
+ allowed to set QSGMaterial::Blending to true and draw transparent
+ pixels.
+ */
+void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
+{
+ if (flags() & OwnsOpaqueMaterial)
+ delete m_opaque_material;
+ m_opaque_material = material;
+#ifndef QT_NO_DEBUG
+ if (m_opaque_material != 0 && m_opaque_material == m_material)
+ qWarning("QSGGeometryNode: using same material for both opaque and translucent");
+#endif
+
+ markDirty(DirtyMaterial);
+}
+
+
+
+/*!
+ Returns the material which should currently be used for geometry node.
+
+ If the inherited opacity of the node is 1 and there is an opaque material
+ set on this node, it will be returned; otherwise, the default material
+ will be returned.
+
+ \warning This function requires the scene graph above this item to be
+ completely free of dirty states, so it can only be called during rendering
+
+ \internal
+
+ \sa setMaterial, setOpaqueMaterial
+ */
+QSGMaterial *QSGGeometryNode::activeMaterial() const
+{
+ Q_ASSERT_X(dirtyFlags() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up");
+ if (m_opaque_material && m_opacity > 0.999)
+ return m_opaque_material;
+ return m_material;
+}
+
+
+/*!
+ Sets the inherited opacity of this geometry to \a opacity.
+
+ This function is meant to be called by the node preprocessing
+ prior to rendering the tree, so it will not mark the tree as
+ dirty.
+
+ \internal
+ */
+void QSGGeometryNode::setInheritedOpacity(qreal opacity)
+{
+ Q_ASSERT(opacity >= 0 && opacity <= 1);
+ m_opacity = opacity;
+}
+
+
+/*!
+ \class QSGClipNode
+ \brief The QSGClipNode class implements the clipping functionality in the scene graph.
+
+ \inmodule QtQuick
+
+ Clipping applies to the node's subtree and can be nested. Multiple clip nodes will be
+ accumulated by intersecting all their geometries. The accumulation happens
+ as part of the rendering.
+
+ Clip nodes must have a geometry before they can be added to the scene graph.
+
+ Clipping is usually implemented by using the stencil buffer.
+ */
+
+
+
+/*!
+ Creates a new QSGClipNode without a geometry.
+
+ The clip node must have a geometry before it can be added to the
+ scene graph.
+ */
+
+QSGClipNode::QSGClipNode()
+ : QSGBasicGeometryNode(ClipNodeType)
+{
+}
+
+
+
+/*!
+ Deletes this QSGClipNode.
+
+ If the flag QSGNode::OwnsGeometry is set, the geometry will also be
+ deleted.
+ */
+
+QSGClipNode::~QSGClipNode()
+{
+}
+
+
+
+/*!
+ \fn bool QSGClipNode::isRectangular() const
+
+ Returns if this clip node has a rectangular clip.
+ */
+
+
+
+/*!
+ Sets whether this clip node has a rectangular clip to \a rectHint.
+
+ This is an optimization hint which means that the renderer can
+ use scissoring instead of stencil, which is significnatly faster.
+
+ When this hint is and it is applicable, the clip region will be
+ generated from clipRect() rather than geometry().
+ */
+
+void QSGClipNode::setIsRectangular(bool rectHint)
+{
+ m_is_rectangular = rectHint;
+}
+
+
+
+/*!
+ \fn void QSGClipNode::clipRect() const
+
+ Returns the clip rect of this node.
+ */
+
+
+/*!
+ Sets the clip rect of this clip node to \a rect.
+
+ When a rectangular clip is set in combination with setIsRectangular
+ the renderer may in some cases use a more optimal clip method.
+ */
+void QSGClipNode::setClipRect(const QRectF &rect)
+{
+ m_clip_rect = rect;
+}
+
+
+/*!
+ \class QSGTransformNode
+ \brief The QSGTransformNode class implements transformations in the scene graph
+
+ \inmodule QtQuick
+
+ Transformations apply the node's subtree and can be nested. Multiple transform nodes
+ will be accumulated by intersecting all their matrices. The accumulation happens
+ as part of the rendering.
+
+ The transform nodes implement a 4x4 matrix which in theory supports full 3D
+ transformations. However, because the renderer optimizes for 2D use-cases rather
+ than 3D use-cases, rendering a scene with full 3D transformations needs to
+ be done with some care.
+ */
+
+QSGTransformNode::QSGTransformNode()
+ : QSGNode(TransformNodeType)
+{
+}
+
+
+
+/*!
+ Deletes this transform node.
+ */
+
+QSGTransformNode::~QSGTransformNode()
+{
+}
+
+
+
+/*!
+ \fn QMatrix4x4 QSGTransformNode::matrix() const
+
+ Returns this transform node's matrix.
+ */
+
+
+
+/*!
+ Sets this transform node's matrix to \a matrix.
+ */
+
+void QSGTransformNode::setMatrix(const QMatrix4x4 &matrix)
+{
+ m_matrix = matrix;
+ markDirty(DirtyMatrix);
+}
+
+
+/*!
+ Sets the combined matrix of this matrix to \a transform.
+
+ This function is meant to be called by the node preprocessing
+ prior to rendering the tree, so it will not mark the tree as
+ dirty.
+
+ \internal
+ */
+void QSGTransformNode::setCombinedMatrix(const QMatrix4x4 &matrix)
+{
+ m_combined_matrix = matrix;
+}
+
+
+
+/*!
+ \class QSGRootNode
+ \brief The QSGRootNode is the toplevel root of any scene graph.
+
+ The root node is used to attach a scene graph to a renderer.
+
+ \internal
+ */
+
+
+
+/*!
+ \fn QSGRootNode::QSGRootNode()
+
+ Creates a new root node.
+ */
+
+QSGRootNode::QSGRootNode()
+ : QSGNode(RootNodeType)
+{
+}
+
+
+/*!
+ Deletes the root node.
+
+ When a root node is deleted it removes itself from all of renderers
+ that are referencing it.
+ */
+
+QSGRootNode::~QSGRootNode()
+{
+ while (!m_renderers.isEmpty())
+ m_renderers.last()->setRootNode(0);
+ destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode.
+}
+
+
+
+/*!
+ Called to notify all renderers that \a node has been marked as dirty
+ with \a flags.
+ */
+
+void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyFlags flags)
+{
+ for (int i=0; i<m_renderers.size(); ++i) {
+ m_renderers.at(i)->nodeChanged(node, flags);
+ }
+}
+
+
+
+/*!
+ \class QSGOpacityNode
+ \brief The QSGOpacityNode class is used to change opacity of nodes.
+
+ \inmodule QtQuick
+
+ Opacity applies to its subtree and can be nested. Multiple opacity nodes
+ will be accumulated by multiplying their opacity. The accumulation happens
+ as part of the rendering.
+
+ When nested opacity gets below a certain threshold, the subtree might
+ be marked as blocked, causing isSubtreeBlocked() to return true. This
+ is done for performance reasons.
+
+ */
+
+
+
+/*!
+ Constructs an opacity node with a default opacity of 1.
+
+ Opacity accumulates downwards in the scene graph so a node with two
+ QSGOpacityNode instances above it, both with opacity of 0.5, will have
+ effective opacity of 0.25.
+
+ The default opacity of nodes is 1.
+ */
+QSGOpacityNode::QSGOpacityNode()
+ : QSGNode(OpacityNodeType)
+ , m_opacity(1)
+ , m_combined_opacity(1)
+{
+}
+
+
+
+/*!
+ Deletes the opacity node.
+ */
+
+QSGOpacityNode::~QSGOpacityNode()
+{
+}
+
+
+
+/*!
+ \fn qreal QSGOpacityNode::opacity() const
+
+ Returns this opacity node's opacity.
+ */
+
+
+
+/*!
+ Sets the opacity of this node to \a opacity.
+
+ Before rendering the graph, the renderer will do an update pass
+ over the subtree to propegate the opacity to its children.
+
+ The value will be bounded to the range 0 to 1.
+ */
+
+void QSGOpacityNode::setOpacity(qreal opacity)
+{
+ opacity = qBound<qreal>(0, opacity, 1);
+ if (m_opacity == opacity)
+ return;
+ m_opacity = opacity;
+ markDirty(DirtyOpacity);
+}
+
+
+
+/*!
+ \fn qreal QSGOpacityNode::combinedOpacity() const
+
+ Returns this node's accumulated opacity.
+
+ This vaule is calculated during rendering and only stored
+ in the opacity node temporarily.
+
+ \internal
+ */
+
+
+
+/*!
+ Sets the combined opacity of this node to \a opacity.
+
+ This function is meant to be called by the node preprocessing
+ prior to rendering the tree, so it will not mark the tree as
+ dirty.
+
+ \internal
+ */
+
+void QSGOpacityNode::setCombinedOpacity(qreal opacity)
+{
+ m_combined_opacity = opacity;
+}
+
+
+
+/*!
+ For performance reasons, we block the subtree when the opacity
+ is below a certain threshold.
+
+ \internal
+ */
+
+bool QSGOpacityNode::isSubtreeBlocked() const
+{
+ return QSGNode::isSubtreeBlocked() || m_opacity < 0.001;
+}
+
+
+/*!
+ \class QSGNodeVisitor
+ \brief The QSGNodeVisitor class is a helper class for traversing the scene graph.
+
+ \internal
+ */
+
+QSGNodeVisitor::~QSGNodeVisitor()
+{
+
+}
+
+
+void QSGNodeVisitor::visitNode(QSGNode *n)
+{
+ switch (n->type()) {
+ case QSGNode::TransformNodeType: {
+ QSGTransformNode *t = static_cast<QSGTransformNode *>(n);
+ enterTransformNode(t);
+ visitChildren(t);
+ leaveTransformNode(t);
+ break; }
+ case QSGNode::GeometryNodeType: {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(n);
+ enterGeometryNode(g);
+ visitChildren(g);
+ leaveGeometryNode(g);
+ break; }
+ case QSGNode::ClipNodeType: {
+ QSGClipNode *c = static_cast<QSGClipNode *>(n);
+ enterClipNode(c);
+ visitChildren(c);
+ leaveClipNode(c);
+ break; }
+ case QSGNode::OpacityNodeType: {
+ QSGOpacityNode *o = static_cast<QSGOpacityNode *>(n);
+ enterOpacityNode(o);
+ visitChildren(o);
+ leaveOpacityNode(o);
+ break; }
+ default:
+ visitChildren(n);
+ break;
+ }
+}
+
+void QSGNodeVisitor::visitChildren(QSGNode *n)
+{
+ for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
+ visitNode(c);
+}
+
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QSGGeometryNode *n)
+{
+ if (!n) {
+ d << "QSGGeometryNode(null)";
+ return d;
+ }
+ d << "QSGGeometryNode(" << hex << (void *) n << dec;
+
+ const QSGGeometry *g = n->geometry();
+
+ if (!g) {
+ d << "no geometry";
+ } else {
+
+ switch (g->drawingMode()) {
+ case GL_TRIANGLE_STRIP: d << "strip"; break;
+ case GL_TRIANGLE_FAN: d << "fan"; break;
+ case GL_TRIANGLES: d << "triangles"; break;
+ default: break;
+ }
+
+ d << g->vertexCount();
+
+ if (g->attributeCount() > 0 && g->attributes()->type == GL_FLOAT) {
+ float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
+ int stride = g->sizeOfVertex();
+ for (int i = 0; i < g->vertexCount(); ++i) {
+ float x = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
+ float y = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
+
+ x1 = qMin(x1, x);
+ x2 = qMax(x2, x);
+ y1 = qMin(y1, y);
+ y2 = qMax(y2, y);
+ }
+
+ d << "x1=" << x1 << "y1=" << y1 << "x2=" << x2 << "y2=" << y2;
+ }
+ }
+
+ d << "order=" << n->renderOrder();
+ if (n->material())
+ d << "effect=" << n->material() << "type=" << n->material()->type();
+
+
+ d << ")";
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QSGClipNode *n)
+{
+ if (!n) {
+ d << "QSGClipNode(null)";
+ return d;
+ }
+ d << "QSGClipNode(" << hex << (void *) n << dec;
+
+ if (n->childCount())
+ d << "children=" << n->childCount();
+
+ d << "is rect?" << (n->isRectangular() ? "yes" : "no");
+
+ d << ")";
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QSGTransformNode *n)
+{
+ if (!n) {
+ d << "QSGTransformNode(null)";
+ return d;
+ }
+ const QMatrix4x4 m = n->matrix();
+ d << "QSGTransformNode(";
+ d << hex << (void *) n << dec;
+ if (m.isIdentity())
+ d << "identity";
+ else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
+ d << "translate" << m(0, 3) << m(1, 3) << m(2, 3);
+ else
+ d << "det=" << n->matrix().determinant();
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
+ d << ")";
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QSGOpacityNode *n)
+{
+ if (!n) {
+ d << "QSGOpacityNode(null)";
+ return d;
+ }
+ d << "QSGOpacityNode(";
+ d << hex << (void *) n << dec;
+ d << "opacity=" << n->opacity()
+ << "combined=" << n->combinedOpacity()
+ << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
+ d << ")";
+ return d;
+}
+
+
+QDebug operator<<(QDebug d, const QSGRootNode *n)
+{
+ if (!n) {
+ d << "QSGRootNode(null)";
+ return d;
+ }
+ d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyFlags() << dec
+ << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << ")";
+ return d;
+}
+
+
+
+QDebug operator<<(QDebug d, const QSGNode *n)
+{
+ if (!n) {
+ d << "QSGNode(null)";
+ return d;
+ }
+ switch (n->type()) {
+ case QSGNode::GeometryNodeType:
+ d << static_cast<const QSGGeometryNode *>(n);
+ break;
+ case QSGNode::TransformNodeType:
+ d << static_cast<const QSGTransformNode *>(n);
+ break;
+ case QSGNode::ClipNodeType:
+ d << static_cast<const QSGClipNode *>(n);
+ break;
+ case QSGNode::RootNodeType:
+ d << static_cast<const QSGRootNode *>(n);
+ break;
+ case QSGNode::OpacityNodeType:
+ d << static_cast<const QSGOpacityNode *>(n);
+ break;
+ default:
+ d << "QSGNode(" << hex << (void *) n << dec
+ << "dirty=" << hex << (int) n->dirtyFlags()
+ << "flags=" << (int) n->flags() << dec
+ << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
+#ifdef QML_RUNTIME_TESTING
+ d << n->description;
+#endif
+ d << ")";
+ break;
+ }
+ return d;
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
new file mode 100644
index 0000000000..41c63e27b6
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 NODE_H
+#define NODE_H
+
+#include "qsggeometry.h"
+#include <QtGui/QMatrix4x4>
+
+#include <float.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define QML_RUNTIME_TESTING
+
+class QSGRenderer;
+
+class QSGNode;
+class QSGRootNode;
+class QSGGeometryNode;
+class QSGTransformNode;
+class QSGClipNode;
+
+class Q_QUICK_EXPORT QSGNode
+{
+public:
+ enum NodeType {
+ BasicNodeType,
+ RootNodeType,
+ GeometryNodeType,
+ TransformNodeType,
+ ClipNodeType,
+ OpacityNodeType,
+ UserNodeType = 1024
+ };
+
+ enum DirtyFlag {
+ DirtyMatrix = 0x0001,
+ DirtyClipList = 0x0002,
+ DirtyNodeAdded = 0x0004,
+ DirtyNodeRemoved = 0x0008,
+ DirtyGeometry = 0x0010,
+ DirtyMaterial = 0x0040,
+ DirtyOpacity = 0x0080,
+ DirtyForceUpdate = 0x0100,
+
+ DirtyPropagationMask = DirtyMatrix
+ | DirtyClipList
+ | DirtyNodeAdded
+ | DirtyOpacity
+ | DirtyForceUpdate
+
+ };
+ Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
+
+ enum Flag {
+ // Lower 16 bites reserved for general node
+ OwnedByParent = 0x0001,
+ UsePreprocess = 0x0002,
+ ChildrenDoNotOverlap = 0x0004,
+
+ // Upper 16 bits reserved for node subclasses
+
+ // QSGBasicGeometryNode
+ OwnsGeometry = 0x00010000,
+ OwnsMaterial = 0x00020000,
+ OwnsOpaqueMaterial = 0x00040000
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QSGNode();
+ virtual ~QSGNode();
+
+ QSGNode *parent() const { return m_parent; }
+
+ void removeChildNode(QSGNode *node);
+ void removeAllChildNodes();
+ void prependChildNode(QSGNode *node);
+ void appendChildNode(QSGNode *node);
+ void insertChildNodeBefore(QSGNode *node, QSGNode *before);
+ void insertChildNodeAfter(QSGNode *node, QSGNode *after);
+
+ int childCount() const;
+ QSGNode *childAtIndex(int i) const;
+ QSGNode *firstChild() const { return m_firstChild; }
+ QSGNode *lastChild() const { return m_lastChild; }
+ QSGNode *nextSibling() const { return m_nextSibling; }
+ QSGNode* previousSibling() const { return m_previousSibling; }
+
+ inline NodeType type() const { return m_type; }
+
+ void clearDirty() { m_flags = 0; }
+ void markDirty(DirtyFlags flags);
+ DirtyFlags dirtyFlags() const { return m_flags; }
+
+ virtual bool isSubtreeBlocked() const;
+
+ Flags flags() const { return m_nodeFlags; }
+ void setFlag(Flag, bool = true);
+ void setFlags(Flags, bool = true);
+
+ virtual void preprocess() { }
+
+#ifdef QML_RUNTIME_TESTING
+ QString description;
+#endif
+
+protected:
+ QSGNode(NodeType type);
+
+private:
+ friend class QSGRootNode;
+
+ void init();
+ void destroy();
+
+ QSGNode *m_parent;
+ NodeType m_type;
+ QSGNode *m_firstChild;
+ QSGNode *m_lastChild;
+ QSGNode *m_nextSibling;
+ QSGNode *m_previousSibling;
+ int m_subtreeGeometryCount;
+
+ Flags m_nodeFlags;
+ DirtyFlags m_flags;
+
+ void *m_reserved;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::Flags)
+
+class Q_QUICK_EXPORT QSGBasicGeometryNode : public QSGNode
+{
+public:
+// enum UsagePattern {
+// Static,
+// Dynamic,
+// Stream
+// };
+// void setUsagePattern(UsagePattern pattern);
+// UsagePattern usagePattern() const { return m_pattern; }
+
+ ~QSGBasicGeometryNode();
+
+ void setGeometry(QSGGeometry *geometry);
+ const QSGGeometry *geometry() const { return m_geometry; }
+ QSGGeometry *geometry() { return m_geometry; }
+
+ const QMatrix4x4 *matrix() const { return m_matrix; }
+ const QSGClipNode *clipList() const { return m_clip_list; }
+
+protected:
+ QSGBasicGeometryNode(NodeType type);
+
+private:
+ friend class QSGNodeUpdater;
+ QSGGeometry *m_geometry;
+
+ int m_reserved_start_index;
+ int m_reserved_end_index;
+
+ const QMatrix4x4 *m_matrix;
+ const QSGClipNode *m_clip_list;
+
+// UsagePattern m_pattern;
+};
+
+class QSGMaterial;
+
+class Q_QUICK_EXPORT QSGGeometryNode : public QSGBasicGeometryNode
+{
+public:
+ QSGGeometryNode();
+ ~QSGGeometryNode();
+
+ void setMaterial(QSGMaterial *material);
+ QSGMaterial *material() const { return m_material; }
+
+ void setOpaqueMaterial(QSGMaterial *material);
+ QSGMaterial *opaqueMaterial() const { return m_opaque_material; }
+
+ QSGMaterial *activeMaterial() const;
+
+ void setRenderOrder(int order);
+ int renderOrder() const { return m_render_order; }
+
+ void setInheritedOpacity(qreal opacity);
+ qreal inheritedOpacity() const { return m_opacity; }
+
+private:
+ friend class QSGNodeUpdater;
+
+ int m_render_order;
+ QSGMaterial *m_material;
+ QSGMaterial *m_opaque_material;
+
+ qreal m_opacity;
+};
+
+class Q_QUICK_EXPORT QSGClipNode : public QSGBasicGeometryNode
+{
+public:
+ QSGClipNode();
+ ~QSGClipNode();
+
+ void setIsRectangular(bool rectHint);
+ bool isRectangular() const { return m_is_rectangular; }
+
+ void setClipRect(const QRectF &);
+ QRectF clipRect() const { return m_clip_rect; }
+
+private:
+ uint m_is_rectangular : 1;
+ uint m_reserved : 31;
+
+ QRectF m_clip_rect;
+};
+
+
+class Q_QUICK_EXPORT QSGTransformNode : public QSGNode
+{
+public:
+ QSGTransformNode();
+ ~QSGTransformNode();
+
+ void setMatrix(const QMatrix4x4 &matrix);
+ const QMatrix4x4 &matrix() const { return m_matrix; }
+
+ void setCombinedMatrix(const QMatrix4x4 &matrix);
+ const QMatrix4x4 &combinedMatrix() const { return m_combined_matrix; }
+
+private:
+ QMatrix4x4 m_matrix;
+ QMatrix4x4 m_combined_matrix;
+};
+
+
+class Q_QUICK_EXPORT QSGRootNode : public QSGNode
+{
+public:
+ QSGRootNode();
+ ~QSGRootNode();
+
+private:
+ void notifyNodeChange(QSGNode *node, DirtyFlags flags);
+
+ friend class QSGRenderer;
+ friend class QSGNode;
+ friend class QSGGeometryNode;
+
+ QList<QSGRenderer *> m_renderers;
+};
+
+
+class Q_QUICK_EXPORT QSGOpacityNode : public QSGNode
+{
+public:
+ QSGOpacityNode();
+ ~QSGOpacityNode();
+
+ void setOpacity(qreal opacity);
+ qreal opacity() const { return m_opacity; }
+
+ void setCombinedOpacity(qreal opacity);
+ qreal combinedOpacity() const { return m_combined_opacity; }
+
+ bool isSubtreeBlocked() const;
+
+private:
+ qreal m_opacity;
+ qreal m_combined_opacity;
+};
+
+class Q_QUICK_EXPORT QSGNodeVisitor {
+public:
+ virtual ~QSGNodeVisitor();
+
+protected:
+ virtual void enterTransformNode(QSGTransformNode *) {}
+ virtual void leaveTransformNode(QSGTransformNode *) {}
+ virtual void enterClipNode(QSGClipNode *) {}
+ virtual void leaveClipNode(QSGClipNode *) {}
+ virtual void enterGeometryNode(QSGGeometryNode *) {}
+ virtual void leaveGeometryNode(QSGGeometryNode *) {}
+ virtual void enterOpacityNode(QSGOpacityNode *) {}
+ virtual void leaveOpacityNode(QSGOpacityNode *) {}
+ virtual void visitNode(QSGNode *n);
+ virtual void visitChildren(QSGNode *n);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_QUICK_EXPORT QDebug operator<<(QDebug, const QSGNode *n);
+Q_QUICK_EXPORT QDebug operator<<(QDebug, const QSGGeometryNode *n);
+Q_QUICK_EXPORT QDebug operator<<(QDebug, const QSGTransformNode *n);
+Q_QUICK_EXPORT QDebug operator<<(QDebug, const QSGOpacityNode *n);
+Q_QUICK_EXPORT QDebug operator<<(QDebug, const QSGRootNode *n);
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // NODE_H
diff --git a/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
index a7e5b08dc1..a7e5b08dc1 100644
--- a/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
new file mode 100644
index 0000000000..446bdefdc5
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 NODEUPDATER_P_H
+#define NODEUPDATER_P_H
+
+#include "qsgnode.h"
+#include <QtGui/private/qdatabuffer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGNodeUpdater
+{
+public:
+ QSGNodeUpdater();
+
+ virtual void updateStates(QSGNode *n);
+ virtual bool isNodeBlocked(QSGNode *n, QSGNode *root) const;
+
+ void setToplevelOpacity(qreal alpha) { m_opacity_stack.last() = alpha; }
+ qreal toplevelOpacity() const { return m_opacity_stack.last(); }
+
+protected:
+ virtual void enterTransformNode(QSGTransformNode *);
+ virtual void leaveTransformNode(QSGTransformNode *);
+ void enterClipNode(QSGClipNode *c);
+ void leaveClipNode(QSGClipNode *c);
+ void enterOpacityNode(QSGOpacityNode *o);
+ void leaveOpacityNode(QSGOpacityNode *o);
+ void enterGeometryNode(QSGGeometryNode *);
+ void leaveGeometryNode(QSGGeometryNode *);
+
+ void visitNode(QSGNode *n);
+ void visitChildren(QSGNode *n);
+
+
+ QDataBuffer<const QMatrix4x4 *> m_combined_matrix_stack;
+ QDataBuffer<qreal> m_opacity_stack;
+ const QSGClipNode *m_current_clip;
+
+ int m_force_update;
+
+ qreal m_toplevel_alpha;
+};
+
+QT_END_NAMESPACE
+
+#endif // NODEUPDATER_P_H
diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index b22631afae..b22631afae 100644
--- a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
new file mode 100644
index 0000000000..e5667c710a
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 RENDERER_H
+#define RENDERER_H
+
+#include <qset.h>
+#include <qhash.h>
+
+#include <qcolor.h>
+#include <qopenglfunctions.h>
+#include <qopenglshaderprogram.h>
+
+#include "qsgnode.h"
+#include "qsgmaterial.h"
+#include <QtQuick/qsgtexture.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGMaterialShader;
+struct QSGMaterialType;
+class QOpenGLFramebufferObject;
+class TextureReference;
+class QSGBindable;
+class QSGNodeUpdater;
+
+class Q_QUICK_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions
+{
+ Q_OBJECT
+public:
+ enum ClipType
+ {
+ NoClip,
+ ScissorClip,
+ StencilClip
+ };
+
+ enum ClearModeBit
+ {
+ ClearColorBuffer = 0x0001,
+ ClearDepthBuffer = 0x0002,
+ ClearStencilBuffer = 0x0004
+ };
+ Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
+
+ QSGRenderer(QSGContext *context);
+ virtual ~QSGRenderer();
+
+ void setRootNode(QSGRootNode *node);
+ QSGRootNode *rootNode() const { return m_root_node; }
+
+ void setDeviceRect(const QRect &rect) { m_device_rect = rect; }
+ inline void setDeviceRect(const QSize &size) { setDeviceRect(QRect(QPoint(), size)); }
+ QRect deviceRect() const { return m_device_rect; }
+
+ void setViewportRect(const QRect &rect) { m_viewport_rect = rect; }
+ inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
+ QRect viewportRect() const { return m_viewport_rect; }
+
+ // Accessed by QSGMaterialShader::RenderState.
+ QMatrix4x4 currentProjectionMatrix() const { return m_current_projection_matrix; }
+ QMatrix4x4 currentModelViewMatrix() const { return m_current_model_view_matrix; }
+ QMatrix4x4 currentCombinedMatrix() const { return m_current_projection_matrix * m_current_model_view_matrix; }
+ qreal currentOpacity() const { return m_current_opacity; }
+
+ void setProjectionMatrixToDeviceRect();
+ void setProjectionMatrixToRect(const QRectF &rect);
+ void setProjectionMatrix(const QMatrix4x4 &matrix);
+ QMatrix4x4 projectionMatrix() const { return m_projection_matrix; }
+ bool isMirrored() const { return m_mirrored; }
+
+ void setClearColor(const QColor &color);
+ QColor clearColor() const { return m_clear_color; }
+
+ QOpenGLContext *glContext() const { Q_ASSERT(m_context); return m_context->glContext(); }
+
+ QSGContext *context();
+
+ void renderScene();
+ void renderScene(const QSGBindable &bindable);
+ virtual void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
+ virtual void materialChanged(QSGGeometryNode *node, QSGMaterial *from, QSGMaterial *to);
+
+ QSGNodeUpdater *nodeUpdater() const;
+ void setNodeUpdater(QSGNodeUpdater *updater);
+
+ inline QSGMaterialShader::RenderState state(QSGMaterialShader::RenderState::DirtyStates dirty) const;
+
+ void setClearMode(ClearMode mode) { m_clear_mode = mode; }
+ ClearMode clearMode() const { return m_clear_mode; }
+
+signals:
+ void sceneGraphChanged(); // Add, remove, ChangeFlags changes...
+
+protected:
+ void draw(const QSGMaterialShader *material, const QSGGeometry *g);
+
+ virtual void render() = 0;
+ QSGRenderer::ClipType updateStencilClip(const QSGClipNode *clip);
+
+ const QSGBindable *bindable() const { return m_bindable; }
+
+ virtual void preprocess();
+
+ void addNodesToPreprocess(QSGNode *node);
+ void removeNodesToPreprocess(QSGNode *node);
+
+
+ QColor m_clear_color;
+ ClearMode m_clear_mode;
+ QMatrix4x4 m_current_projection_matrix;
+ QMatrix4x4 m_current_model_view_matrix;
+ qreal m_current_opacity;
+
+ QSGContext *m_context;
+
+private:
+ QSGRootNode *m_root_node;
+ QSGNodeUpdater *m_node_updater;
+
+ QRect m_device_rect;
+ QRect m_viewport_rect;
+
+ QSet<QSGNode *> m_nodes_to_preprocess;
+
+ QMatrix4x4 m_projection_matrix;
+ QOpenGLShaderProgram m_clip_program;
+ int m_clip_matrix_id;
+
+ const QSGBindable *m_bindable;
+
+ uint m_changed_emitted : 1;
+ uint m_mirrored : 1;
+ uint m_is_rendering : 1;
+
+ uint m_vertex_buffer_bound : 1;
+ uint m_index_buffer_bound : 1;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderer::ClearMode)
+
+class Q_QUICK_EXPORT QSGBindable
+{
+public:
+ virtual ~QSGBindable() { }
+ virtual void bind() const = 0;
+ virtual void clear(QSGRenderer::ClearMode mode) const;
+ virtual void reactivate() const;
+};
+
+class QSGBindableFbo : public QSGBindable
+{
+public:
+ QSGBindableFbo(QOpenGLFramebufferObject *fbo);
+ virtual void bind() const;
+private:
+ QOpenGLFramebufferObject *m_fbo;
+};
+
+
+
+QSGMaterialShader::RenderState QSGRenderer::state(QSGMaterialShader::RenderState::DirtyStates dirty) const
+{
+ QSGMaterialShader::RenderState s;
+ s.m_dirty = dirty;
+ s.m_data = this;
+ return s;
+}
+
+
+class Q_QUICK_EXPORT QSGNodeDumper : public QSGNodeVisitor {
+
+public:
+ static void dump(QSGNode *n);
+
+ QSGNodeDumper() : m_indent(0) {}
+ void visitNode(QSGNode *n);
+ void visitChildren(QSGNode *n);
+
+private:
+ int m_indent;
+};
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // RENDERER_H
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
new file mode 100644
index 0000000000..972bff80e0
--- /dev/null
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgadaptationlayer_p.h"
+
+#include <qmath.h>
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
+#include <private/qrawfont_p.h>
+#include <QtGui/qguiapplication.h>
+#include <qdir.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_caches_data;
+
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
+ : ctx(c)
+ , m_manager(man)
+{
+ Q_ASSERT(font.isValid());
+ m_font = font;
+
+ m_cacheData = cacheData();
+
+ QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
+ m_glyphCount = fontD->fontEngine->glyphCount();
+
+ m_cacheData->doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
+
+ m_referenceFont = m_font;
+ m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution));
+ Q_ASSERT(m_referenceFont.isValid());
+}
+
+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
+{
+ 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);
+ }
+
+ return metric.value();
+}
+
+QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph) const
+{
+ return m_cacheData->texCoords.value(glyph);
+}
+
+static QSGDistanceFieldGlyphCache::Texture g_emptyTexture;
+
+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();
+}
+
+void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
+{
+ QSet<glyph_t> newGlyphs;
+ int count = glyphs.count();
+ for (int i = 0; i < count; ++i) {
+ glyph_t glyphIndex = glyphs.at(i);
+ if ((int) glyphIndex >= glyphCount()) {
+ qWarning("Warning: distance-field glyph is not available with index %d", glyphIndex);
+ continue;
+ }
+
+ if (m_cacheData->texCoords.contains(glyphIndex) || 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;
+ }
+
+ newGlyphs.insert(glyphIndex);
+ }
+
+ if (newGlyphs.isEmpty())
+ return;
+
+ QVector<glyph_t> glyphsVec;
+ QSet<glyph_t>::const_iterator it = newGlyphs.constBegin();
+ while (it != newGlyphs.constEnd()) {
+ glyphsVec.append(*it);
+ ++it;
+ }
+ requestGlyphs(glyphsVec);
+}
+
+void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
+{
+ releaseGlyphs(glyphs);
+}
+
+void QSGDistanceFieldGlyphCache::update()
+{
+ if (m_cacheData->pendingGlyphs.isEmpty())
+ return;
+
+ QHash<glyph_t, QImage> distanceFields;
+
+ // ### Remove before final release
+ static bool cacheDistanceFields = QGuiApplication::arguments().contains(QLatin1String("--cache-distance-fields"));
+
+ 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());
+
+ 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);
+
+ if (cacheDistanceFields) {
+ QString key = keyBase.arg(glyphIndex);
+ QFile file(key);
+ if (file.open(QFile::ReadOnly)) {
+ int fileSize = file.size();
+ int dim = sqrt(float(fileSize));
+ QByteArray blob = file.readAll();
+ QImage df(dim, dim, QImage::Format_Indexed8);
+ memcpy(df.bits(), blob.constData(), fileSize);
+ distanceFields.insert(glyphIndex, df);
+ continue;
+ }
+ }
+
+ QImage distanceField = qt_renderDistanceFieldGlyph(m_font, glyphIndex, m_cacheData->doubleGlyphResolution);
+ distanceFields.insert(glyphIndex, distanceField);
+
+ if (cacheDistanceFields) {
+ QString key = keyBase.arg(glyphIndex);
+ QFile file(key);
+ file.open(QFile::WriteOnly);
+ file.write((const char *) distanceField.constBits(), distanceField.width() * distanceField.height());
+ }
+ }
+
+ m_cacheData->pendingGlyphs.reset();
+
+ storeGlyphs(distanceFields);
+}
+
+void QSGDistanceFieldGlyphCache::addGlyphPositions(const QList<GlyphPosition> &glyphs)
+{
+ int count = glyphs.count();
+ for (int i = 0; i < count; ++i) {
+ GlyphPosition glyph = glyphs.at(i);
+
+ 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();
+
+ m_cacheData->texCoords.insert(glyph.glyph, c);
+ }
+}
+
+void QSGDistanceFieldGlyphCache::addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex)
+{
+ int i = m_cacheData->textures.indexOf(tex);
+ if (i == -1) {
+ m_cacheData->textures.append(tex);
+ i = m_cacheData->textures.size() - 1;
+ } else {
+ m_cacheData->textures[i].size = tex.size;
+ }
+ Texture *texture = &(m_cacheData->textures[i]);
+
+ int count = glyphs.count();
+ for (int j = 0; j < count; ++j)
+ m_cacheData->glyphTextures.insert(glyphs.at(j), texture);
+
+ QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
+ while (it != m_cacheData->m_registeredNodes.end()) {
+ (*it)->updateGeometry();
+ ++it;
+ }
+}
+
+void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyphs)
+{
+ 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);
+}
+
+void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize)
+{
+ int count = m_cacheData->textures.count();
+ for (int i = 0; i < count; ++i) {
+ Texture &tex = m_cacheData->textures[i];
+ if (tex.textureId == oldTex) {
+ tex.textureId = newTex;
+ tex.size = newTexSize;
+ return;
+ }
+ }
+}
+
+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
new file mode 100644
index 0000000000..5912802a84
--- /dev/null
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 ADAPTATIONINTERFACES_H
+#define ADAPTATIONINTERFACES_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgtexture.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcolor.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtGui/qglyphrun.h>
+#include <QtCore/qurl.h>
+#include <private/qfontengine_p.h>
+#include <QtGui/private/qdatabuffer_p.h>
+#include <private/qopenglcontext_p.h>
+
+// ### remove
+#include <QtQuick/private/qquicktext_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGNode;
+class QImage;
+class TextureReference;
+class QSGDistanceFieldGlyphCacheManager;
+class QSGDistanceFieldGlyphNode;
+
+// TODO: Rename from XInterface to AbstractX.
+class Q_QUICK_EXPORT QSGRectangleNode : public QSGGeometryNode
+{
+public:
+ virtual void setRect(const QRectF &rect) = 0;
+ virtual void setColor(const QColor &color) = 0;
+ virtual void setPenColor(const QColor &color) = 0;
+ virtual void setPenWidth(qreal width) = 0;
+ virtual void setGradientStops(const QGradientStops &stops) = 0;
+ virtual void setRadius(qreal radius) = 0;
+ virtual void setAligned(bool aligned) = 0;
+
+ virtual void update() = 0;
+};
+
+
+class Q_QUICK_EXPORT QSGImageNode : public QSGGeometryNode
+{
+public:
+ virtual void setTargetRect(const QRectF &rect) = 0;
+ virtual void setSourceRect(const QRectF &rect) = 0;
+ virtual void setTexture(QSGTexture *texture) = 0;
+
+ virtual void setMipmapFiltering(QSGTexture::Filtering filtering) = 0;
+ virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
+ virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
+ virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
+
+ virtual void update() = 0;
+};
+
+
+class Q_QUICK_EXPORT QSGGlyphNode : public QSGGeometryNode
+{
+public:
+ enum AntialiasingMode
+ {
+ GrayAntialiasing,
+ LowQualitySubPixelAntialiasing,
+ HighQualitySubPixelAntialiasing
+ };
+
+ virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) = 0;
+ virtual void setColor(const QColor &color) = 0;
+ virtual void setStyle(QQuickText::TextStyle style) = 0;
+ virtual void setStyleColor(const QColor &color) = 0;
+ virtual QPointF baseLine() const = 0;
+
+ virtual QRectF boundingRect() const { return m_bounding_rect; }
+ virtual void setBoundingRect(const QRectF &bounds) { m_bounding_rect = bounds; }
+
+ virtual void setPreferredAntialiasingMode(AntialiasingMode) = 0;
+
+ virtual void update() = 0;
+
+protected:
+ QRectF m_bounding_rect;
+};
+
+class Q_QUICK_EXPORT QSGDistanceFieldGlyphCache
+{
+public:
+ QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+ virtual ~QSGDistanceFieldGlyphCache();
+
+ struct Metrics {
+ qreal width;
+ qreal height;
+ qreal baselineX;
+ qreal baselineY;
+
+ bool isNull() const { return width == 0 || height == 0; }
+ };
+
+ struct TexCoord {
+ qreal x;
+ qreal y;
+ qreal width;
+ qreal height;
+ qreal xMargin;
+ qreal yMargin;
+
+ TexCoord() : x(0), y(0), width(-1), height(-1), xMargin(0), yMargin(0) { }
+
+ bool isNull() const { return width <= 0 || height <= 0; }
+ bool isValid() const { return width >= 0 && height >= 0; }
+ };
+
+ struct Texture {
+ GLuint textureId;
+ QSize size;
+
+ Texture() : textureId(0), size(QSize()) { }
+ bool operator == (const Texture &other) const { return textureId == other.textureId; }
+ };
+
+ const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
+
+ const QRawFont &font() const { return m_font; }
+
+ qreal fontScale() const;
+ int distanceFieldRadius() const;
+ int glyphCount() const { return m_glyphCount; }
+ bool doubleGlyphResolution() const { return m_cacheData->doubleGlyphResolution; }
+
+ Metrics glyphMetrics(glyph_t glyph);
+ TexCoord glyphTexCoord(glyph_t glyph) const;
+ const Texture *glyphTexture(glyph_t glyph) const;
+
+ void populate(const QVector<glyph_t> &glyphs);
+ void release(const QVector<glyph_t> &glyphs);
+
+ void update();
+
+ void registerGlyphNode(QSGDistanceFieldGlyphNode *node);
+ void unregisterGlyphNode(QSGDistanceFieldGlyphNode *node);
+
+protected:
+ struct GlyphPosition {
+ glyph_t glyph;
+ QPointF position;
+ };
+
+ virtual void requestGlyphs(const QVector<glyph_t> &glyphs) = 0;
+ virtual void storeGlyphs(const QHash<glyph_t, QImage> &glyphs) = 0;
+ virtual void releaseGlyphs(const QVector<glyph_t> &glyphs) = 0;
+
+ void addGlyphPositions(const QList<GlyphPosition> &glyphs);
+ void addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex);
+ void markGlyphsToRender(const QVector<glyph_t> &glyphs);
+ void removeGlyph(glyph_t glyph);
+
+ void updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize);
+
+ bool containsGlyph(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;
+
+ GlyphCacheData(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , pendingGlyphs(64)
+ , doubleGlyphResolution(false)
+ {}
+
+ void invalidateResource()
+ {
+ textures.clear();
+ glyphTextures.clear();
+ texCoords.clear();
+ }
+
+ void freeResource(QOpenGLContext *)
+ {
+ }
+ };
+
+ 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;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
new file mode 100644
index 0000000000..93fea15921
--- /dev/null
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgcontext_p.h"
+#include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/qsgnode.h>
+
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+
+#include <private/qsgdefaultrenderer_p.h>
+
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <QtQuick/private/qsgdefaultdistancefieldglyphcache_p.h>
+#include <private/qsgdefaultrectanglenode_p.h>
+#include <private/qsgdefaultimagenode_p.h>
+#include <private/qsgdefaultglyphnode_p.h>
+#include <private/qsgdistancefieldglyphnode_p.h>
+
+#include <QtQuick/private/qsgtexture_p.h>
+#include <QGuiApplication>
+#include <QOpenGLContext>
+
+#include <QDeclarativeImageProvider>
+
+#include <private/qobject_p.h>
+#include <qmutex.h>
+#include <private/qdeclarativeglobal_p.h>
+
+DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
+DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
+/*
+ Comments about this class from Gunnar:
+
+ The QSGContext class is right now two things.. The first is the
+ adaptation layer and central storage ground for all the things
+ in the scene graph, like textures and materials. This part really
+ belongs inside the scene graph coreapi.
+
+ The other part is the QML adaptation classes, like how to implement
+ rectangle nodes. This is not part of the scene graph core API, but
+ more part of the QML adaptation of scene graph.
+
+ If we ever move the scene graph core API into its own thing, this class
+ needs to be split in two. Right now its one because we're lazy when it comes
+ to defining plugin interfaces..
+*/
+
+
+QT_BEGIN_NAMESPACE
+
+class QSGContextPrivate : public QObjectPrivate
+{
+public:
+ QSGContextPrivate()
+ : rootNode(0)
+ , renderer(0)
+ , gl(0)
+ , distanceFieldCacheManager(0)
+ , flashMode(qmlFlashMode())
+ , distanceFieldDisabled(qmlDisableDistanceField())
+ {
+ renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
+ }
+
+ ~QSGContextPrivate()
+ {
+ }
+
+ QSGRootNode *rootNode;
+ QSGRenderer *renderer;
+
+ QOpenGLContext *gl;
+
+ QHash<QSGMaterialType *, QSGMaterialShader *> materials;
+ QHash<QDeclarativeTextureFactory *, QSGTexture *> textures;
+
+ QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
+
+ bool flashMode;
+ float renderAlpha;
+ bool distanceFieldDisabled;
+};
+
+
+/*!
+ \class QSGContext
+
+ \brief The QSGContext holds the scene graph entry points for one QML engine.
+
+ The context is not ready for use until it has a QOpenGLContext. Once that happens,
+ the scene graph population can start.
+
+ \internal
+ */
+
+QSGContext::QSGContext(QObject *parent) :
+ QObject(*(new QSGContextPrivate), parent)
+{
+}
+
+
+QSGContext::~QSGContext()
+{
+ Q_D(QSGContext);
+ qDeleteAll(d->textures.values());
+ d->textures.clear();
+ delete d->renderer;
+ delete d->rootNode;
+ qDeleteAll(d->materials.values());
+ delete d->distanceFieldCacheManager;
+}
+
+
+QSGTexture *QSGContext::textureForFactory(QDeclarativeTextureFactory *factory)
+{
+ Q_D(QSGContext);
+ if (!factory)
+ return 0;
+
+ QSGTexture *texture = d->textures.value(factory);
+ if (!texture) {
+ if (QDeclarativeDefaultTextureFactory *dtf = qobject_cast<QDeclarativeDefaultTextureFactory *>(factory))
+ texture = createTexture(dtf->image());
+ else
+ texture = factory->createTexture();
+ d->textures.insert(factory, texture);
+ connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)));
+ }
+ return texture;
+}
+
+
+void QSGContext::textureFactoryDestroyed(QObject *o)
+{
+ Q_D(QSGContext);
+ QDeclarativeTextureFactory *f = static_cast<QDeclarativeTextureFactory *>(o);
+
+ // This function will only be called on the scene graph thread, so it is
+ // safe to directly delete the texture here.
+ delete d->textures.take(f);
+}
+
+
+
+/*!
+ Returns the renderer. The renderer instance is created through the adaptation layer.
+ */
+QSGRenderer *QSGContext::renderer() const
+{
+ Q_D(const QSGContext);
+ return d->renderer;
+}
+
+
+/*!
+ Returns the root node. The root node instance is only created once the scene graph
+ context becomes ready.
+ */
+QSGRootNode *QSGContext::rootNode() const
+{
+ Q_D(const QSGContext);
+ return d->rootNode;
+}
+
+
+QOpenGLContext *QSGContext::glContext() const
+{
+ Q_D(const QSGContext);
+ return d->gl;
+}
+
+/*!
+ Initializes the scene graph context with the GL context \a context. This also
+ emits the ready() signal so that the QML graph can start building scene graph nodes.
+ */
+void QSGContext::initialize(QOpenGLContext *context)
+{
+ Q_D(QSGContext);
+
+ Q_ASSERT(!d->gl);
+
+ d->gl = context;
+
+ d->renderer = createRenderer();
+ d->renderer->setClearColor(Qt::white);
+
+ d->rootNode = new QSGRootNode();
+ d->renderer->setRootNode(d->rootNode);
+
+ emit ready();
+}
+
+
+/*!
+ Returns if the scene graph context is ready or not, meaning that it has a valid
+ GL context.
+ */
+bool QSGContext::isReady() const
+{
+ Q_D(const QSGContext);
+ return d->gl;
+}
+
+
+void QSGContext::renderNextFrame(QOpenGLFramebufferObject *fbo)
+{
+ Q_D(QSGContext);
+
+ if (fbo) {
+ QSGBindableFbo bindable(fbo);
+ d->renderer->renderScene(bindable);
+ } else {
+ d->renderer->renderScene();
+ }
+
+}
+
+/*!
+ Factory function for scene graph backends of the Rectangle element.
+ */
+QSGRectangleNode *QSGContext::createRectangleNode()
+{
+ return new QSGDefaultRectangleNode(this);
+}
+
+/*!
+ Factory function for scene graph backends of the Image element.
+ */
+QSGImageNode *QSGContext::createImageNode()
+{
+ return new QSGDefaultImageNode;
+}
+
+/*!
+ Factory function for scene graph backends of the distance-field glyph cache.
+ */
+QSGDistanceFieldGlyphCache *QSGContext::createDistanceFieldGlyphCache(const QRawFont &font)
+{
+ Q_D(QSGContext);
+ return new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
+}
+
+/*!
+ Factory function for scene graph backends of the Text elements;
+ */
+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);
+ return node;
+ }
+}
+
+/*!
+ Factory function for the scene graph renderers.
+
+ The renderers are used for the toplevel renderer and once for every
+ QQuickShaderEffectSource used in the QML scene.
+ */
+QSGRenderer *QSGContext::createRenderer()
+{
+ // ### Do something with this before release...
+ static bool doFrontToBack = qApp->arguments().contains(QLatin1String("--opaque-front-to-back"));
+ QSGDefaultRenderer *renderer = new QSGDefaultRenderer(this);
+ if (doFrontToBack) {
+ printf("QSGContext: Sorting opaque nodes front to back...\n");
+ renderer->setSortFrontToBackEnabled(true);
+ }
+ return renderer;
+}
+
+
+
+/*!
+ Return true if the image provider supports direct decoding of images,
+ straight into textures without going through a QImage first.
+
+ If the implementation returns true from this function, the decodeImageToTexture() function
+ will be called to read data from a QIODevice, rather than QML decoding
+ the image using QImageReader and passing the result to setImage().
+
+ \warning This function will be called from outside the GUI and rendering threads
+ and must not make use of OpenGL.
+ */
+
+bool QSGContext::canDecodeImageToTexture() const
+{
+ return true;
+}
+
+
+
+/*!
+ Decode the data in \a dev directly to a texture provider of \a requestSize size.
+ The size of the decoded data should be written to \a impsize.
+
+ If the implementation fails to decode the image data, it should return 0. The
+ image data will then be decoded normally.
+
+ \warning This function will be called from outside the GUI and renderer threads
+ and must not make use of GL calls.
+ */
+
+QSGTexture *QSGContext::decodeImageToTexture(QIODevice *dev,
+ QSize *size,
+ const QSize &requestSize)
+{
+ Q_UNUSED(dev);
+ Q_UNUSED(size);
+ Q_UNUSED(requestSize);
+ return 0;
+}
+
+
+
+QSurfaceFormat QSGContext::defaultSurfaceFormat() const
+{
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ format.setSamples(16);
+ return format;
+}
+
+
+/*!
+ Factory function for texture objects.
+
+ If \a image is a valid image, the QSGTexture::setImage function
+ will be called with \a image as argument.
+ */
+
+QSGTexture *QSGContext::createTexture(const QImage &image) const
+{
+ QSGPlainTexture *t = new QSGPlainTexture();
+ if (!image.isNull())
+ t->setImage(image);
+ return t;
+}
+
+
+
+/*!
+ Returns the minimum supported framebuffer object size.
+ */
+
+QSize QSGContext::minimumFBOSize() const
+{
+#ifdef Q_OS_MAC
+ return QSize(33, 33);
+#else
+ return QSize(1, 1);
+#endif
+}
+
+
+
+/*!
+ Returns a material shader for the given material.
+ */
+
+QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
+{
+ Q_D(QSGContext);
+ QSGMaterialType *type = material->type();
+ QSGMaterialShader *shader = d->materials.value(type);
+ if (shader)
+ return shader;
+
+ shader = material->createShader();
+ shader->compile();
+ shader->initialize();
+ d->materials[type] = shader;
+
+ return shader;
+}
+
+
+
+/*!
+ Sets whether the scene graph should render with flashing update rectangles or not
+ */
+
+void QSGContext::setFlashModeEnabled(bool enabled)
+{
+ d_func()->flashMode = enabled;
+}
+
+
+/*!
+ Returns true if the scene graph should be rendered with flashing update rectangles
+ */
+bool QSGContext::isFlashModeEnabled() const
+{
+ return d_func()->flashMode;
+}
+
+
+/*!
+ Sets the toplevel opacity for rendering. This value will be multiplied into all
+ drawing calls where possible.
+
+ The default value is 1. Any other value will cause artifacts and is primarily
+ useful for debugging.
+ */
+void QSGContext::setRenderAlpha(qreal renderAlpha)
+{
+ d_func()->renderAlpha = renderAlpha;
+}
+
+
+/*!
+ Returns the toplevel opacity used for rendering.
+
+ The default value is 1.
+
+ \sa setRenderAlpha()
+ */
+qreal QSGContext::renderAlpha() const
+{
+ return d_func()->renderAlpha;
+}
+
+
+/*!
+ Sets whether or not the scene graph should use the distance field technique to render text
+ */
+void QSGContext::setDistanceFieldEnabled(bool enabled)
+{
+ d_func()->distanceFieldDisabled = !enabled;
+}
+
+
+/*!
+ Returns true if the scene graph uses the distance field technique to render text
+ */
+bool QSGContext::isDistanceFieldEnabled() const
+{
+ return !d_func()->distanceFieldDisabled;
+}
+
+
+
+/*!
+ Creates a new animation driver.
+ */
+
+QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
+{
+ return new QAnimationDriver(parent);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
new file mode 100644
index 0000000000..ded9d2727a
--- /dev/null
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGCONTEXT_H
+#define QSGCONTEXT_H
+
+#include <QtCore/QObject>
+#include <QtCore/qabstractanimation.h>
+
+#include <QtGui/QImage>
+#include <QtGui/QSurfaceFormat>
+
+#include <private/qrawfont_p.h>
+
+#include <QtQuick/qsgnode.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGContextPrivate;
+class QSGRectangleNode;
+class QSGImageNode;
+class QSGGlyphNode;
+class QSGRenderer;
+class QSGDistanceFieldGlyphCache;
+
+class QSGTexture;
+class QSGMaterial;
+class QSGMaterialShader;
+class QSGEngine;
+
+class QOpenGLContext;
+class QOpenGLFramebufferObject;
+
+class QDeclarativeTextureFactory;
+
+class Q_QUICK_EXPORT QSGContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGContext)
+
+public:
+ explicit QSGContext(QObject *parent = 0);
+ ~QSGContext();
+
+ virtual void initialize(QOpenGLContext *context);
+
+ QSGRenderer *renderer() const;
+
+ void setRootNode(QSGRootNode *node);
+ QSGRootNode *rootNode() const;
+
+ QOpenGLContext *glContext() const;
+
+ bool isReady() const;
+
+ QSGMaterialShader *prepareMaterial(QSGMaterial *material);
+
+ virtual void renderNextFrame(QOpenGLFramebufferObject *fbo = 0);
+
+ virtual QSGDistanceFieldGlyphCache *createDistanceFieldGlyphCache(const QRawFont &font);
+
+ virtual QSGRectangleNode *createRectangleNode();
+ virtual QSGImageNode *createImageNode();
+ virtual QSGGlyphNode *createGlyphNode();
+ virtual QSGRenderer *createRenderer();
+
+ virtual bool canDecodeImageToTexture() const;
+ virtual QSGTexture *decodeImageToTexture(QIODevice *dev,
+ QSize *size,
+ const QSize &requestSize);
+ virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
+ virtual QSize minimumFBOSize() const;
+
+ virtual QSurfaceFormat defaultSurfaceFormat() const;
+
+ QSGTexture *textureForFactory(QDeclarativeTextureFactory *factory);
+
+ static QSGContext *createDefaultContext();
+
+ void setFlashModeEnabled(bool enabled);
+ bool isFlashModeEnabled() const;
+
+ void setRenderAlpha(qreal renderAlpha);
+ qreal renderAlpha() const;
+
+ void setDistanceFieldEnabled(bool enabled);
+ bool isDistanceFieldEnabled() const;
+
+ virtual QAnimationDriver *createAnimationDriver(QObject *parent);
+
+signals:
+ void ready();
+
+public slots:
+ void textureFactoryDestroyed(QObject *o);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGCONTEXT_H
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
new file mode 100644
index 0000000000..a07793f44f
--- /dev/null
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgcontextplugin_p.h"
+#include <QtQuick/private/qsgcontext_p.h>
+#include <QtGui/qguiapplication.h>
+#include <QtCore/private/qfactoryloader_p.h>
+#include <QtCore/qlibraryinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+QSGContextPlugin::QSGContextPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QSGContextPlugin::~QSGContextPlugin()
+{
+}
+
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QSGContextFactoryInterface_iid, QLatin1String("/scenegraph")))
+#endif
+
+/*!
+ \fn QSGContext *QSGContext::createDefaultContext()
+
+ Creates a default scene graph context for the current hardware.
+ This may load a device-specific plugin.
+*/
+QSGContext *QSGContext::createDefaultContext()
+{
+ const QStringList args = QGuiApplication::arguments();
+ QString device;
+ for (int index = 0; index < args.count(); ++index) {
+ if (args.at(index).startsWith(QLatin1String("--device="))) {
+ device = args.at(index).mid(9);
+ break;
+ }
+ }
+ if (device.isEmpty())
+ device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
+ if (device.isEmpty())
+ return new QSGContext();
+
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ if (QSGContextFactoryInterface *factory
+ = qobject_cast<QSGContextFactoryInterface*>
+ (loader()->instance(device))) {
+ QSGContext *context = factory->create(device);
+ if (context)
+ return context;
+ }
+#ifndef QT_NO_DEBUG
+ qWarning("Could not create scene graph context for device '%s'"
+ " - check that plugins are installed correctly in %s",
+ qPrintable(device),
+ qPrintable(QLibraryInfo::location(QLibraryInfo::PluginsPath)));
+#endif
+#endif // QT_NO_LIBRARY || QT_NO_SETTINGS
+
+ return new QSGContext();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontextplugin_p.h b/src/quick/scenegraph/qsgcontextplugin_p.h
new file mode 100644
index 0000000000..a480ee51eb
--- /dev/null
+++ b/src/quick/scenegraph/qsgcontextplugin_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGCONTEXTPLUGIN_H
+#define QSGCONTEXTPLUGIN_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGContext;
+
+struct Q_QUICK_EXPORT QSGContextFactoryInterface : public QFactoryInterface
+{
+ virtual QSGContext *create(const QString &key) const = 0;
+};
+
+#define QSGContextFactoryInterface_iid \
+ "com.trolltech.Qt.QSGContextFactoryInterface"
+Q_DECLARE_INTERFACE(QSGContextFactoryInterface, QSGContextFactoryInterface_iid)
+
+class Q_QUICK_EXPORT QSGContextPlugin : public QObject, public QSGContextFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QSGContextFactoryInterface:QFactoryInterface)
+public:
+ explicit QSGContextPlugin(QObject *parent = 0);
+ virtual ~QSGContextPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QSGContext *create(const QString &key) const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGCONTEXTPLUGIN_H
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
new file mode 100644
index 0000000000..95ccc8f437
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdefaultdistancefieldglyphcache_p.h"
+
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <qopenglfunctions.h>
+
+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_textureData = textureData(c);
+}
+
+void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector<glyph_t> &glyphs)
+{
+ int count = glyphs.count();
+
+ // Avoid useless and costly glyph re-generation
+ if (cacheIsFull() && !m_textureData->unusedGlyphs.isEmpty()) {
+ for (int i = 0; i < count; ++i) {
+ glyph_t glyphIndex = glyphs.at(i);
+ if (containsGlyph(glyphIndex) && m_textureData->unusedGlyphs.contains(glyphIndex))
+ m_textureData->unusedGlyphs.remove(glyphIndex);
+ }
+ }
+
+ QList<GlyphPosition> glyphPositions;
+ QVector<glyph_t> glyphsToRender;
+
+ for (int i = 0; i < count; ++i) {
+ glyph_t glyphIndex = glyphs.at(i);
+
+ if (++m_textureData->glyphRefCount[glyphIndex] == 1)
+ m_textureData->unusedGlyphs.remove(glyphIndex);
+
+ if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
+ continue;
+
+ GlyphPosition p;
+ p.glyph = glyphIndex;
+ p.position = QPointF(m_textureData->currX, m_textureData->currY);
+
+ if (!cacheIsFull()) {
+ m_textureData->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+ if (m_textureData->currX >= maxTextureSize()) {
+ m_textureData->currX = 0;
+ m_textureData->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+ }
+ } else {
+ // Recycle glyphs
+ if (!m_textureData->unusedGlyphs.isEmpty()) {
+ glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
+ TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
+ p.position = QPointF(unusedCoord.x, unusedCoord.y);
+ m_textureData->unusedGlyphs.remove(unusedGlyph);
+ removeGlyph(unusedGlyph);
+ }
+ }
+
+ if (p.position.y() < maxTextureSize()) {
+ glyphPositions.append(p);
+ glyphsToRender.append(glyphIndex);
+ }
+ }
+
+ addGlyphPositions(glyphPositions);
+ markGlyphsToRender(glyphsToRender);
+}
+
+void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage> &glyphs)
+{
+ int requiredWidth = maxTextureSize();
+ int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default..
+ int requiredHeight = qMin(maxTextureSize(),
+ qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
+ QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows));
+
+ resizeTexture((requiredWidth), (requiredHeight));
+ glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+ 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);
+
+ glyphTextures.append(glyphIndex);
+
+ QImage glyph = it.value();
+
+ if (useWorkaroundBrokenFBOReadback()) {
+ uchar *inBits = glyph.scanLine(0);
+ uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x);
+ for (int y = 0; y < glyph.height(); ++y) {
+ qMemCopy(outBits, inBits, glyph.width());
+ inBits += glyph.bytesPerLine();
+ outBits += m_textureData->image.bytesPerLine();
+ }
+ }
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
+ }
+
+ Texture t;
+ t.textureId = m_textureData->texture;
+ t.size = m_textureData->size;
+ addGlyphTextures(glyphTextures, t);
+}
+
+void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector<glyph_t> &glyphs)
+{
+ int count = glyphs.count();
+ for (int i = 0; i < count; ++i) {
+ glyph_t glyphIndex = glyphs.at(i);
+ if (--m_textureData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
+ m_textureData->unusedGlyphs.insert(glyphIndex);
+ }
+}
+
+void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
+{
+ if (useWorkaroundBrokenFBOReadback() && m_textureData->image.isNull())
+ m_textureData->image = QImage(width, height, QImage::Format_Indexed8);
+
+ while (glGetError() != GL_NO_ERROR) { }
+
+ glGenTextures(1, &m_textureData->texture);
+ glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ m_textureData->size = QSize(width, height);
+
+ GLuint error = glGetError();
+ if (error != GL_NO_ERROR) {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &m_textureData->texture);
+ m_textureData->texture = 0;
+ }
+
+}
+
+void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
+{
+ int oldWidth = m_textureData->size.width();
+ int oldHeight = m_textureData->size.height();
+ if (width == oldWidth && height == oldHeight)
+ return;
+
+ GLuint oldTexture = m_textureData->texture;
+ createTexture(width, height);
+
+ if (!oldTexture)
+ return;
+
+ updateTexture(oldTexture, m_textureData->texture, m_textureData->size);
+
+ if (useWorkaroundBrokenFBOReadback()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, m_textureData->image.constBits());
+ m_textureData->image = m_textureData->image.copy(0, 0, width, height);
+ glDeleteTextures(1, &oldTexture);
+ return;
+ }
+
+ if (!m_textureData->blitProgram)
+ m_textureData->createBlitProgram();
+
+ Q_ASSERT(m_textureData->blitProgram);
+
+ if (!m_textureData->fbo)
+ ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo);
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo);
+
+ GLuint tmp_texture;
+ glGenTextures(1, &tmp_texture);
+ glBindTexture(GL_TEXTURE_2D, tmp_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tmp_texture, 0);
+
+ ctx->functions()->glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, oldTexture);
+
+ // save current render states
+ GLboolean stencilTestEnabled;
+ GLboolean depthTestEnabled;
+ GLboolean scissorTestEnabled;
+ GLboolean blendEnabled;
+ GLint viewport[4];
+ GLint oldProgram;
+ glGetBooleanv(GL_STENCIL_TEST, &stencilTestEnabled);
+ glGetBooleanv(GL_DEPTH_TEST, &depthTestEnabled);
+ glGetBooleanv(GL_SCISSOR_TEST, &scissorTestEnabled);
+ glGetBooleanv(GL_BLEND, &blendEnabled);
+ glGetIntegerv(GL_VIEWPORT, &viewport[0]);
+ glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram);
+
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_BLEND);
+
+ 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);
+
+ 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));
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+
+ ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, 0);
+ glDeleteTextures(1, &tmp_texture);
+ glDeleteTextures(1, &oldTexture);
+
+ ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // restore render states
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (depthTestEnabled)
+ glEnable(GL_DEPTH_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ if (blendEnabled)
+ glEnable(GL_BLEND);
+ glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+ ctx->functions()->glUseProgram(oldProgram);
+}
+
+bool QSGDefaultDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
+{
+ static bool set = false;
+ static bool useWorkaround = false;
+ if (!set) {
+ QOpenGLContextPrivate *ctx_p = static_cast<QOpenGLContextPrivate *>(QOpenGLContextPrivate::get(ctx));
+ useWorkaround = ctx_p->workaround_brokenFBOReadBack;
+ set = true;
+ }
+ return useWorkaround;
+}
+
+int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const
+{
+ if (!m_maxTextureSize)
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
+ return m_maxTextureSize;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
new file mode 100644
index 0000000000..b52ec45107
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
+#define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
+
+#include <QtGui/qopenglfunctions.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <qopenglshaderprogram.h>
+#include <QtGui/private/qopenglengineshadersource_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
+{
+public:
+ QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+
+ void requestGlyphs(const QVector<glyph_t> &glyphs);
+ void storeGlyphs(const QHash<glyph_t, QImage> &glyphs);
+ void releaseGlyphs(const QVector<glyph_t> &glyphs);
+
+ bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
+ bool useWorkaroundBrokenFBOReadback() const;
+ int maxTextureSize() const;
+
+private:
+ void createTexture(int width, int height);
+ void resizeTexture(int width, int height);
+
+ mutable int m_maxTextureSize;
+
+ struct DistanceFieldTextureData : public QOpenGLSharedResource {
+ GLuint texture;
+ GLuint fbo;
+ QSize size;
+ QHash<glyph_t, quint32> glyphRefCount;
+ QSet<glyph_t> unusedGlyphs;
+ int currX;
+ int currY;
+ QImage image;
+
+ QOpenGLShaderProgram *blitProgram;
+ GLfloat blitVertexCoordinateArray[8];
+ GLfloat blitTextureCoordinateArray[8];
+
+ DistanceFieldTextureData(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , texture(0)
+ , fbo(0)
+ , currX(0)
+ , currY(0)
+ , blitProgram(0)
+ {
+ 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;
+ }
+
+ void invalidateResource()
+ {
+ texture = 0;
+ fbo = 0;
+ size = QSize();
+ delete blitProgram;
+ blitProgram = 0;
+ }
+
+ void freeResource(QOpenGLContext *ctx)
+ {
+ glDeleteTextures(1, &texture);
+ ctx->functions()->glDeleteFramebuffers(1, &fbo);
+ delete blitProgram;
+ blitProgram = 0;
+ }
+
+ 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();
+ }
+ };
+
+ DistanceFieldTextureData *textureData(QOpenGLContext *c);
+ DistanceFieldTextureData *m_textureData;
+ static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
index f41fbe486a..f41fbe486a 100644
--- a/src/declarative/scenegraph/qsgdefaultglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
new file mode 100644
index 0000000000..36efe9b570
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdefaultglyphnode_p_p.h"
+
+#include <qopenglshaderprogram.h>
+
+#include <QtGui/private/qopengltextureglyphcache_p.h>
+#include <private/qfontengine_p.h>
+#include <private/qopenglextensions_p.h>
+
+#include <QtQuick/private/qsgtexture_p.h>
+
+#include <private/qrawfont_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGTextMaskMaterialData : public QSGMaterialShader
+{
+public:
+ QSGTextMaskMaterialData();
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+ int m_color_id;
+ int m_textureScale_id;
+};
+
+const char *QSGTextMaskMaterialData::vertexShader() const {
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *QSGTextMaskMaterialData::fragmentShader() const {
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color * texture2D(texture, sampleCoord).a; \n"
+ "}";
+}
+
+char const *const *QSGTextMaskMaterialData::attributeNames() const
+{
+ static char const *const attr[] = { "vCoord", "tCoord", 0 };
+ return attr;
+}
+
+QSGTextMaskMaterialData::QSGTextMaskMaterialData()
+{
+}
+
+void QSGTextMaskMaterialData::initialize()
+{
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_color_id = program()->uniformLocation("color");
+ m_textureScale_id = program()->uniformLocation("textureScale");
+}
+
+void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ QSGTextMaskMaterial *material = static_cast<QSGTextMaskMaterial *>(newEffect);
+ QSGTextMaskMaterial *oldMaterial = static_cast<QSGTextMaskMaterial *>(oldEffect);
+
+ if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
+ QVector4D color(material->color().redF(), material->color().greenF(),
+ material->color().blueF(), material->color().alphaF());
+ color *= state.opacity();
+ program()->setUniformValue(m_color_id, color);
+ }
+
+ bool updated = material->ensureUpToDate();
+ Q_ASSERT(material->texture());
+
+ Q_ASSERT(oldMaterial == 0 || oldMaterial->texture());
+ if (updated
+ || oldMaterial == 0
+ || oldMaterial->texture()->textureId() != material->texture()->textureId()) {
+ program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->cacheTextureWidth(),
+ 1.0 / material->cacheTextureHeight()));
+ glBindTexture(GL_TEXTURE_2D, material->texture()->textureId());
+
+ // Set the mag/min filters to be linear. We only need to do this when the texture
+ // has been recreated.
+ if (updated) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ }
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font)
+ : m_texture(0), m_glyphCache(), m_font(font)
+{
+ init();
+}
+
+QSGTextMaskMaterial::~QSGTextMaskMaterial()
+{
+}
+
+void QSGTextMaskMaterial::init()
+{
+ Q_ASSERT(m_font.isValid());
+
+ QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_A8;
+ setFlag(Blending, true);
+
+ QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ Q_ASSERT(ctx != 0);
+
+ QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
+ if (fontD->fontEngine != 0) {
+ m_glyphCache = fontD->fontEngine->glyphCache(ctx, type, QTransform());
+ if (!m_glyphCache || m_glyphCache->cacheType() != type) {
+ m_glyphCache = new QOpenGLTextureGlyphCache(type, QTransform());
+ fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
+ }
+ }
+}
+
+void QSGTextMaskMaterial::populate(const QPointF &p,
+ const QVector<quint32> &glyphIndexes,
+ const QVector<QPointF> &glyphPositions,
+ QSGGeometry *geometry,
+ QRectF *boundingRect,
+ QPointF *baseLine)
+{
+ Q_ASSERT(m_font.isValid());
+ QVector<QFixedPoint> fixedPointPositions;
+ for (int i=0; i<glyphPositions.size(); ++i)
+ fixedPointPositions.append(QFixedPoint::fromPointF(glyphPositions.at(i)));
+
+ QTextureGlyphCache *cache = glyphCache();
+
+ QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
+ cache->populate(fontD->fontEngine, glyphIndexes.size(), glyphIndexes.constData(),
+ fixedPointPositions.data());
+ cache->fillInPendingGlyphs();
+
+ int margin = cache->glyphMargin();
+
+ Q_ASSERT(geometry->indexType() == GL_UNSIGNED_SHORT);
+ geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6);
+ QVector4D *vp = (QVector4D *)geometry->vertexDataAsTexturedPoint2D();
+ Q_ASSERT(geometry->sizeOfVertex() == sizeof(QVector4D));
+ ushort *ip = geometry->indexDataAsUShort();
+
+ QPointF position(p.x(), p.y() - m_font.ascent());
+ bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions();
+ for (int i=0; i<glyphIndexes.size(); ++i) {
+ QFixed subPixelPosition;
+ if (supportsSubPixelPositions)
+ subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPositions.at(i).x()));
+
+ QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition);
+ const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
+
+ QPointF glyphPosition = glyphPositions.at(i) + position;
+ int x = qRound(glyphPosition.x()) + c.baseLineX - margin;
+ int y = qRound(glyphPosition.y()) - c.baseLineY - margin;
+
+ *boundingRect |= QRectF(x + margin, y + margin, c.w, c.h);
+
+ float cx1 = x;
+ float cx2 = x + c.w;
+ float cy1 = y;
+ float cy2 = y + c.h;
+
+ float tx1 = c.x;
+ float tx2 = (c.x + c.w);
+ float ty1 = c.y;
+ float ty2 = (c.y + c.h);
+
+ if (baseLine->isNull())
+ *baseLine = glyphPosition;
+
+ vp[4 * i + 0] = QVector4D(cx1, cy1, tx1, ty1);
+ vp[4 * i + 1] = QVector4D(cx2, cy1, tx2, ty1);
+ vp[4 * i + 2] = QVector4D(cx1, cy2, tx1, ty2);
+ vp[4 * i + 3] = QVector4D(cx2, cy2, tx2, ty2);
+
+ int o = i * 4;
+ ip[6 * i + 0] = o + 0;
+ ip[6 * i + 1] = o + 2;
+ ip[6 * i + 2] = o + 3;
+ ip[6 * i + 3] = o + 3;
+ ip[6 * i + 4] = o + 1;
+ ip[6 * i + 5] = o + 0;
+ }
+}
+
+QSGMaterialType *QSGTextMaskMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QOpenGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const
+{
+ return static_cast<QOpenGLTextureGlyphCache*>(m_glyphCache.data());
+}
+
+QSGMaterialShader *QSGTextMaskMaterial::createShader() const
+{
+ return new QSGTextMaskMaterialData;
+}
+
+int QSGTextMaskMaterial::compare(const QSGMaterial *o) const
+{
+ Q_ASSERT(o && type() == o->type());
+ const QSGTextMaskMaterial *other = static_cast<const QSGTextMaskMaterial *>(o);
+ if (m_glyphCache != other->m_glyphCache)
+ return m_glyphCache - other->m_glyphCache;
+ QRgb c1 = m_color.rgba();
+ QRgb c2 = other->m_color.rgba();
+ return int(c2 < c1) - int(c1 < c2);
+}
+
+bool QSGTextMaskMaterial::ensureUpToDate()
+{
+ QSize glyphCacheSize(glyphCache()->width(), glyphCache()->height());
+ if (glyphCacheSize != m_size) {
+ if (m_texture)
+ delete m_texture;
+ m_texture = new QSGPlainTexture();
+ m_texture->setTextureId(glyphCache()->texture());
+ m_texture->setTextureSize(QSize(glyphCache()->width(), glyphCache()->height()));
+ m_texture->setOwnsTexture(false);
+
+ m_size = glyphCacheSize;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int QSGTextMaskMaterial::cacheTextureWidth() const
+{
+ return glyphCache()->width();
+}
+
+int QSGTextMaskMaterial::cacheTextureHeight() const
+{
+ return glyphCache()->height();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
new file mode 100644
index 0000000000..cc14d33a30
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DEFAULT_GLYPHNODE_H
+#define DEFAULT_GLYPHNODE_H
+
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/qsgnode.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGlyphs;
+class QSGTextMaskMaterial;
+class QSGDefaultGlyphNode: public QSGGlyphNode
+{
+public:
+ QSGDefaultGlyphNode();
+ ~QSGDefaultGlyphNode();
+
+ virtual QPointF baseLine() const { return m_baseLine; }
+ virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs);
+ virtual void setColor(const QColor &color);
+
+ virtual void setPreferredAntialiasingMode(AntialiasingMode) { }
+ virtual void setStyle(QQuickText::TextStyle) { }
+ virtual void setStyleColor(const QColor &) { }
+
+ virtual void update() { }
+
+private:
+ QGlyphRun m_glyphs;
+ QPointF m_position;
+ QColor m_color;
+
+ QPointF m_baseLine;
+ QSGTextMaskMaterial *m_material;
+
+ QSGGeometry m_geometry;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DEFAULT_GLYPHNODE_H
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
new file mode 100644
index 0000000000..2378178a1b
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 TEXTMASKMATERIAL_H
+#define TEXTMASKMATERIAL_H
+
+#include <qcolor.h>
+#include <QtQuick/qsgmaterial.h>
+#include <QtQuick/qsgtexture.h>
+#include <QtQuick/qsggeometry.h>
+#include <qshareddata.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include <qrawfont.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFontEngineGlyphCache;
+class QOpenGLTextureGlyphCache;
+class QFontEngine;
+class Geometry;
+class QSGTextMaskMaterial: public QSGMaterial
+{
+public:
+ QSGTextMaskMaterial(const QRawFont &font);
+ ~QSGTextMaskMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setColor(const QColor &color) { m_color = color; }
+ const QColor &color() const { return m_color; }
+
+ QSGTexture *texture() const { return m_texture; }
+
+ int cacheTextureWidth() const;
+ int cacheTextureHeight() const;
+
+ bool ensureUpToDate();
+
+ QOpenGLTextureGlyphCache *glyphCache() const;
+ void populate(const QPointF &position,
+ const QVector<quint32> &glyphIndexes, const QVector<QPointF> &glyphPositions,
+ QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine);
+
+private:
+ void init();
+
+ QSGPlainTexture *m_texture;
+ QExplicitlySharedDataPointer<QFontEngineGlyphCache> m_glyphCache;
+ QRawFont m_font;
+ QColor m_color;
+ QSize m_size;
+};
+
+QT_END_NAMESPACE
+
+#endif // TEXTMASKMATERIAL_H
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
new file mode 100644
index 0000000000..f360aaef0d
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdefaultimagenode_p.h"
+
+#include <QtQuick/private/qsgtextureprovider_p.h>
+
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmath.h>
+#include <QtGui/qopenglfunctions.h>
+
+QT_BEGIN_NAMESPACE
+
+QSGDefaultImageNode::QSGDefaultImageNode()
+ : m_sourceRect(0, 0, 1, 1)
+ , m_dirtyGeometry(false)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+{
+ setMaterial(&m_materialO);
+ setOpaqueMaterial(&m_material);
+ setGeometry(&m_geometry);
+
+#ifdef QML_RUNTIME_TESTING
+ description = QLatin1String("image");
+#endif
+}
+
+void QSGDefaultImageNode::setTargetRect(const QRectF &rect)
+{
+ if (rect == m_targetRect)
+ return;
+ m_targetRect = rect;
+ m_dirtyGeometry = true;
+}
+
+void QSGDefaultImageNode::setSourceRect(const QRectF &rect)
+{
+ if (rect == m_sourceRect)
+ return;
+ m_sourceRect = rect;
+ m_dirtyGeometry = true;
+}
+
+
+void QSGDefaultImageNode::setFiltering(QSGTexture::Filtering filtering)
+{
+ if (m_material.filtering() == filtering)
+ return;
+
+ m_material.setFiltering(filtering);
+ m_materialO.setFiltering(filtering);
+ markDirty(DirtyMaterial);
+}
+
+
+void QSGDefaultImageNode::setMipmapFiltering(QSGTexture::Filtering filtering)
+{
+ if (m_material.mipmapFiltering() == filtering)
+ return;
+
+ m_material.setMipmapFiltering(filtering);
+ m_materialO.setMipmapFiltering(filtering);
+ markDirty(DirtyMaterial);
+}
+
+void QSGDefaultImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode)
+{
+ if (m_material.verticalWrapMode() == wrapMode)
+ return;
+
+ m_material.setVerticalWrapMode(wrapMode);
+ m_materialO.setVerticalWrapMode(wrapMode);
+ markDirty(DirtyMaterial);
+}
+
+void QSGDefaultImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)
+{
+ if (m_material.horizontalWrapMode() == wrapMode)
+ return;
+
+ m_material.setHorizontalWrapMode(wrapMode);
+ m_materialO.setHorizontalWrapMode(wrapMode);
+ markDirty(DirtyMaterial);
+}
+
+
+void QSGDefaultImageNode::setTexture(QSGTexture *texture)
+{
+ if (texture == m_material.texture())
+ return;
+
+ m_material.setTexture(texture);
+ m_materialO.setTexture(texture);
+ // Texture cleanup
+// if (!texture.isNull())
+// m_material.setBlending(texture->hasAlphaChannel());
+ markDirty(DirtyMaterial);
+
+ // Because the texture can be a different part of the atlas, we need to update it...
+ m_dirtyGeometry = true;
+}
+
+void QSGDefaultImageNode::update()
+{
+ if (m_dirtyGeometry)
+ updateGeometry();
+}
+
+void QSGDefaultImageNode::preprocess()
+{
+ bool doDirty = false;
+ QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
+ if (t) {
+ doDirty = t->updateTexture();
+ updateGeometry();
+ }
+// ### texture cleanup
+// bool alpha = m_material.blending();
+// if (!m_material->texture().isNull() && alpha != m_material.texture()->hasAlphaChannel()) {
+// m_material.setBlending(!alpha);
+// doDirty = true;
+// }
+
+ if (doDirty)
+ markDirty(DirtyMaterial);
+}
+
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+namespace {
+ struct X { float x, tx; };
+ struct Y { float y, ty; };
+}
+
+void QSGDefaultImageNode::updateGeometry()
+{
+ const QSGTexture *t = m_material.texture();
+ if (!t) {
+ m_geometry.allocate(4);
+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, QRectF(), QRectF());
+ } else {
+ QRectF textureRect = t->textureSubRect();
+
+ bool isSubRect = textureRect != QRectF(0, 0, 1, 1);
+ const int ceilRight = qCeil(m_sourceRect.right());
+ const int floorLeft = qFloor(m_sourceRect.left());
+ const int ceilBottom = qCeil(m_sourceRect.bottom());
+ const int floorTop = qFloor(m_sourceRect.top());
+ const int hCells = ceilRight - floorLeft;
+ const int vCells = ceilBottom - floorTop;
+ bool isRepeating = hCells > 1 || vCells > 1;
+
+#ifdef QT_OPENGL_ES_2
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+
+ QSize size = t->textureSize();
+ bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+
+ if (isRepeating && (isSubRect || (isNpot && !npotSupported))) {
+#else
+ if (isRepeating && isSubRect) {
+#endif
+ m_geometry.allocate(hCells * vCells * 4, hCells * vCells * 6);
+ m_geometry.setDrawingMode(GL_TRIANGLES);
+ QVarLengthArray<X, 32> xData(2 * hCells);
+ QVarLengthArray<Y, 32> yData(2 * vCells);
+ X *xs = xData.data();
+ Y *ys = yData.data();
+
+ xs->x = m_targetRect.left();
+ xs->tx = textureRect.x() + (m_sourceRect.left() - floorLeft) * textureRect.width();
+ ++xs;
+ ys->y = m_targetRect.top();
+ ys->ty = textureRect.y() + (m_sourceRect.top() - floorTop) * textureRect.height();
+ ++ys;
+
+ float a, b;
+ b = m_targetRect.width() / m_sourceRect.width();
+ a = m_targetRect.x() - m_sourceRect.x() * b;
+
+ float tex_x1 = textureRect.x();
+ float tex_x2 = textureRect.right();
+ float tex_y1 = textureRect.y();
+ float tex_y2 = textureRect.bottom();
+ for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
+ xs[0].x = xs[1].x = a + b * i;
+ xs[0].tx = tex_x2;
+ xs[1].tx = tex_x1;
+ xs += 2;
+ }
+ b = m_targetRect.height() / m_sourceRect.height();
+ a = m_targetRect.y() - m_sourceRect.y() * b;
+ for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
+ ys[0].y = ys[1].y = a + b * i;
+ ys[0].ty = tex_y2;
+ ys[1].ty = tex_y1;
+ ys += 2;
+ }
+
+ xs->x = m_targetRect.right();
+ xs->tx = textureRect.x() + (m_sourceRect.right() - ceilRight + 1) * textureRect.width();
+
+ ys->y = m_targetRect.bottom();
+ ys->ty = textureRect.y() + (m_sourceRect.bottom() - ceilBottom + 1) * textureRect.height();
+
+ QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D();
+ ys = yData.data();
+ for (int j = 0; j < vCells; ++j, ys += 2) {
+ xs = xData.data();
+ for (int i = 0; i < hCells; ++i, xs += 2) {
+ vertices[0].x = vertices[2].x = xs[0].x;
+ vertices[0].tx = vertices[2].tx = xs[0].tx;
+ vertices[1].x = vertices[3].x = xs[1].x;
+ vertices[1].tx = vertices[3].tx = xs[1].tx;
+
+ vertices[0].y = vertices[1].y = ys[0].y;
+ vertices[0].ty = vertices[1].ty = ys[0].ty;
+ vertices[2].y = vertices[3].y = ys[1].y;
+ vertices[2].ty = vertices[3].ty = ys[1].ty;
+
+ vertices += 4;
+ }
+ }
+
+ quint16 *indices = m_geometry.indexDataAsUShort();
+ for (int i = 0; i < 4 * vCells * hCells; i += 4) {
+ *indices++ = i;
+ *indices++ = i + 2;
+ *indices++ = i + 3;
+ *indices++ = i + 3;
+ *indices++ = i + 1;
+ *indices++ = i;
+ }
+ } else {
+ QRectF sr(textureRect.x() + m_sourceRect.x() * textureRect.width(),
+ textureRect.y() + m_sourceRect.y() * textureRect.height(),
+ m_sourceRect.width() * textureRect.width(),
+ m_sourceRect.height() * textureRect.height());
+
+ m_geometry.allocate(4);
+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr);
+ }
+ }
+ markDirty(DirtyGeometry);
+ m_dirtyGeometry = false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h
new file mode 100644
index 0000000000..f1b416d69c
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DEFAULT_PIXMAPNODE_H
+#define DEFAULT_PIXMAPNODE_H
+
+#include <private/qsgadaptationlayer_p.h>
+
+#include <QtQuick/qsgtexturematerial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGDefaultImageNode : public QSGImageNode
+{
+public:
+ QSGDefaultImageNode();
+ virtual void setTargetRect(const QRectF &rect);
+ virtual void setSourceRect(const QRectF &rect);
+ virtual void setTexture(QSGTexture *t);
+ virtual void update();
+
+ virtual void setMipmapFiltering(QSGTexture::Filtering filtering);
+ virtual void setFiltering(QSGTexture::Filtering filtering);
+ virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode);
+ virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode);
+
+ virtual void preprocess();
+
+private:
+ void updateGeometry();
+
+ QRectF m_targetRect;
+ QRectF m_sourceRect;
+
+ QSGOpaqueTextureMaterial m_material;
+ QSGTextureMaterial m_materialO;
+
+ uint m_dirtyGeometry : 1;
+
+ QSGGeometry m_geometry;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
new file mode 100644
index 0000000000..bb89b4a9f8
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
@@ -0,0 +1,548 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdefaultrectanglenode_p.h"
+
+#include <QtQuick/qsgvertexcolormaterial.h>
+#include <QtQuick/qsgtexturematerial.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+
+#include <QtCore/qmath.h>
+#include <QtCore/qvarlengtharray.h>
+
+QT_BEGIN_NAMESPACE
+
+QSGDefaultRectangleNode::QSGDefaultRectangleNode(QSGContext *context)
+ : m_border(0)
+ , m_radius(0)
+ , m_pen_width(0)
+ , m_aligned(true)
+ , m_gradient_is_opaque(true)
+ , m_dirty_geometry(false)
+ , m_default_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
+ , m_context(context)
+{
+ setGeometry(&m_default_geometry);
+ setMaterial(&m_fill_material);
+ m_border_material.setColor(QColor(0, 0, 0));
+
+ m_material_type = TypeFlat;
+
+#ifdef QML_RUNTIME_TESTING
+ description = QLatin1String("rectangle");
+#endif
+}
+
+QSGDefaultRectangleNode::~QSGDefaultRectangleNode()
+{
+ if (m_material_type == TypeVertexGradient)
+ delete material();
+ delete m_border;
+}
+
+QSGGeometryNode *QSGDefaultRectangleNode::border()
+{
+ if (!m_border) {
+ m_border = new QSGGeometryNode;
+ m_border->setMaterial(&m_border_material);
+ QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
+ m_border->setGeometry(geometry);
+ m_border->setFlag(QSGNode::OwnsGeometry);
+ }
+ return m_border;
+}
+
+void QSGDefaultRectangleNode::setRect(const QRectF &rect)
+{
+ if (rect == m_rect)
+ return;
+ m_rect = rect;
+ m_dirty_geometry = true;
+}
+
+void QSGDefaultRectangleNode::setColor(const QColor &color)
+{
+ if (color == m_fill_material.color())
+ return;
+ m_fill_material.setColor(color);
+ if (m_gradient_stops.isEmpty()) {
+ Q_ASSERT(m_material_type == TypeFlat);
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGDefaultRectangleNode::setPenColor(const QColor &color)
+{
+ if (color == m_border_material.color())
+ return;
+ m_border_material.setColor(color);
+ if (m_border)
+ m_border->markDirty(DirtyMaterial);
+}
+
+void QSGDefaultRectangleNode::setPenWidth(qreal width)
+{
+ if (width == m_pen_width)
+ return;
+ m_pen_width = width;
+ if (m_pen_width <= 0 && m_border && m_border->parent())
+ removeChildNode(m_border);
+ else if (m_pen_width > 0 && !border()->parent())
+ appendChildNode(m_border);
+ m_dirty_geometry = true;
+}
+
+
+void QSGDefaultRectangleNode::setGradientStops(const QGradientStops &stops)
+{
+ if (stops.constData() == m_gradient_stops.constData())
+ return;
+
+ m_gradient_stops = stops;
+
+ m_gradient_is_opaque = true;
+ for (int i = 0; i < stops.size(); ++i)
+ m_gradient_is_opaque &= stops.at(i).second.alpha() == 0xff;
+
+ if (stops.isEmpty()) {
+ // No gradient specified, use flat color.
+ if (m_material_type != TypeFlat) {
+ delete material();
+
+ setMaterial(&m_fill_material);
+ m_material_type = TypeFlat;
+
+ setGeometry(&m_default_geometry);
+ setFlag(OwnsGeometry, false);
+ }
+ } else {
+ if (m_material_type == TypeFlat) {
+ QSGVertexColorMaterial *material = new QSGVertexColorMaterial;
+ setMaterial(material);
+ m_material_type = TypeVertexGradient;
+ QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0);
+ setGeometry(g);
+ setFlag(OwnsGeometry);
+ }
+ static_cast<QSGVertexColorMaterial *>(material())->setFlag(QSGMaterial::Blending, !m_gradient_is_opaque);
+ }
+
+ m_dirty_geometry = true;
+}
+
+void QSGDefaultRectangleNode::setRadius(qreal radius)
+{
+ if (radius == m_radius)
+ return;
+ m_radius = radius;
+ m_dirty_geometry = true;
+}
+
+void QSGDefaultRectangleNode::setAligned(bool aligned)
+{
+ if (aligned == m_aligned)
+ return;
+ m_aligned = aligned;
+ m_dirty_geometry = true;
+}
+
+void QSGDefaultRectangleNode::update()
+{
+ if (m_dirty_geometry) {
+ updateGeometry();
+ m_dirty_geometry = false;
+ }
+}
+
+struct Color4ub
+{
+ unsigned char r, g, b, a;
+};
+
+Color4ub operator *(Color4ub c, float t) { c.a *= t; c.r *= t; c.g *= t; c.b *= t; return c; }
+Color4ub operator +(Color4ub a, Color4ub b) { a.a += b.a; a.r += b.r; a.g += b.g; a.b += b.b; return a; }
+
+static inline Color4ub colorToColor4ub(const QColor &c)
+{
+ Color4ub color = { uchar(c.redF() * c.alphaF() * 255),
+ uchar(c.greenF() * c.alphaF() * 255),
+ uchar(c.blueF() * c.alphaF() * 255),
+ uchar(c.alphaF() * 255)
+ };
+ return color;
+}
+
+struct Vertex
+{
+ QVector2D position;
+};
+
+struct ColorVertex
+{
+ QVector2D position;
+ Color4ub color;
+};
+
+void QSGDefaultRectangleNode::updateGeometry()
+{
+ qreal penWidth = m_aligned ? qreal(qRound(m_pen_width)) : m_pen_width;
+
+ // fast path for the simple case...
+ if ((penWidth == 0 || m_border_material.color().alpha() == 0)
+ && m_radius == 0
+ && m_material_type == TypeFlat) {
+ QSGGeometry::updateRectGeometry(&m_default_geometry, m_rect);
+ return;
+ }
+
+ QSGGeometry *fill = geometry();
+
+ // Check that the vertex type matches the material.
+ Q_ASSERT(m_material_type != TypeFlat || fill->sizeOfVertex() == sizeof(Vertex));
+ Q_ASSERT(m_material_type != TypeVertexGradient || fill->sizeOfVertex() == sizeof(ColorVertex));
+
+ QSGGeometry *borderGeometry = 0;
+ if (m_border) {
+ borderGeometry = m_border->geometry();
+ Q_ASSERT(borderGeometry->sizeOfVertex() == sizeof(Vertex));
+ }
+
+ int fillVertexCount = 0;
+
+ // Preallocate arrays for a rectangle with 18 segments per corner and 3 gradient stops.
+ uchar *fillVertices = 0;
+ Vertex *borderVertices = 0;
+
+ Color4ub fillColor = colorToColor4ub(m_fill_material.color());
+ const QGradientStops &stops = m_gradient_stops;
+
+ if (m_radius > 0) {
+ // Rounded corners.
+
+ // Radius should never exceeds half of the width or half of the height
+ qreal radius = qMin(qMin(m_rect.width() * qreal(0.5), m_rect.height() * qreal(0.5)), m_radius);
+ QRectF innerRect = m_rect;
+ innerRect.adjust(radius, radius, -radius, -radius);
+ if (m_aligned && (int(penWidth) & 1)) {
+ // Pen width is odd, so add the offset as documented.
+ innerRect.moveLeft(innerRect.left() + qreal(0.5));
+ innerRect.moveTop(innerRect.top() + qreal(0.5));
+ }
+
+ qreal innerRadius = radius - penWidth * qreal(0.5);
+ qreal outerRadius = radius + penWidth * qreal(0.5);
+
+ // Number of segments per corner, approximately one per 3 pixels.
+ int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18);
+
+ /*
+
+ --+-__
+ | segment
+ | _+
+ --+-__ _- \
+ -+ segment
+ --------+ \ <- gradient line
+ +-----+
+ | |
+
+ */
+
+ int nextGradientStop = 0;
+ qreal gradientPos = (radius - innerRadius) / (innerRect.height() + 2 * radius);
+ while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
+ ++nextGradientStop;
+ int lastGradientStop = stops.size() - 1;
+ qreal lastGradientPos = (innerRect.height() + radius + innerRadius) / (innerRect.height() + 2 * radius);
+ while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
+ --lastGradientStop;
+
+ int borderVertexHead = 0;
+ int borderVertexTail = 0;
+ if (penWidth) {
+ // The reason I add extra vertices where the gradient lines intersect the border is
+ // to avoid pixel sized gaps between the fill and the border caused by floating point
+ // inaccuracies.
+ borderGeometry->allocate((segments + 1) * 2 * 4 + (lastGradientStop - nextGradientStop + 1) * 4 + 2);
+ borderVertexHead = borderVertexTail = (borderGeometry->vertexCount() >> 1) - 1;
+ borderVertices = (Vertex *)borderGeometry->vertexData();
+ }
+
+ fill->allocate((segments + 1) * 4 + (lastGradientStop - nextGradientStop + 1) * 2);
+ fillVertices = (uchar *)fill->vertexData();
+
+ qreal py = 0; // previous inner y-coordinate.
+ qreal plx = 0; // previous inner left x-coordinate.
+ qreal prx = 0; // previous inner right x-coordinate.
+
+ qreal angle = qreal(0.5) * M_PI / qreal(segments);
+ qreal cosStep = qFastCos(angle);
+ qreal sinStep = qFastSin(angle);
+
+ for (int part = 0; part < 2; ++part) {
+ qreal c = 1 - part;
+ qreal s = part;
+ for (int i = 0; i <= segments; ++i) {
+ qreal y, lx, rx;
+ if (innerRadius > 0) {
+ y = (part ? innerRect.bottom() : innerRect.top()) - innerRadius * c; // current inner y-coordinate.
+ lx = innerRect.left() - innerRadius * s; // current inner left x-coordinate.
+ rx = innerRect.right() + innerRadius * s; // current inner right x-coordinate.
+ gradientPos = ((part ? innerRect.height() : 0) + radius - innerRadius * c) / (innerRect.height() + 2 * radius);
+ } else {
+ y = (part ? innerRect.bottom() + innerRadius : innerRect.top() - innerRadius); // current inner y-coordinate.
+ lx = innerRect.left() - innerRadius; // current inner left x-coordinate.
+ rx = innerRect.right() + innerRadius; // current inner right x-coordinate.
+ gradientPos = ((part ? innerRect.height() + innerRadius : -innerRadius) + radius) / (innerRect.height() + 2 * radius);
+ }
+ qreal Y = (part ? innerRect.bottom() : innerRect.top()) - outerRadius * c; // current outer y-coordinate.
+ qreal lX = innerRect.left() - outerRadius * s; // current outer left x-coordinate.
+ qreal rX = innerRect.right() + outerRadius * s; // current outer right x-coordinate.
+
+ while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
+ // Insert vertices at gradient stops.
+ qreal gy = (innerRect.top() - radius) + stops.at(nextGradientStop).first * (innerRect.height() + 2 * radius);
+ Q_ASSERT(fillVertexCount >= 2);
+ qreal t = (gy - py) / (y - py);
+ qreal glx = plx * (1 - t) + t * lx;
+ qreal grx = prx * (1 - t) + t * rx;
+
+ if (penWidth) {
+ const Vertex &first = borderVertices[borderVertexHead];
+ borderVertices[--borderVertexHead].position = QVector2D(glx, gy);
+ borderVertices[--borderVertexHead] = first;
+
+ const Vertex &last = borderVertices[borderVertexTail - 2];
+ borderVertices[borderVertexTail++] = last;
+ borderVertices[borderVertexTail++].position = QVector2D(grx, gy);
+ }
+
+ ColorVertex *vertices = (ColorVertex *)fillVertices;
+
+ fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
+ vertices[fillVertexCount].position = QVector2D(grx, gy);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ vertices[fillVertexCount].position = QVector2D(glx, gy);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+
+ ++nextGradientStop;
+ }
+
+ if (penWidth) {
+ borderVertices[--borderVertexHead].position = QVector2D(lx, y);
+ borderVertices[--borderVertexHead].position = QVector2D(lX, Y);
+ borderVertices[borderVertexTail++].position = QVector2D(rX, Y);
+ borderVertices[borderVertexTail++].position = QVector2D(rx, y);
+ }
+
+ if (stops.isEmpty()) {
+ Q_ASSERT(m_material_type == TypeFlat);
+ Vertex *vertices = (Vertex *)fillVertices;
+ vertices[fillVertexCount++].position = QVector2D(rx, y);
+ vertices[fillVertexCount++].position = QVector2D(lx, y);
+ } else {
+ if (nextGradientStop == 0) {
+ fillColor = colorToColor4ub(stops.at(0).second);
+ } else if (nextGradientStop == stops.size()) {
+ fillColor = colorToColor4ub(stops.last().second);
+ } else {
+ const QGradientStop &prev = stops.at(nextGradientStop - 1);
+ const QGradientStop &next = stops.at(nextGradientStop);
+ qreal t = (gradientPos - prev.first) / (next.first - prev.first);
+ fillColor = (colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t);
+ }
+
+ ColorVertex *vertices = (ColorVertex *)fillVertices;
+ vertices[fillVertexCount].position = QVector2D(rx, y);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ vertices[fillVertexCount].position = QVector2D(lx, y);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ }
+ py = y;
+ plx = lx;
+ prx = rx;
+
+ // Rotate
+ qreal tmp = c;
+ c = c * cosStep - s * sinStep;
+ s = s * cosStep + tmp * sinStep;
+ }
+ }
+
+ if (penWidth) {
+ // Close border.
+ const Vertex &first = borderVertices[borderVertexHead];
+ const Vertex &second = borderVertices[borderVertexHead + 1];
+ borderVertices[borderVertexTail++] = first;
+ borderVertices[borderVertexTail++] = second;
+
+ Q_ASSERT(borderVertexHead == 0 && borderVertexTail == borderGeometry->vertexCount());
+ }
+ Q_ASSERT(fillVertexCount == fill->vertexCount());
+
+ } else {
+
+ // Straight corners.
+ QRectF innerRect = m_rect;
+ QRectF outerRect = m_rect;
+
+ qreal halfPenWidth = 0;
+ if (penWidth) {
+ if (m_aligned && (int(penWidth) & 1)) {
+ // Pen width is odd, so add the offset as documented.
+ innerRect.moveLeft(innerRect.left() + qreal(0.5));
+ innerRect.moveTop(innerRect.top() + qreal(0.5));
+ outerRect = innerRect;
+ }
+ halfPenWidth = penWidth * qreal(0.5);
+ innerRect.adjust(halfPenWidth, halfPenWidth, -halfPenWidth, -halfPenWidth);
+ outerRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
+ }
+
+ int nextGradientStop = 0;
+ qreal gradientPos = halfPenWidth / m_rect.height();
+ while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
+ ++nextGradientStop;
+ int lastGradientStop = stops.size() - 1;
+ qreal lastGradientPos = (m_rect.height() - halfPenWidth) / m_rect.height();
+ while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
+ --lastGradientStop;
+
+ int borderVertexCount = 0;
+ if (penWidth) {
+ borderGeometry->allocate((1 + lastGradientStop - nextGradientStop) * 4 + 10);
+ borderVertices = (Vertex *)borderGeometry->vertexData();
+ }
+ fill->allocate((3 + lastGradientStop - nextGradientStop) * 2);
+ fillVertices = (uchar *)fill->vertexData();
+
+ QVarLengthArray<qreal, 16> ys(3 + lastGradientStop - nextGradientStop);
+ int yCount = 0;
+
+ for (int part = 0; part < 2; ++part) {
+ qreal y = (part ? innerRect.bottom() : innerRect.top());
+ gradientPos = (y - innerRect.top() + halfPenWidth) / m_rect.height();
+
+ while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
+ // Insert vertices at gradient stops.
+ qreal gy = (innerRect.top() - halfPenWidth) + stops.at(nextGradientStop).first * m_rect.height();
+ Q_ASSERT(fillVertexCount >= 2);
+
+ ColorVertex *vertices = (ColorVertex *)fillVertices;
+
+ fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
+ vertices[fillVertexCount].position = QVector2D(innerRect.right(), gy);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ vertices[fillVertexCount].position = QVector2D(innerRect.left(), gy);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+
+ ys[yCount++] = gy;
+
+ ++nextGradientStop;
+ }
+
+ if (stops.isEmpty()) {
+ Q_ASSERT(m_material_type == TypeFlat);
+ Vertex *vertices = (Vertex *)fillVertices;
+ vertices[fillVertexCount++].position = QVector2D(innerRect.right(), y);
+ vertices[fillVertexCount++].position = QVector2D(innerRect.left(), y);
+ } else {
+ if (nextGradientStop == 0) {
+ fillColor = colorToColor4ub(stops.at(0).second);
+ } else if (nextGradientStop == stops.size()) {
+ fillColor = colorToColor4ub(stops.last().second);
+ } else {
+ const QGradientStop &prev = stops.at(nextGradientStop - 1);
+ const QGradientStop &next = stops.at(nextGradientStop);
+ qreal t = (gradientPos - prev.first) / (next.first - prev.first);
+ fillColor = (colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t);
+ }
+
+ ColorVertex *vertices = (ColorVertex *)fillVertices;
+ vertices[fillVertexCount].position = QVector2D(innerRect.right(), y);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ vertices[fillVertexCount].position = QVector2D(innerRect.left(), y);
+ vertices[fillVertexCount].color = fillColor;
+ ++fillVertexCount;
+ }
+
+ ys[yCount++] = y;
+ }
+
+ if (penWidth) {
+ borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.top());
+ borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), ys[0]);
+ for (int i = 1; i < fillVertexCount / 2; ++i) {
+ borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.bottom());
+ borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), ys[i]);
+ }
+
+ borderVertices[borderVertexCount++].position = QVector2D(outerRect.left(), outerRect.bottom());
+ borderVertices[borderVertexCount++].position = QVector2D(innerRect.left(), ys[fillVertexCount / 2 - 1]);
+ for (int i = fillVertexCount / 2 - 2; i >= 0; --i) {
+ borderVertices[borderVertexCount++].position = QVector2D(outerRect.left(), outerRect.top());
+ borderVertices[borderVertexCount++].position = QVector2D(innerRect.left(), ys[i]);
+ }
+
+ borderVertices[borderVertexCount++].position = QVector2D(outerRect.right(), outerRect.top());
+ borderVertices[borderVertexCount++].position = QVector2D(innerRect.right(), innerRect.top());
+
+ Q_ASSERT(borderVertexCount == borderGeometry->vertexCount());
+ }
+ Q_ASSERT(fillVertexCount == fill->vertexCount());
+ }
+
+ markDirty(DirtyGeometry);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h
new file mode 100644
index 0000000000..b491913428
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DEFAULT_RECTANGLENODE_H
+#define DEFAULT_RECTANGLENODE_H
+
+#include <private/qsgadaptationlayer_p.h>
+
+#include <QtQuick/qsgflatcolormaterial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGMaterial;
+class QSGContext;
+
+class QSGDefaultRectangleNode : public QSGRectangleNode
+{
+public:
+ QSGDefaultRectangleNode(QSGContext *context);
+ ~QSGDefaultRectangleNode();
+
+ virtual void setRect(const QRectF &rect);
+ virtual void setColor(const QColor &color);
+ virtual void setPenColor(const QColor &color);
+ virtual void setPenWidth(qreal width);
+ virtual void setGradientStops(const QGradientStops &stops);
+ virtual void setRadius(qreal radius);
+ virtual void setAligned(bool aligned);
+ virtual void update();
+
+private:
+ enum {
+ TypeFlat,
+ TypeVertexGradient
+ };
+ QSGGeometryNode *border();
+
+ void updateGeometry();
+ void updateGradientTexture();
+
+ QSGGeometryNode *m_border;
+ QSGFlatColorMaterial m_border_material;
+ QSGFlatColorMaterial m_fill_material;
+
+ QRectF m_rect;
+ QGradientStops m_gradient_stops;
+ qreal m_radius;
+ qreal m_pen_width;
+
+ uint m_aligned : 1;
+ uint m_gradient_is_opaque : 1;
+ uint m_dirty_geometry : 1;
+
+ uint m_material_type : 2; // Only goes up to 3
+
+ QSGGeometry m_default_geometry;
+
+ QSGContext *m_context;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
new file mode 100644
index 0000000000..d3b90bed60
--- /dev/null
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdistancefieldglyphnode_p.h"
+#include "qsgdistancefieldglyphnode_p_p.h"
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager)
+ : m_material(0)
+ , m_glyph_cacheManager(cacheManager)
+ , m_glyph_cache(0)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
+ , m_style(QQuickText::Normal)
+ , m_antialiasingMode(GrayAntialiasing)
+ , m_dirtyGeometry(false)
+ , m_dirtyMaterial(false)
+{
+ m_geometry.setDrawingMode(GL_TRIANGLES);
+ setGeometry(&m_geometry);
+ setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode());
+#ifdef QML_RUNTIME_TESTING
+ description = QLatin1String("glyphs");
+#endif
+}
+
+QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
+{
+ delete m_material;
+ if (m_glyph_cache) {
+ m_glyph_cache->release(m_glyphs.glyphIndexes());
+ m_glyph_cache->unregisterGlyphNode(this);
+ }
+}
+
+void QSGDistanceFieldGlyphNode::setColor(const QColor &color)
+{
+ m_color = color;
+ if (m_material != 0) {
+ m_material->setColor(color);
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGDistanceFieldGlyphNode::setPreferredAntialiasingMode(AntialiasingMode mode)
+{
+ if (mode == m_antialiasingMode)
+ return;
+ m_antialiasingMode = mode;
+ m_dirtyMaterial = true;
+}
+
+void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
+{
+ QRawFont font = glyphs.rawFont();
+ m_position = QPointF(position.x(), position.y() - font.ascent());
+ m_glyphs = glyphs;
+
+ QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
+ m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
+ if (m_glyph_cache != oldCache) {
+ if (oldCache)
+ oldCache->unregisterGlyphNode(this);
+ m_glyph_cache->registerGlyphNode(this);
+ }
+ m_glyph_cache->populate(glyphs.glyphIndexes());
+
+ const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
+ const QVector<QPointF> &glyphPositions = m_glyphs.positions();
+ for (int i = 0; i < glyphIndexes.size(); ++i) {
+ GlyphInfo g;
+ g.glyphIndex = glyphIndexes.at(i);
+ g.position = glyphPositions.at(i);
+ m_glyphsToAdd.append(g);
+ }
+
+ m_dirtyGeometry = true;
+ m_dirtyMaterial = true;
+}
+
+void QSGDistanceFieldGlyphNode::setStyle(QQuickText::TextStyle style)
+{
+ if (m_style == style)
+ return;
+ m_style = style;
+ m_dirtyMaterial = true;
+}
+
+void QSGDistanceFieldGlyphNode::setStyleColor(const QColor &color)
+{
+ if (m_styleColor == color)
+ return;
+ m_styleColor = color;
+ m_dirtyMaterial = true;
+}
+
+void QSGDistanceFieldGlyphNode::update()
+{
+ if (m_dirtyMaterial)
+ updateMaterial();
+ if (m_dirtyGeometry)
+ updateGeometry();
+}
+
+void QSGDistanceFieldGlyphNode::updateGeometry()
+{
+ Q_ASSERT(m_glyph_cache);
+
+ if (m_glyphsToAdd.isEmpty())
+ return;
+
+ QSGGeometry *g = geometry();
+
+ Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT);
+
+ int oldVertexCount = g->vertexCount();
+ int oldIndexCount = g->indexCount();
+
+ QVector<QSGGeometry::TexturedPoint2D> vp;
+ vp.reserve(m_glyphsToAdd.size() * 4);
+ QVector<ushort> ip;
+ ip.reserve(m_glyphsToAdd.size() * 6);
+
+ QPointF margins(2, 2);
+ QPointF texMargins = margins / m_glyph_cache->fontScale();
+
+ const QSGDistanceFieldGlyphCache::Texture *textureToUse = 0;
+
+ QLinkedList<GlyphInfo>::iterator it = m_glyphsToAdd.begin();
+ while (it != m_glyphsToAdd.end()) {
+ quint32 glyphIndex = it->glyphIndex;
+ QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
+
+ if (c.isNull()) {
+ if (!c.isValid())
+ ++it;
+ else
+ it = m_glyphsToAdd.erase(it);
+ continue;
+ }
+
+ const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
+ if (!texture->textureId) {
+ ++it;
+ continue;
+ }
+
+ QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
+
+ if (!textureToUse)
+ textureToUse = texture;
+
+ metrics.width += margins.x() * 2;
+ metrics.height += margins.y() * 2;
+ metrics.baselineX -= margins.x();
+ metrics.baselineY += margins.y();
+ c.xMargin -= texMargins.x();
+ c.yMargin -= texMargins.y();
+ c.width += texMargins.x() * 2;
+ c.height += texMargins.y() * 2;
+
+ const QPointF &glyphPosition = it->position;
+ qreal x = glyphPosition.x() + metrics.baselineX + m_position.x();
+ qreal y = glyphPosition.y() - metrics.baselineY + m_position.y();
+
+ m_boundingRect |= QRectF(x, y, metrics.width, metrics.height);
+
+ float cx1 = x;
+ float cx2 = x + metrics.width;
+ float cy1 = y;
+ float cy2 = y + metrics.height;
+
+ float tx1 = c.x + c.xMargin;
+ float tx2 = tx1 + c.width;
+ float ty1 = c.y + c.yMargin;
+ float ty2 = ty1 + c.height;
+
+ if (m_baseLine.isNull())
+ m_baseLine = glyphPosition;
+
+ int i = vp.size();
+
+ QSGGeometry::TexturedPoint2D v1;
+ v1.set(cx1, cy1, tx1, ty1);
+ QSGGeometry::TexturedPoint2D v2;
+ v2.set(cx2, cy1, tx2, ty1);
+ QSGGeometry::TexturedPoint2D v3;
+ v3.set(cx1, cy2, tx1, ty2);
+ QSGGeometry::TexturedPoint2D v4;
+ v4.set(cx2, cy2, tx2, ty2);
+ vp.append(v1);
+ vp.append(v2);
+ vp.append(v3);
+ vp.append(v4);
+
+ int o = i + oldVertexCount;
+ ip.append(o + 0);
+ ip.append(o + 2);
+ ip.append(o + 3);
+ ip.append(o + 3);
+ ip.append(o + 1);
+ ip.append(o + 0);
+
+ it = m_glyphsToAdd.erase(it);
+ }
+
+ if (vp.isEmpty())
+ return;
+
+ void *data = 0;
+ if (oldVertexCount && oldIndexCount) {
+ int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)
+ + oldIndexCount * sizeof(quint16);
+ data = qMalloc(byteSize);
+ memcpy(data, g->vertexData(), byteSize);
+ }
+
+ g->allocate(oldVertexCount + vp.size(), oldIndexCount + ip.size());
+
+ if (data) {
+ memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D));
+ memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D),
+ oldIndexCount * sizeof(quint16));
+ qFree(data);
+ }
+
+ memcpy(g->vertexDataAsTexturedPoint2D() + oldVertexCount, vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
+ memcpy(g->indexDataAsUShort() + oldIndexCount, ip.constData(), ip.size() * sizeof(quint16));
+
+ setBoundingRect(m_boundingRect);
+ markDirty(DirtyGeometry);
+ m_dirtyGeometry = false;
+
+ m_material->setTexture(textureToUse);
+}
+
+void QSGDistanceFieldGlyphNode::updateMaterial()
+{
+ delete m_material;
+
+ if (m_style == QQuickText::Normal) {
+ switch (m_antialiasingMode) {
+ case HighQualitySubPixelAntialiasing:
+ m_material = new QSGHiQSubPixelDistanceFieldTextMaterial;
+ break;
+ case LowQualitySubPixelAntialiasing:
+ m_material = new QSGLoQSubPixelDistanceFieldTextMaterial;
+ break;
+ case GrayAntialiasing:
+ default:
+ m_material = new QSGDistanceFieldTextMaterial;
+ break;
+ }
+ } else {
+ QSGDistanceFieldStyledTextMaterial *material;
+ if (m_style == QQuickText::Outline) {
+ material = new QSGDistanceFieldOutlineTextMaterial;
+ } else {
+ QSGDistanceFieldShiftedStyleTextMaterial *sMaterial = new QSGDistanceFieldShiftedStyleTextMaterial;
+ if (m_style == QQuickText::Raised)
+ sMaterial->setShift(QPointF(0.0, 1.0));
+ else
+ sMaterial->setShift(QPointF(0.0, -1.0));
+ material = sMaterial;
+ }
+ material->setStyleColor(m_styleColor);
+ m_material = material;
+ }
+
+ m_material->setGlyphCache(m_glyph_cache);
+ m_material->setColor(m_color);
+ setMaterial(m_material);
+ m_dirtyMaterial = false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
new file mode 100644
index 0000000000..3852b01518
--- /dev/null
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -0,0 +1,725 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdistancefieldglyphnode_p_p.h"
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
+#include <QtGui/qopenglfunctions.h>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGDistanceFieldTextMaterialShader : public QSGMaterialShader
+{
+public:
+ QSGDistanceFieldTextMaterialShader();
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+protected:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
+
+ float m_fontScale;
+ float m_matrixScale;
+
+ int m_matrix_id;
+ int m_textureScale_id;
+ int m_alphaMin_id;
+ int m_alphaMax_id;
+ int m_color_id;
+};
+
+const char *QSGDistanceFieldTextMaterialShader::vertexShader() const {
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *QSGDistanceFieldTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "void main() { \n"
+ " gl_FragColor = color * smoothstep(alphaMin, \n"
+ " alphaMax, \n"
+ " texture2D(texture, sampleCoord).a); \n"
+ "}";
+}
+
+char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const {
+ static char const *const attr[] = { "vCoord", "tCoord", 0 };
+ return attr;
+}
+
+QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
+ : m_fontScale(1.0)
+ , m_matrixScale(1.0)
+{
+}
+
+void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
+{
+ float combinedScale = m_fontScale * m_matrixScale;
+ float base = thresholdFunc(combinedScale);
+ float range = spreadFunc(combinedScale);
+
+ float alphaMin = qMax(0.0f, base - range);
+ float alphaMax = qMin(base + range, 1.0f);
+ program()->setUniformValue(m_alphaMin_id, GLfloat(alphaMin));
+ program()->setUniformValue(m_alphaMax_id, GLfloat(alphaMax));
+}
+
+void QSGDistanceFieldTextMaterialShader::initialize()
+{
+ QSGMaterialShader::initialize();
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_textureScale_id = program()->uniformLocation("textureScale");
+ m_color_id = program()->uniformLocation("color");
+ m_alphaMin_id = program()->uniformLocation("alphaMin");
+ m_alphaMax_id = program()->uniformLocation("alphaMax");
+}
+
+void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
+ QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
+
+ bool updated = material->updateCache();
+
+ if (oldMaterial == 0
+ || material->color() != oldMaterial->color()
+ || state.isOpacityDirty()) {
+ QVector4D color(material->color().redF(), material->color().greenF(),
+ material->color().blueF(), material->color().alphaF());
+ color *= state.opacity();
+ program()->setUniformValue(m_color_id, color);
+ }
+
+ bool updateRange = false;
+ if (oldMaterial == 0
+ || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()) {
+ m_fontScale = material->glyphCache()->fontScale();
+ updateRange = true;
+ }
+ if (state.isMatrixDirty()) {
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ m_matrixScale = qSqrt(qAbs(state.modelViewMatrix().determinant()));
+ updateRange = true;
+ }
+ if (updateRange) {
+ updateAlphaRange(material->glyphCache()->manager()->thresholdFunc(),
+ material->glyphCache()->manager()->antialiasingSpreadFunc());
+ }
+
+ Q_ASSERT(material->glyphCache());
+
+ if (updated
+ || oldMaterial == 0
+ || oldMaterial->texture()->textureId != material->texture()->textureId) {
+ program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->textureSize().width(),
+ 1.0 / material->textureSize().height()));
+ glBindTexture(GL_TEXTURE_2D, material->texture()->textureId);
+
+ if (updated) {
+ // Set the mag/min filters to be linear. We only need to do this when the texture
+ // has been recreated.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
+}
+
+QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
+ : m_glyph_cache(0)
+ , m_texture(0)
+{
+ setFlag(Blending, true);
+}
+
+QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial()
+{
+}
+
+QSGMaterialType *QSGDistanceFieldTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
+{
+ return new QSGDistanceFieldTextMaterialShader;
+}
+
+bool QSGDistanceFieldTextMaterial::updateCache()
+{
+ m_glyph_cache->update();
+ if (!m_texture)
+ m_texture = m_glyph_cache->glyphTexture(-1); // invalid texture
+ QSize glyphCacheSize = m_texture->size;
+ if (glyphCacheSize != m_size) {
+ m_size = glyphCacheSize;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const
+{
+ Q_ASSERT(o && type() == o->type());
+ 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);
+ }
+ QRgb c1 = m_color.rgba();
+ QRgb c2 = other->m_color.rgba();
+ return int(c2 < c1) - int(c1 < c2);
+}
+
+
+class DistanceFieldStyledTextMaterialShader : public QSGDistanceFieldTextMaterialShader
+{
+public:
+ DistanceFieldStyledTextMaterialShader();
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+
+protected:
+ virtual void initialize();
+ virtual const char *fragmentShader() const = 0;
+
+ int m_styleColor_id;
+};
+
+DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
+ : QSGDistanceFieldTextMaterialShader()
+{
+}
+
+void DistanceFieldStyledTextMaterialShader::initialize()
+{
+ QSGDistanceFieldTextMaterialShader::initialize();
+ m_styleColor_id = program()->uniformLocation("styleColor");
+}
+
+void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
+
+ QSGDistanceFieldStyledTextMaterial *material = static_cast<QSGDistanceFieldStyledTextMaterial *>(newEffect);
+ QSGDistanceFieldStyledTextMaterial *oldMaterial = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldEffect);
+
+ if (oldMaterial == 0
+ || material->styleColor() != oldMaterial->styleColor()
+ || (state.isOpacityDirty())) {
+ QVector4D color(material->styleColor().redF(), material->styleColor().greenF(),
+ material->styleColor().blueF(), material->styleColor().alphaF());
+ color *= state.opacity();
+ program()->setUniformValue(m_styleColor_id, color);
+ }
+}
+
+QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial()
+ : QSGDistanceFieldTextMaterial()
+{
+}
+
+QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial()
+{
+}
+
+int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const
+{
+ Q_ASSERT(o && type() == o->type());
+ const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o);
+ if (m_styleColor != other->m_styleColor) {
+ QRgb c1 = m_styleColor.rgba();
+ QRgb c2 = other->m_styleColor.rgba();
+ return int(c2 < c1) - int(c1 < c2);
+ }
+ return QSGDistanceFieldTextMaterial::compare(o);
+}
+
+
+class DistanceFieldOutlineTextMaterialShader : public DistanceFieldStyledTextMaterialShader
+{
+public:
+ DistanceFieldOutlineTextMaterialShader();
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+
+protected:
+ virtual void initialize();
+ virtual const char *fragmentShader() const;
+
+ void updateOutlineAlphaRange(int dfRadius);
+
+ int m_outlineAlphaMax0_id;
+ int m_outlineAlphaMax1_id;
+};
+
+const char *DistanceFieldOutlineTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform lowp vec4 styleColor; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "uniform highp float outlineAlphaMax0; \n"
+ "uniform highp float outlineAlphaMax1; \n"
+ "void main() { \n"
+ " mediump float d = texture2D(texture, sampleCoord).a; \n"
+ " gl_FragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d)) \n"
+ " * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d); \n"
+ "}";
+}
+
+DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
+ : DistanceFieldStyledTextMaterialShader()
+{
+}
+
+void DistanceFieldOutlineTextMaterialShader::initialize()
+{
+ DistanceFieldStyledTextMaterialShader::initialize();
+ m_outlineAlphaMax0_id = program()->uniformLocation("outlineAlphaMax0");
+ m_outlineAlphaMax1_id = program()->uniformLocation("outlineAlphaMax1");
+}
+
+void DistanceFieldOutlineTextMaterialShader::updateOutlineAlphaRange(int dfRadius)
+{
+ qreal outlineLimit = qMax(qreal(0.2), qreal(0.5 - 0.5 / dfRadius / m_fontScale));
+
+ qreal combinedScale = m_fontScale * m_matrixScale;
+ qreal alphaMin = qMax(0.0, 0.5 - 0.07 / combinedScale);
+ qreal styleAlphaMin0 = qMax(0.0, outlineLimit - 0.07 / combinedScale);
+ qreal styleAlphaMin1 = qMin(qreal(outlineLimit + 0.07 / combinedScale), alphaMin);
+ program()->setUniformValue(m_outlineAlphaMax0_id, GLfloat(styleAlphaMin0));
+ program()->setUniformValue(m_outlineAlphaMax1_id, GLfloat(styleAlphaMin1));
+}
+
+void DistanceFieldOutlineTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
+
+ QSGDistanceFieldOutlineTextMaterial *material = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newEffect);
+ QSGDistanceFieldOutlineTextMaterial *oldMaterial = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldEffect);
+
+ if (oldMaterial == 0
+ || material->glyphCache()->fontScale() != oldMaterial->glyphCache()->fontScale()
+ || state.isMatrixDirty())
+ updateOutlineAlphaRange(material->glyphCache()->distanceFieldRadius());
+}
+
+
+QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial()
+ : QSGDistanceFieldStyledTextMaterial()
+{
+}
+
+QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial()
+{
+}
+
+QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader() const
+{
+ return new DistanceFieldOutlineTextMaterialShader;
+}
+
+
+class DistanceFieldShiftedStyleTextMaterialShader : public DistanceFieldStyledTextMaterialShader
+{
+public:
+ DistanceFieldShiftedStyleTextMaterialShader();
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+
+protected:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ void updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF& shift);
+
+ int m_shift_id;
+};
+
+DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
+ : DistanceFieldStyledTextMaterialShader()
+{
+}
+
+void DistanceFieldShiftedStyleTextMaterialShader::initialize()
+{
+ DistanceFieldStyledTextMaterialShader::initialize();
+ m_shift_id = program()->uniformLocation("shift");
+}
+
+void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ DistanceFieldStyledTextMaterialShader::updateState(state, newEffect, oldEffect);
+
+ QSGDistanceFieldShiftedStyleTextMaterial *material = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newEffect);
+ QSGDistanceFieldShiftedStyleTextMaterial *oldMaterial = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldEffect);
+
+ if (oldMaterial == 0
+ || oldMaterial->glyphCache()->fontScale() != material->glyphCache()->fontScale()
+ || oldMaterial->shift() != material->shift()
+ || oldMaterial->textureSize() != material->textureSize()) {
+ updateShift(material->glyphCache(), material->shift());
+ }
+}
+
+void DistanceFieldShiftedStyleTextMaterialShader::updateShift(const QSGDistanceFieldGlyphCache *cache, const QPointF &shift)
+{
+ QPointF texel(1.0 / cache->fontScale() * shift.x(),
+ 1.0 / cache->fontScale() * shift.y());
+ program()->setUniformValue(m_shift_id, texel);
+}
+
+const char *DistanceFieldShiftedStyleTextMaterialShader::vertexShader() const
+{
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "uniform highp vec2 shift; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 shiftedSampleCoord; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *DistanceFieldShiftedStyleTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 shiftedSampleCoord; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform lowp vec4 styleColor; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "void main() { \n"
+ " highp float a = smoothstep(alphaMin, alphaMax, texture2D(texture, sampleCoord).a);\n"
+ " highp vec4 shifted = styleColor * smoothstep(alphaMin, \n"
+ " alphaMax, \n"
+ " texture2D(texture, shiftedSampleCoord).a); \n"
+ " gl_FragColor = mix(shifted, color, a); \n"
+ "}";
+}
+
+QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
+ : QSGDistanceFieldStyledTextMaterial()
+{
+}
+
+QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial()
+{
+}
+
+QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() const
+{
+ return new DistanceFieldShiftedStyleTextMaterialShader;
+}
+
+
+class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
+{
+public:
+ virtual void initialize();
+ virtual void activate();
+ virtual void deactivate();
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+
+protected:
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+private:
+ int m_fontScale_id;
+ int m_vecDelta_id;
+};
+
+const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "uniform highp float fontScale; \n"
+ "uniform highp vec4 vecDelta; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec3 sampleFarLeft; \n"
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "varying highp vec3 sampleFarRight; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ // Calculate neighbour pixel position in item space.
+ " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
+ " highp vec3 farLeft = vCoord.xyw - 0.667 * wDelta; \n"
+ " highp vec3 nearLeft = vCoord.xyw - 0.333 * wDelta; \n"
+ " highp vec3 nearRight = vCoord.xyw + 0.333 * wDelta; \n"
+ " highp vec3 farRight = vCoord.xyw + 0.667 * wDelta; \n"
+ // Calculate neighbour texture coordinate.
+ " highp vec2 scale = textureScale / fontScale; \n"
+ " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
+ " sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z); \n"
+ " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
+ " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
+ " sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z); \n"
+ "}";
+}
+
+const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec3 sampleFarLeft; \n"
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "varying highp vec3 sampleFarRight; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "void main() { \n"
+ " highp vec4 n; \n"
+ " n.x = texture2DProj(texture, sampleFarLeft).a; \n"
+ " n.y = texture2DProj(texture, sampleNearLeft).a; \n"
+ " highp float c = texture2D(texture, sampleCoord).a; \n"
+ " n.z = texture2DProj(texture, sampleNearRight).a; \n"
+ " n.w = texture2DProj(texture, sampleFarRight).a; \n"
+#if 0
+ // Blurrier, faster.
+ " n = smoothstep(alphaMin, alphaMax, n); \n"
+ " c = smoothstep(alphaMin, alphaMax, c); \n"
+#else
+ // Sharper, slower.
+ " highp vec2 d = min(abs(n.yw - n.xz) * 2., 0.67); \n"
+ " highp vec2 lo = mix(vec2(alphaMin), vec2(0.5), d); \n"
+ " highp vec2 hi = mix(vec2(alphaMax), vec2(0.5), d); \n"
+ " n = smoothstep(lo.xxyy, hi.xxyy, n); \n"
+ " c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c); \n"
+#endif
+ " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
+ "}";
+}
+
+//const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+// return
+// "#extension GL_OES_standard_derivatives: enable \n"
+// "varying highp vec2 sampleCoord; \n"
+// "uniform sampler2D texture; \n"
+// "uniform lowp vec4 color; \n"
+// "uniform highp float alphaMin; \n"
+// "uniform highp float alphaMax; \n"
+// "void main() { \n"
+// " highp vec2 delta = dFdx(sampleCoord); \n"
+// " highp vec4 n; \n"
+// " n.x = texture2D(texture, sampleCoord - 0.667 * delta).a; \n"
+// " n.y = texture2D(texture, sampleCoord - 0.333 * delta).a; \n"
+// " highp float c = texture2D(texture, sampleCoord).a; \n"
+// " n.z = texture2D(texture, sampleCoord + 0.333 * delta).a; \n"
+// " n.w = texture2D(texture, sampleCoord + 0.667 * delta).a; \n"
+// " n = smoothstep(alphaMin, alphaMax, n); \n"
+// " c = smoothstep(alphaMin, alphaMax, c); \n"
+// " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
+// "}";
+//}
+
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
+{
+ QSGDistanceFieldTextMaterialShader::initialize();
+ m_fontScale_id = program()->uniformLocation("fontScale");
+ m_vecDelta_id = program()->uniformLocation("vecDelta");
+}
+
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::activate()
+{
+ QSGDistanceFieldTextMaterialShader::activate();
+ glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
+}
+
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::deactivate()
+{
+ QSGDistanceFieldTextMaterialShader::deactivate();
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
+ QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
+
+ if (oldMaterial == 0 || material->color() != oldMaterial->color()) {
+ QColor c = material->color();
+ 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 || state.isMatrixDirty()) {
+ int viewportWidth = state.viewportRect().width();
+ QMatrix4x4 mat = state.combinedMatrix().inverted();
+ program()->setUniformValue(m_vecDelta_id, mat.column(0) * (qreal(2) / viewportWidth));
+ }
+
+ QSGDistanceFieldTextMaterialShader::updateState(state, newEffect, oldEffect);
+}
+
+QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
+{
+ return new QSGHiQSubPixelDistanceFieldTextMaterialShader;
+}
+
+
+class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
+{
+protected:
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+};
+
+const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "uniform highp float fontScale; \n"
+ "uniform highp vec4 vecDelta; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "void main() { \n"
+ " highp vec2 sampleCoord = tCoord * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ // Calculate neighbour pixel position in item space.
+ " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
+ " highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta; \n"
+ " highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta; \n"
+ // Calculate neighbour texture coordinate.
+ " highp vec2 scale = textureScale / fontScale; \n"
+ " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
+ " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
+ " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
+ "}";
+}
+
+const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
+ return
+ "varying highp vec3 sampleNearLeft; \n"
+ "varying highp vec3 sampleNearRight; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform highp float alphaMin; \n"
+ "uniform highp float alphaMax; \n"
+ "void main() { \n"
+ " highp vec2 n; \n"
+ " n.x = texture2DProj(texture, sampleNearLeft).a; \n"
+ " n.y = texture2DProj(texture, sampleNearRight).a; \n"
+ " n = smoothstep(alphaMin, alphaMax, n); \n"
+ " highp float c = 0.5 * (n.x + n.y); \n"
+ " gl_FragColor = vec4(n.x, c, n.y, c) * color.w; \n"
+ "}";
+}
+
+QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader() const
+{
+ return new QSGLoQSubPixelDistanceFieldTextMaterialShader;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
new file mode 100644
index 0000000000..8096d4ae70
--- /dev/null
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DISTANCEFIELD_GLYPHNODE_H
+#define DISTANCEFIELD_GLYPHNODE_H
+
+#include <private/qsgadaptationlayer_p.h>
+#include <QtQuick/qsgtexture.h>
+
+#include <QtQuick/private/qquicktext_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGDistanceFieldGlyphCacheManager;
+class QSGDistanceFieldTextMaterial;
+class QSGDistanceFieldGlyphNode: public QSGGlyphNode
+{
+public:
+ QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheManager *cacheManager);
+ ~QSGDistanceFieldGlyphNode();
+
+ virtual QPointF baseLine() const { return m_baseLine; }
+ virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs);
+ virtual void setColor(const QColor &color);
+
+ virtual void setPreferredAntialiasingMode(AntialiasingMode mode);
+
+ virtual void setStyle(QQuickText::TextStyle style);
+ virtual void setStyleColor(const QColor &color);
+
+ virtual void update();
+
+ void updateGeometry();
+
+private:
+ void updateMaterial();
+
+ QColor m_color;
+ QPointF m_baseLine;
+ QSGDistanceFieldTextMaterial *m_material;
+ QPointF m_position;
+ QGlyphRun m_glyphs;
+ QSGDistanceFieldGlyphCacheManager *m_glyph_cacheManager;
+ QSGDistanceFieldGlyphCache *m_glyph_cache;
+ QSGGeometry m_geometry;
+ QQuickText::TextStyle m_style;
+ QColor m_styleColor;
+ AntialiasingMode m_antialiasingMode;
+ QRectF m_boundingRect;
+
+ struct GlyphInfo {
+ quint32 glyphIndex;
+ QPointF position;
+ };
+ QLinkedList<GlyphInfo> m_glyphsToAdd;
+
+ uint m_dirtyGeometry: 1;
+ uint m_dirtyMaterial: 1;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // DISTANCEFIELD_GLYPHNODE_H
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
new file mode 100644
index 0000000000..dbdc6e2498
--- /dev/null
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 DISTANCEFIELDTEXTMATERIAL_H
+#define DISTANCEFIELDTEXTMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+#include "qsgdistancefieldglyphnode_p.h"
+#include "qsgadaptationlayer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSGDistanceFieldTextMaterial: public QSGMaterial
+{
+public:
+ QSGDistanceFieldTextMaterial();
+ ~QSGDistanceFieldTextMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setColor(const QColor &color) { m_color = color; }
+ const QColor &color() const { return m_color; }
+
+ void setGlyphCache(QSGDistanceFieldGlyphCache *a) { m_glyph_cache = a; }
+ QSGDistanceFieldGlyphCache *glyphCache() const { return m_glyph_cache; }
+
+ void setTexture(const QSGDistanceFieldGlyphCache::Texture * tex) { m_texture = tex; }
+ const QSGDistanceFieldGlyphCache::Texture * texture() const { return m_texture; }
+
+ QSize textureSize() const { return m_size; }
+
+ bool updateCache();
+
+protected:
+ QSize m_size;
+ QColor m_color;
+ QSGDistanceFieldGlyphCache *m_glyph_cache;
+ const QSGDistanceFieldGlyphCache::Texture *m_texture;
+};
+
+class QSGDistanceFieldStyledTextMaterial : public QSGDistanceFieldTextMaterial
+{
+public:
+ QSGDistanceFieldStyledTextMaterial();
+ ~QSGDistanceFieldStyledTextMaterial();
+
+ virtual QSGMaterialType *type() const = 0;
+ virtual QSGMaterialShader *createShader() const = 0;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setStyleColor(const QColor &color) { m_styleColor = color; }
+ const QColor &styleColor() const { return m_styleColor; }
+
+protected:
+ QColor m_styleColor;
+};
+
+class QSGDistanceFieldOutlineTextMaterial : public QSGDistanceFieldStyledTextMaterial
+{
+public:
+ QSGDistanceFieldOutlineTextMaterial();
+ ~QSGDistanceFieldOutlineTextMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+class QSGDistanceFieldShiftedStyleTextMaterial : public QSGDistanceFieldStyledTextMaterial
+{
+public:
+ QSGDistanceFieldShiftedStyleTextMaterial();
+ ~QSGDistanceFieldShiftedStyleTextMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+
+ void setShift(const QPointF &shift) { m_shift = shift; }
+ const QPointF &shift() const { return m_shift; }
+
+protected:
+ QPointF m_shift;
+};
+
+class QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+{
+public:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+class QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial
+{
+public:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // DISTANCEFIELDTEXTMATERIAL_H
diff --git a/src/declarative/scenegraph/qsgflashnode.cpp b/src/quick/scenegraph/qsgflashnode.cpp
index 9546e91ee1..9546e91ee1 100644
--- a/src/declarative/scenegraph/qsgflashnode.cpp
+++ b/src/quick/scenegraph/qsgflashnode.cpp
diff --git a/src/quick/scenegraph/qsgflashnode_p.h b/src/quick/scenegraph/qsgflashnode_p.h
new file mode 100644
index 0000000000..71ac22d648
--- /dev/null
+++ b/src/quick/scenegraph/qsgflashnode_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGFLASHNODE_H
+#define QSGFLASHNODE_H
+
+#include <QtQuick/QSGSimpleRectNode>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGFlashNode : public QSGSimpleRectNode
+{
+public:
+ QSGFlashNode();
+
+ void preprocess();
+
+private:
+ int m_counter;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGFLASHNODE_H
+
diff --git a/src/declarative/scenegraph/qsgpathsimplifier.cpp b/src/quick/scenegraph/qsgpathsimplifier.cpp
index 9e851bf434..9e851bf434 100644
--- a/src/declarative/scenegraph/qsgpathsimplifier.cpp
+++ b/src/quick/scenegraph/qsgpathsimplifier.cpp
diff --git a/src/declarative/scenegraph/qsgpathsimplifier_p.h b/src/quick/scenegraph/qsgpathsimplifier_p.h
index 0639c4f622..0639c4f622 100644
--- a/src/declarative/scenegraph/qsgpathsimplifier_p.h
+++ b/src/quick/scenegraph/qsgpathsimplifier_p.h
diff --git a/src/declarative/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 0adc20502d..0adc20502d 100644
--- a/src/declarative/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
diff --git a/src/declarative/scenegraph/util/qsgareaallocator.cpp b/src/quick/scenegraph/util/qsgareaallocator.cpp
index c5171f1c93..c5171f1c93 100644
--- a/src/declarative/scenegraph/util/qsgareaallocator.cpp
+++ b/src/quick/scenegraph/util/qsgareaallocator.cpp
diff --git a/src/quick/scenegraph/util/qsgareaallocator_p.h b/src/quick/scenegraph/util/qsgareaallocator_p.h
new file mode 100644
index 0000000000..be26046865
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgareaallocator_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 AREAALLOCATOR_H
+#define AREAALLOCATOR_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRect;
+class QPoint;
+struct QSGAreaAllocatorNode;
+class Q_QUICK_EXPORT QSGAreaAllocator
+{
+public:
+ QSGAreaAllocator(const QSize &size);
+ ~QSGAreaAllocator();
+
+ QRect allocate(const QSize &size);
+ bool deallocate(const QRect &rect);
+ bool isEmpty() const { return m_root == 0; }
+ QSize size() const { return m_size; }
+private:
+ bool allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, QSGAreaAllocatorNode *node);
+ bool deallocateInNode(const QPoint &pos, QSGAreaAllocatorNode *node);
+ void mergeNodeWithNeighbors(QSGAreaAllocatorNode *node);
+
+ QSGAreaAllocatorNode *m_root;
+ QSize m_size;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
new file mode 100644
index 0000000000..d1b0445ee0
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
@@ -0,0 +1,805 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgdistancefieldutil_p.h"
+
+#include <qmath.h>
+#include <private/qsgpathsimplifier_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <QtGui/private/qopenglengineshadersource_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static float defaultThresholdFunc(float glyphScale)
+{
+ static float base = qgetenv("QT_DF_BASE").isEmpty() ? 0.5f : qgetenv("QT_DF_BASE").toFloat();
+ static float baseDev = qgetenv("QT_DF_BASEDEVIATION").isEmpty() ? 0.065f : qgetenv("QT_DF_BASEDEVIATION").toFloat();
+ static float devScaleMin = qgetenv("QT_DF_SCALEFORMAXDEV").isEmpty() ? 0.15f : qgetenv("QT_DF_SCALEFORMAXDEV").toFloat();
+ static float devScaleMax = qgetenv("QT_DF_SCALEFORNODEV").isEmpty() ? 0.3f : qgetenv("QT_DF_SCALEFORNODEV").toFloat();
+ return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+static float defaultAntialiasingSpreadFunc(float glyphScale)
+{
+ static float range = qgetenv("QT_DF_RANGE").isEmpty() ? 0.06f : qgetenv("QT_DF_RANGE").toFloat();
+ return range / glyphScale;
+}
+
+namespace
+{
+ enum FillHDir
+ {
+ LeftToRight,
+ RightToLeft
+ };
+
+ enum FillVDir
+ {
+ TopDown,
+ BottomUp
+ };
+
+ enum FillClip
+ {
+ NoClip,
+ Clip
+ };
+}
+
+template <FillClip clip, FillHDir dir>
+inline void fillLine(qint32 *, int, int, int, qint32, qint32)
+{
+}
+
+template <>
+inline void fillLine<Clip, LeftToRight>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = qMax(0, lx >> 8);
+ int toX = qMin(width, rx >> 8);
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + (((fromX << 8) + 0xff - lx) * dd >> 8);
+ line += fromX;
+ do {
+ *line = abs(val) < abs(*line) ? val : *line;
+ val += dd;
+ ++line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<Clip, RightToLeft>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = qMax(0, lx >> 8);
+ int toX = qMin(width, rx >> 8);
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + (((toX << 8) + 0xff - rx) * dd >> 8);
+ line += toX;
+ do {
+ val -= dd;
+ --line;
+ *line = abs(val) < abs(*line) ? val : *line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<NoClip, LeftToRight>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = lx >> 8;
+ int toX = rx >> 8;
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + ((~lx & 0xff) * dd >> 8);
+ line += fromX;
+ do {
+ *line = abs(val) < abs(*line) ? val : *line;
+ val += dd;
+ ++line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<NoClip, RightToLeft>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = lx >> 8;
+ int toX = rx >> 8;
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + ((~rx & 0xff) * dd >> 8);
+ line += toX;
+ do {
+ val -= dd;
+ --line;
+ *line = abs(val) < abs(*line) ? val : *line;
+ } while (--x);
+}
+
+template <FillClip clip, FillVDir vDir, FillHDir hDir>
+inline void fillLines(qint32 *bits, int width, int height, int upperY, int lowerY,
+ int &lx, int ldx, int &rx, int rdx, qint32 &d, qint32 ddy, qint32 ddx)
+{
+ Q_UNUSED(height);
+ Q_ASSERT(upperY < lowerY);
+ int y = lowerY - upperY;
+ if (vDir == TopDown) {
+ qint32 *line = bits + upperY * width;
+ do {
+ fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
+ lx += ldx;
+ d += ddy;
+ rx += rdx;
+ line += width;
+ } while (--y);
+ } else {
+ qint32 *line = bits + lowerY * width;
+ do {
+ lx -= ldx;
+ d -= ddy;
+ rx -= rdx;
+ line -= width;
+ fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
+ } while (--y);
+ }
+}
+
+template <FillClip clip>
+void drawTriangle(qint32 *bits, int width, int height, const QPoint *center,
+ const QPoint *v1, const QPoint *v2, qint32 value)
+{
+ const int y1 = clip == Clip ? qBound(0, v1->y() >> 8, height) : v1->y() >> 8;
+ const int y2 = clip == Clip ? qBound(0, v2->y() >> 8, height) : v2->y() >> 8;
+ const int yC = clip == Clip ? qBound(0, center->y() >> 8, height) : center->y() >> 8;
+
+ const int v1Frac = clip == Clip ? (y1 << 8) + 0xff - v1->y() : ~v2->y() & 0xff;
+ const int v2Frac = clip == Clip ? (y2 << 8) + 0xff - v2->y() : ~v1->y() & 0xff;
+ const int centerFrac = clip == Clip ? (yC << 8) + 0xff - center->y() : ~center->y() & 0xff;
+
+ int dx1 = 0, x1 = 0, dx2 = 0, x2 = 0;
+ qint32 dd1, d1, dd2, d2;
+ if (v1->y() != center->y()) {
+ dx1 = ((v1->x() - center->x()) << 8) / (v1->y() - center->y());
+ x1 = center->x() + centerFrac * (v1->x() - center->x()) / (v1->y() - center->y());
+ }
+ if (v2->y() != center->y()) {
+ dx2 = ((v2->x() - center->x()) << 8) / (v2->y() - center->y());
+ x2 = center->x() + centerFrac * (v2->x() - center->x()) / (v2->y() - center->y());
+ }
+
+ const qint32 div = (v2->x() - center->x()) * (v1->y() - center->y())
+ - (v2->y() - center->y()) * (v1->x() - center->x());
+ const qint32 dd = div ? qint32((qint64(value * (v1->y() - v2->y())) << 8) / div) : 0;
+
+ if (y2 < yC) {
+ if (y1 < yC) {
+ // Center at the bottom.
+ if (y2 < y1) {
+ // y2 < y1 < yC
+ // Long right edge.
+ d1 = centerFrac * value / (v1->y() - center->y());
+ dd1 = ((value << 8) / (v1->y() - center->y()));
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y1, yC, x1, dx1,
+ x2, dx2, d1, dd1, dd);
+ dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, y1, x1, dx1,
+ x2, dx2, value, 0, dd);
+ } else {
+ // y1 <= y2 < yC
+ // Long left edge.
+ d2 = centerFrac * value / (v2->y() - center->y());
+ dd2 = ((value << 8) / (v2->y() - center->y()));
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y2, yC, x1, dx1,
+ x2, dx2, d2, dd2, dd);
+ if (y1 != y2) {
+ dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, y2, x1, dx1,
+ x2, dx2, value, 0, dd);
+ }
+ }
+ } else {
+ // y2 < yC <= y1
+ // Center to the right.
+ int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ int xUp, xDn;
+ xUp = xDn = v2->x() + (clip == Clip ? (yC << 8) + 0xff - v2->y()
+ : (center->y() | 0xff) - v2->y())
+ * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, yC, xUp, dx,
+ x2, dx2, value, 0, dd);
+ if (yC != y1)
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y1, xDn, dx,
+ x1, dx1, value, 0, dd);
+ }
+ } else {
+ if (y1 < yC) {
+ // y1 < yC <= y2
+ // Center to the left.
+ int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ int xUp, xDn;
+ xUp = xDn = v1->x() + (clip == Clip ? (yC << 8) + 0xff - v1->y()
+ : (center->y() | 0xff) - v1->y())
+ * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, yC, x1, dx1,
+ xUp, dx, value, 0, dd);
+ if (yC != y2)
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y2, x2, dx2,
+ xDn, dx, value, 0, dd);
+ } else {
+ // Center at the top.
+ if (y2 < y1) {
+ // yC <= y2 < y1
+ // Long right edge.
+ if (yC != y2) {
+ d2 = centerFrac * value / (v2->y() - center->y());
+ dd2 = ((value << 8) / (v2->y() - center->y()));
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y2, x2, dx2,
+ x1, dx1, d2, dd2, dd);
+ }
+ dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, y2, y1, x2, dx2,
+ x1, dx1, value, 0, dd);
+ } else {
+ // Long left edge.
+ // yC <= y1 <= y2
+ if (yC != y1) {
+ d1 = centerFrac * value / (v1->y() - center->y());
+ dd1 = ((value << 8) / (v1->y() - center->y()));
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y1, x2, dx2,
+ x1, dx1, d1, dd1, dd);
+ }
+ if (y1 != y2) {
+ dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, y1, y2, x2, dx2,
+ x1, dx1, value, 0, dd);
+ }
+ }
+ }
+ }
+}
+
+template <FillClip clip>
+void drawRectangle(qint32 *bits, int width, int height,
+ const QPoint *int1, const QPoint *center1, const QPoint *ext1,
+ const QPoint *int2, const QPoint *center2, const QPoint *ext2,
+ qint32 extValue)
+{
+ if (center1->y() > center2->y()) {
+ qSwap(center1, center2);
+ qSwap(int1, ext2);
+ qSwap(ext1, int2);
+ extValue = -extValue;
+ }
+
+ Q_ASSERT(ext1->x() - center1->x() == center1->x() - int1->x());
+ Q_ASSERT(ext1->y() - center1->y() == center1->y() - int1->y());
+ Q_ASSERT(ext2->x() - center2->x() == center2->x() - int2->x());
+ Q_ASSERT(ext2->y() - center2->y() == center2->y() - int2->y());
+
+ const int yc1 = clip == Clip ? qBound(0, center1->y() >> 8, height) : center1->y() >> 8;
+ const int yc2 = clip == Clip ? qBound(0, center2->y() >> 8, height) : center2->y() >> 8;
+ const int yi1 = clip == Clip ? qBound(0, int1->y() >> 8, height) : int1->y() >> 8;
+ const int yi2 = clip == Clip ? qBound(0, int2->y() >> 8, height) : int2->y() >> 8;
+ const int ye1 = clip == Clip ? qBound(0, ext1->y() >> 8, height) : ext1->y() >> 8;
+ const int ye2 = clip == Clip ? qBound(0, ext2->y() >> 8, height) : ext2->y() >> 8;
+
+ const int center1Frac = clip == Clip ? (yc1 << 8) + 0xff - center1->y() : ~center1->y() & 0xff;
+ const int center2Frac = clip == Clip ? (yc2 << 8) + 0xff - center2->y() : ~center2->y() & 0xff;
+ const int int1Frac = clip == Clip ? (yi1 << 8) + 0xff - int1->y() : ~int1->y() & 0xff;
+ const int ext1Frac = clip == Clip ? (ye1 << 8) + 0xff - ext1->y() : ~ext1->y() & 0xff;
+
+ int dxC = 0, dxE = 0; // cap slope, edge slope
+ qint32 ddC = 0;
+ if (ext1->y() != int1->y()) {
+ dxC = ((ext1->x() - int1->x()) << 8) / (ext1->y() - int1->y());
+ ddC = (extValue << 9) / (ext1->y() - int1->y());
+ }
+ if (ext1->y() != ext2->y())
+ dxE = ((ext1->x() - ext2->x()) << 8) / (ext1->y() - ext2->y());
+
+ const qint32 div = (ext1->x() - int1->x()) * (ext2->y() - int1->y())
+ - (ext1->y() - int1->y()) * (ext2->x() - int1->x());
+ const qint32 dd = div ? qint32((qint64(extValue * (ext2->y() - ext1->y())) << 9) / div) : 0;
+
+ int xe1, xe2, xc1, xc2;
+ qint32 d;
+
+ qint32 intValue = -extValue;
+
+ if (center2->x() < center1->x()) {
+ // Leaning to the right. '/'
+ if (int1->y() < ext2->y()) {
+ // Mostly vertical.
+ Q_ASSERT(ext1->y() != ext2->y());
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ if (ye1 != yi1) {
+ xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 += (ye1 - yc1) * dxC;
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, yi1, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ if (yi1 != ye2)
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi1, ye2, xe1, dxE,
+ xe2, dxE, extValue, 0, dd);
+ if (ye2 != yi2) {
+ xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (ye2 - yc2) * dxC;
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye2, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ } else {
+ // Mostly horizontal.
+ Q_ASSERT(ext1->y() != int1->y());
+ xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (ye2 - yc2) * dxC;
+ xc2 += (ye1 - yc1) * dxC;
+ if (ye1 != ye2) {
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ if (ye2 != yi1) {
+ d = (clip == Clip ? (ye2 << 8) + 0xff - center2->y()
+ : (ext2->y() | 0xff) - center2->y())
+ * 2 * extValue / (ext1->y() - int1->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye2, yi1, xc1, dxC,
+ xc2, dxC, d, ddC, dd);
+ }
+ if (yi1 != yi2) {
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ }
+ } else {
+ // Leaning to the left. '\'
+ if (ext1->y() < int2->y()) {
+ // Mostly vertical.
+ Q_ASSERT(ext1->y() != ext2->y());
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ if (yi1 != ye1) {
+ xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (yi1 - yc1) * dxC;
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, ye1, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ if (ye1 != yi2)
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye1, yi2, xe1, dxE,
+ xe2, dxE, intValue, 0, dd);
+ if (yi2 != ye2) {
+ xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 += (yi2 - yc2) * dxC;
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi2, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ } else {
+ // Mostly horizontal.
+ Q_ASSERT(ext1->y() != int1->y());
+ xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (yi1 - yc1) * dxC;
+ xc2 += (yi2 - yc2) * dxC;
+ if (yi1 != yi2) {
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ if (yi2 != ye1) {
+ d = (clip == Clip ? (yi2 << 8) + 0xff - center2->y()
+ : (int2->y() | 0xff) - center2->y())
+ * 2 * extValue / (ext1->y() - int1->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi2, ye1, xc1, dxC,
+ xc2, dxC, d, ddC, dd);
+ }
+ if (ye1 != ye2) {
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ }
+ }
+}
+
+static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vertices,
+ const quint32 *indices, int indexCount, qint32 value)
+{
+ Q_ASSERT(indexCount != 0);
+ Q_ASSERT(height <= 128);
+ QVarLengthArray<quint8, 16> scans[128];
+ int first = 0;
+ for (int i = 1; i < indexCount; ++i) {
+ quint32 idx1 = indices[i - 1];
+ quint32 idx2 = indices[i];
+ Q_ASSERT(idx1 != quint32(-1));
+ if (idx2 == quint32(-1)) {
+ idx2 = indices[first];
+ Q_ASSERT(idx2 != quint32(-1));
+ first = ++i;
+ }
+ const QPoint *v1 = &vertices[idx1];
+ const QPoint *v2 = &vertices[idx2];
+ if (v2->y() < v1->y())
+ qSwap(v1, v2);
+ int fromY = qMax(0, v1->y() >> 8);
+ int toY = qMin(height, v2->y() >> 8);
+ if (fromY >= toY)
+ continue;
+ int dx = ((v2->x() - v1->x()) << 8) / (v2->y() - v1->y());
+ int x = v1->x() + ((fromY << 8) + 0xff - v1->y()) * (v2->x() - v1->x()) / (v2->y() - v1->y());
+ for (int y = fromY; y < toY; ++y) {
+ quint32 c = quint32(x >> 8);
+ if (c < quint32(width))
+ scans[y].append(quint8(c));
+ x += dx;
+ }
+ }
+ for (int i = 0; i < height; ++i) {
+ quint8 *scanline = scans[i].data();
+ int size = scans[i].size();
+ for (int j = 1; j < size; ++j) {
+ int k = j;
+ quint8 value = scanline[k];
+ for (; k != 0 && value < scanline[k - 1]; --k)
+ scanline[k] = scanline[k - 1];
+ scanline[k] = value;
+ }
+ qint32 *line = bits + i * width;
+ int j = 0;
+ for (; j + 1 < size; j += 2) {
+ for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
+ line[x] = value;
+ }
+ if (j < size) {
+ for (int x = scanline[j]; x < width; ++x)
+ line[x] = value;
+ }
+ }
+}
+
+static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfScale, int offs)
+{
+ QImage image(imgSize, imgSize, QImage::Format_Indexed8);
+
+ if (path.isEmpty()) {
+ image.fill(0);
+ return image;
+ }
+
+ QTransform transform;
+ transform.translate(offs, offs);
+ transform.scale(qreal(1) / dfScale, qreal(1) / dfScale);
+
+ QDataBuffer<quint32> pathIndices(0);
+ QDataBuffer<QPoint> pathVertices(0);
+ qSimplifyPath(path, pathVertices, pathIndices, transform);
+
+ const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5
+ const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5
+
+ QScopedArrayPointer<qint32> bits(new qint32[imgSize * imgSize]);
+ for (int i = 0; i < imgSize * imgSize; ++i)
+ bits[i] = exteriorColor;
+
+ const qreal angleStep = qreal(15 * 3.141592653589793238 / 180);
+ const QPoint rotation(qRound(cos(angleStep) * 0x4000),
+ qRound(sin(angleStep) * 0x4000)); // 2:14 signed
+
+ const quint32 *indices = pathIndices.data();
+ QVarLengthArray<QPoint> normals;
+ QVarLengthArray<QPoint> vertices;
+ QVarLengthArray<bool> isConvex;
+ QVarLengthArray<bool> needsClipping;
+
+ drawPolygons(bits.data(), imgSize, imgSize, pathVertices.data(), indices, pathIndices.size(),
+ interiorColor);
+
+ int index = 0;
+
+ while (index < pathIndices.size()) {
+ normals.clear();
+ vertices.clear();
+ needsClipping.clear();
+
+ // Find end of polygon.
+ int end = index;
+ while (indices[end] != quint32(-1))
+ ++end;
+
+ // Calculate vertex normals.
+ for (int next = index, prev = end - 1; next < end; prev = next++) {
+ quint32 fromVertexIndex = indices[prev];
+ quint32 toVertexIndex = indices[next];
+
+ const QPoint &from = pathVertices.at(fromVertexIndex);
+ const QPoint &to = pathVertices.at(toVertexIndex);
+
+ QPoint n(to.y() - from.y(), from.x() - to.x());
+ if (n.x() == 0 && n.y() == 0)
+ continue;
+ int scale = qRound((offs << 16) / sqrt(qreal(n.x() * n.x() + n.y() * n.y()))); // 8:16
+ n.rx() = n.x() * scale >> 8;
+ n.ry() = n.y() * scale >> 8;
+ normals.append(n);
+ QPoint v(to.x() + 0x7f, to.y() + 0x7f);
+ vertices.append(v);
+ needsClipping.append((to.x() < offs << 8) || (to.x() >= (imgSize - offs) << 8)
+ || (to.y() < offs << 8) || (to.y() >= (imgSize - offs) << 8));
+ }
+
+ isConvex.resize(normals.count());
+ for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ isConvex[prev] = normals.at(prev).x() * normals.at(next).y()
+ - normals.at(prev).y() * normals.at(next).x() < 0;
+ }
+
+ // Draw quads.
+ for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ QPoint n = normals.at(next);
+ QPoint intPrev = vertices.at(prev);
+ QPoint extPrev = vertices.at(prev);
+ QPoint intNext = vertices.at(next);
+ QPoint extNext = vertices.at(next);
+
+ extPrev.rx() -= n.x();
+ extPrev.ry() -= n.y();
+ intPrev.rx() += n.x();
+ intPrev.ry() += n.y();
+ extNext.rx() -= n.x();
+ extNext.ry() -= n.y();
+ intNext.rx() += n.x();
+ intNext.ry() += n.y();
+
+ if (needsClipping[prev] || needsClipping[next]) {
+ drawRectangle<Clip>(bits.data(), imgSize, imgSize,
+ &intPrev, &vertices.at(prev), &extPrev,
+ &intNext, &vertices.at(next), &extNext,
+ exteriorColor);
+ } else {
+ drawRectangle<NoClip>(bits.data(), imgSize, imgSize,
+ &intPrev, &vertices.at(prev), &extPrev,
+ &intNext, &vertices.at(next), &extNext,
+ exteriorColor);
+ }
+
+ if (isConvex.at(prev)) {
+ QPoint p = extPrev;
+ if (needsClipping[prev]) {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
+ p.rx() = vertices.at(prev).x() - normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() - normals.at(prev).y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() - n.x();
+ p.ry() = vertices.at(prev).y() - n.y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ extPrev = p;
+ }
+ } else {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
+ p.rx() = vertices.at(prev).x() - normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() - normals.at(prev).y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() - n.x();
+ p.ry() = vertices.at(prev).y() - n.y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ extPrev = p;
+ }
+ }
+ } else {
+ QPoint p = intPrev;
+ if (needsClipping[prev]) {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
+ p.rx() = vertices.at(prev).x() + normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() + normals.at(prev).y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() + n.x();
+ p.ry() = vertices.at(prev).y() + n.y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ intPrev = p;
+ }
+ } else {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
+ p.rx() = vertices.at(prev).x() + normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() + normals.at(prev).y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() + n.x();
+ p.ry() = vertices.at(prev).y() + n.y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ intPrev = p;
+ }
+ }
+ }
+ }
+
+ index = end + 1;
+ }
+
+ const qint32 *inLine = bits.data();
+ uchar *outLine = image.bits();
+ int padding = image.bytesPerLine() - image.width();
+ for (int y = 0; y < imgSize; ++y) {
+ for (int x = 0; x < imgSize; ++x, ++inLine, ++outLine)
+ *outLine = uchar((0x7f80 - *inLine) >> 8);
+ outLine += padding;
+ }
+
+ return image;
+}
+
+bool qt_fontHasNarrowOutlines(const QRawFont &f)
+{
+ QRawFont font = f;
+ font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);
+ Q_ASSERT(font.isValid());
+
+ QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O"));
+ if (glyphIndices.size() < 1)
+ return false;
+
+ QImage im = font.alphaMapForGlyph(glyphIndices.at(0), QRawFont::PixelAntialiasing);
+ if (im.isNull())
+ return false;
+
+ int minHThick = 999;
+ int minVThick = 999;
+
+ int thick = 0;
+ bool in = false;
+ int y = (im.height() + 1) / 2;
+ for (int x = 0; x < im.width(); ++x) {
+ int a = qAlpha(im.pixel(x, y));
+ if (a > 127) {
+ in = true;
+ ++thick;
+ } else if (in) {
+ in = false;
+ minHThick = qMin(minHThick, thick);
+ thick = 0;
+ }
+ }
+
+ thick = 0;
+ in = false;
+ int x = (im.width() + 1) / 2;
+ for (int y = 0; y < im.height(); ++y) {
+ int a = qAlpha(im.pixel(x, y));
+ if (a > 127) {
+ in = true;
+ ++thick;
+ } else if (in) {
+ in = false;
+ minVThick = qMin(minVThick, thick);
+ thick = 0;
+ }
+ }
+
+ return minHThick == 1 || minVThick == 1;
+}
+
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution)
+{
+ QRawFont renderFont = font;
+ renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(doubleResolution) * QT_DISTANCEFIELD_SCALE(doubleResolution));
+
+ QPainterPath path = renderFont.pathForGlyph(glyph);
+ path.translate(-path.boundingRect().topLeft());
+ path.setFillRule(Qt::WindingFill);
+
+ QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution),
+ path,
+ QT_DISTANCEFIELD_SCALE(doubleResolution),
+ QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution));
+ return im;
+}
+
+QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QSGContext *c)
+ : sgCtx(c)
+ , m_threshold_func(defaultThresholdFunc)
+ , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
+{
+#ifndef QT_OPENGL_ES
+ m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
+#else
+ m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
+#endif
+}
+
+QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
+{
+ qDeleteAll(m_caches.values());
+}
+
+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();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
new file mode 100644
index 0000000000..bc28a4d9e1
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGDISTANCEFIELDUTIL_H
+#define QSGDISTANCEFIELDUTIL_H
+
+#include <qrawfont.h>
+#include <private/qfontengine_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54
+#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64
+#define QT_DISTANCEFIELD_DEFAULT_SCALE 16
+#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80
+#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000
+
+#define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \
+ QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE)
+#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \
+ QT_DISTANCEFIELD_DEFAULT_TILESIZE)
+#define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \
+ QT_DISTANCEFIELD_DEFAULT_SCALE)
+#define QT_DISTANCEFIELD_RADIUS(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \
+ QT_DISTANCEFIELD_DEFAULT_RADIUS)
+
+
+typedef float (*ThresholdFunc)(float glyphScale);
+typedef float (*AntialiasingSpreadFunc)(float glyphScale);
+
+bool qt_fontHasNarrowOutlines(const QRawFont &f);
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution);
+
+
+class QOpenGLShaderProgram;
+class QSGDistanceFieldGlyphCache;
+class QSGContext;
+
+class Q_QUICK_EXPORT QSGDistanceFieldGlyphCacheManager
+{
+public:
+ QSGDistanceFieldGlyphCacheManager(QSGContext *c);
+ ~QSGDistanceFieldGlyphCacheManager();
+
+ QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
+
+ QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
+ void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
+
+ ThresholdFunc thresholdFunc() const { return m_threshold_func; }
+ void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
+
+ AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
+ void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
+
+private:
+ QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
+
+ QSGContext *sgCtx;
+
+ QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
+ ThresholdFunc m_threshold_func;
+ AntialiasingSpreadFunc m_antialiasingSpread_func;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDISTANCEFIELDUTIL_H
diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp
new file mode 100644
index 0000000000..b8c93bab8b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgengine.h"
+
+#include <QtQuick/qquickcanvas.h>
+
+#include <private/qobject_p.h>
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QSGEnginePrivate : public QObjectPrivate
+{
+public:
+ QSGEnginePrivate()
+ : canvas(0)
+ {
+ }
+
+ QQuickCanvas *canvas;
+};
+
+/*!
+ \class QSGEngine
+ \deprecated
+ */
+
+QSGEngine::QSGEngine(QObject *parent) :
+ QObject(*(new QSGEnginePrivate), parent)
+{
+}
+
+
+QSGEngine::~QSGEngine()
+{
+}
+
+
+void QSGEngine::setCanvas(QQuickCanvas *canvas)
+{
+ d_func()->canvas = canvas;
+ connect(canvas, SIGNAL(afterRendering()), this, SIGNAL(afterRendering()));
+ connect(canvas, SIGNAL(beforeRendering()), this, SIGNAL(beforeRendering()));
+}
+
+void QSGEngine::setClearBeforeRendering(bool enabled)
+{
+ d_func()->canvas->setClearBeforeRendering(enabled);
+}
+
+bool QSGEngine::clearBeforeRendering() const
+{
+ return d_func()->canvas->clearBeforeRendering();
+}
+
+QSGTexture *QSGEngine::createTextureFromImage(const QImage &image) const
+{
+ return d_func()->canvas->createTextureFromImage(image);
+}
+
+QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, TextureOptions options) const
+{
+ return d_func()->canvas->createTextureFromId(id, size, QQuickCanvas::CreateTextureOptions((int) options));
+}
+
+void QSGEngine::setClearColor(const QColor &color)
+{
+ d_func()->canvas->setClearColor(color);
+}
+
+QColor QSGEngine::clearColor() const
+{
+ return d_func()->canvas->clearColor();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h
new file mode 100644
index 0000000000..6b7ceb939f
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGENGINE_H
+#define QSGENGINE_H
+
+#include <QObject>
+
+#include <QtQuick/qsgtexture.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGEnginePrivate;
+
+class QQuickCanvas;
+
+class Q_QUICK_EXPORT QSGEngine : public QObject
+{
+ Q_OBJECT
+
+ Q_DECLARE_PRIVATE(QSGEngine)
+
+public:
+
+ enum TextureOption {
+ TextureHasAlphaChannel = 0x0001,
+ TextureHasMipmaps = 0x0002,
+ TextureOwnsGLTexture = 0x0004
+ };
+ Q_DECLARE_FLAGS(TextureOptions, TextureOption)
+
+ QSGTexture *createTextureFromImage(const QImage &image) const;
+ QSGTexture *createTextureFromId(uint id, const QSize &size, TextureOptions options = TextureOption(0)) const;
+
+ void setClearBeforeRendering(bool enabled);
+ bool clearBeforeRendering() const;
+
+ void setClearColor(const QColor &color);
+ QColor clearColor() const;
+
+Q_SIGNALS:
+ void beforeRendering();
+ void afterRendering();
+
+private:
+ QSGEngine(QObject *parent = 0);
+ ~QSGEngine();
+
+ friend class QSGContext;
+ friend class QSGContextPrivate;
+ friend class QQuickCanvasPrivate;
+ void setCanvas(QQuickCanvas *canvas);
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGENGINE_H
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
new file mode 100644
index 0000000000..cf5c7869ea
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgflatcolormaterial.h"
+
+#include <qopenglshaderprogram.h>
+
+QT_BEGIN_NAMESPACE
+
+class FlatColorMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+ int m_color_id;
+};
+
+QSGMaterialType FlatColorMaterialShader::type;
+
+void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+
+ QSGFlatColorMaterial *oldMaterial = static_cast<QSGFlatColorMaterial *>(oldEffect);
+ QSGFlatColorMaterial *newMaterial = static_cast<QSGFlatColorMaterial *>(newEffect);
+
+ const QColor &c = newMaterial->color();
+
+ if (oldMaterial == 0 || c != oldMaterial->color() || state.isOpacityDirty()) {
+ float opacity = state.opacity();
+ QVector4D v(c.redF() * c.alphaF() * opacity,
+ c.greenF() * c.alphaF() * opacity,
+ c.blueF() * c.alphaF() * opacity,
+ c.alphaF() * opacity);
+ program()->setUniformValue(m_color_id, v);
+ }
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+char const *const *FlatColorMaterialShader::attributeNames() const
+{
+ static char const *const attr[] = { "vCoord", 0 };
+ return attr;
+}
+
+void FlatColorMaterialShader::initialize()
+{
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_color_id = program()->uniformLocation("color");
+}
+
+const char *FlatColorMaterialShader::vertexShader() const {
+ return
+ "attribute highp vec4 vCoord; \n"
+ "uniform highp mat4 matrix; \n"
+ "void main() { \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *FlatColorMaterialShader::fragmentShader() const {
+ return
+ "uniform lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "}";
+}
+
+
+
+/*!
+ \class QSGFlatColorMaterial
+ \brief The QSGFlatColorMaterial class provides a convenient way of rendering
+ solid colored geometry in the scene graph.
+
+ \inmodule QtQuick
+
+ The flat color material will fill every pixel in a geometry using
+ a solid color. The color can contain transparency.
+
+ The geometry to be rendered with a flat color material requires
+ vertices in attribute location 0 in the QSGGeometry object to render
+ correctly. The QSGGeometry::defaultAttributes_Point2D() returns an attribute
+ set compatible with this material.
+
+ The flat color material respects both current opacity and current matrix
+ when updating it's rendering state.
+ */
+
+
+/*!
+ Constructs a new flat color material.
+
+ The default color is white.
+ */
+
+QSGFlatColorMaterial::QSGFlatColorMaterial() : m_color(QColor(255, 255, 255))
+{
+}
+
+
+
+/*!
+ \fn QColor QSGFlatColorMaterial::color() const
+
+ Returns this flat color material's color.
+
+ The default color is white.
+ */
+
+
+
+/*!
+ Sets this flat color material's color to \a color.
+ */
+
+void QSGFlatColorMaterial::setColor(const QColor &color)
+{
+ m_color = color;
+ setFlag(Blending, m_color.alpha() != 0xff);
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialType *QSGFlatColorMaterial::type() const
+{
+ return &FlatColorMaterialShader::type;
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialShader *QSGFlatColorMaterial::createShader() const
+{
+ return new FlatColorMaterialShader;
+}
+
+
+int QSGFlatColorMaterial::compare(const QSGMaterial *other) const
+{
+ const QSGFlatColorMaterial *flat = static_cast<const QSGFlatColorMaterial *>(other);
+ return m_color.rgba() - flat->color().rgba();
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.h b/src/quick/scenegraph/util/qsgflatcolormaterial.h
new file mode 100644
index 0000000000..d788901b8a
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 FLATCOLORMATERIAL_H
+#define FLATCOLORMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+#include <qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGFlatColorMaterial : public QSGMaterial
+{
+public:
+ QSGFlatColorMaterial();
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+
+ void setColor(const QColor &color);
+ const QColor &color() const { return m_color; }
+
+ int compare(const QSGMaterial *other) const;
+
+private:
+ QColor m_color;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // FLATCOLORMATERIAL_H
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
new file mode 100644
index 0000000000..640aab967e
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgpainternode_p.h"
+
+#include <QtQuick/private/qquickpainteditem_p.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qopenglextensions_p.h>
+#include <qopenglframebufferobject.h>
+#include <qopenglfunctions.h>
+#include <qopenglpaintdevice.h>
+#include <qmath.h>
+#include <qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_MINIMUM_DYNAMIC_FBO_SIZE 64
+
+static inline int qt_next_power_of_two(int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+QSGPainterTexture::QSGPainterTexture()
+ : QSGPlainTexture()
+{
+
+}
+
+void QSGPainterTexture::bind()
+{
+ if (m_dirty_rect.isNull()) {
+ QSGPlainTexture::bind();
+ return;
+ }
+
+ bool oldMipmapsGenerated = m_mipmaps_generated;
+ m_mipmaps_generated = true;
+ QSGPlainTexture::bind();
+ m_mipmaps_generated = oldMipmapsGenerated;
+
+ QImage subImage = m_image.copy(m_dirty_rect);
+
+ int w = m_dirty_rect.width();
+ int h = m_dirty_rect.height();
+
+#ifdef QT_OPENGL_ES
+ glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
+ GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
+#else
+ glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
+ GL_BGRA, GL_UNSIGNED_BYTE, subImage.constBits());
+#endif
+
+ if (m_has_mipmaps && !m_mipmaps_generated) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+
+ m_dirty_texture = false;
+ m_dirty_bind_options = false;
+
+ m_dirty_rect = QRect();
+}
+
+QSGPainterNode::QSGPainterNode(QQuickPaintedItem *item)
+ : QSGGeometryNode()
+ , m_preferredRenderTarget(QQuickPaintedItem::Image)
+ , m_actualRenderTarget(QQuickPaintedItem::Image)
+ , m_item(item)
+ , m_fbo(0)
+ , m_multisampledFbo(0)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+ , m_texture(0)
+ , m_gl_device(0)
+ , m_size(1, 1)
+ , m_dirtyContents(false)
+ , m_opaquePainting(false)
+ , m_linear_filtering(false)
+ , m_mipmapping(false)
+ , m_smoothPainting(false)
+ , m_extensionsChecked(false)
+ , m_multisamplingSupported(false)
+ , m_fastFBOResizing(false)
+ , m_fillColor(Qt::transparent)
+ , m_contentsScale(1.0)
+ , m_dirtyGeometry(false)
+ , m_dirtyRenderTarget(false)
+ , m_dirtyTexture(false)
+{
+ m_context = static_cast<QQuickPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphContext();
+
+ setMaterial(&m_materialO);
+ setOpaqueMaterial(&m_material);
+ setGeometry(&m_geometry);
+}
+
+QSGPainterNode::~QSGPainterNode()
+{
+ delete m_texture;
+ delete m_fbo;
+ delete m_multisampledFbo;
+ delete m_gl_device;
+}
+
+void QSGPainterNode::paint()
+{
+ QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
+
+ QPainter painter;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ painter.begin(&m_image);
+ else {
+ if (!m_gl_device) {
+ m_gl_device = new QOpenGLPaintDevice(m_fboSize);
+ m_gl_device->setPaintFlipped(true);
+ }
+
+ if (m_multisampledFbo)
+ m_multisampledFbo->bind();
+ else
+ m_fbo->bind();
+
+ painter.begin(m_gl_device);
+ }
+
+ if (m_smoothPainting) {
+ painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
+ | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
+ }
+
+ painter.scale(m_contentsScale, m_contentsScale);
+
+ QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
+ qFloor(dirtyRect.y()/m_contentsScale),
+ qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
+ qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+
+ if (!m_dirtyRect.isNull())
+ painter.setClipRect(sclip);
+
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(sclip, m_fillColor);
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ m_item->paint(&painter);
+ painter.end();
+
+ if (m_actualRenderTarget == QQuickPaintedItem::Image) {
+ m_texture->setImage(m_image);
+ m_texture->setDirtyRect(dirtyRect);
+ } else if (m_multisampledFbo) {
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
+ }
+
+ if (m_multisampledFbo)
+ m_multisampledFbo->release();
+ else if (m_fbo)
+ m_fbo->release();
+
+ m_dirtyRect = QRect();
+}
+
+void QSGPainterNode::update()
+{
+ if (m_dirtyRenderTarget)
+ updateRenderTarget();
+ if (m_dirtyGeometry)
+ updateGeometry();
+ if (m_dirtyTexture)
+ updateTexture();
+
+ if (m_dirtyContents)
+ paint();
+
+ m_dirtyGeometry = false;
+ m_dirtyRenderTarget = false;
+ m_dirtyTexture = false;
+ m_dirtyContents = false;
+}
+
+void QSGPainterNode::updateTexture()
+{
+ m_texture->setHasMipmaps(m_mipmapping);
+ m_texture->setHasAlphaChannel(!m_opaquePainting);
+ m_material.setTexture(m_texture);
+ m_materialO.setTexture(m_texture);
+
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::updateGeometry()
+{
+ QRectF source;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ source = QRectF(0, 0, 1, 1);
+ else
+ source = QRectF(0, 0, qreal(m_size.width()) / m_fboSize.width(), qreal(m_size.height()) / m_fboSize.height());
+ QRectF dest(0, 0, m_size.width(), m_size.height());
+ if (m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject)
+ dest = QRectF(QPointF(0, m_size.height()), QPointF(m_size.width(), 0));
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry,
+ dest,
+ source);
+ markDirty(DirtyGeometry);
+}
+
+void QSGPainterNode::updateRenderTarget()
+{
+ if (!m_extensionsChecked) {
+ QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
+ m_multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample")
+ && extensions.contains("GL_EXT_framebuffer_blit");
+ m_extensionsChecked = true;
+ }
+
+ m_dirtyContents = true;
+
+ QQuickPaintedItem::RenderTarget oldTarget = m_actualRenderTarget;
+ if (m_preferredRenderTarget == QQuickPaintedItem::Image) {
+ m_actualRenderTarget = QQuickPaintedItem::Image;
+ } else {
+ if (!m_multisamplingSupported && m_smoothPainting)
+ m_actualRenderTarget = QQuickPaintedItem::Image;
+ else
+ m_actualRenderTarget = m_preferredRenderTarget;
+ }
+ if (oldTarget != m_actualRenderTarget) {
+ m_image = QImage();
+ delete m_fbo;
+ delete m_multisampledFbo;
+ m_fbo = m_multisampledFbo = 0;
+ }
+
+ if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject ||
+ m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) {
+ const QOpenGLContext *ctx = m_context->glContext();
+ if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
+ return;
+
+ if (m_fboSize.isEmpty())
+ updateFBOSize();
+
+ delete m_fbo;
+ delete m_multisampledFbo;
+ m_fbo = m_multisampledFbo = 0;
+
+ if (m_smoothPainting && ctx->format().samples() && m_multisamplingSupported) {
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(8);
+ m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ } else {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ } else {
+ if (!m_image.isNull() && !m_dirtyGeometry)
+ return;
+
+ m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
+ m_image.fill(Qt::transparent);
+ }
+
+ QSGPainterTexture *texture = new QSGPainterTexture;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image) {
+ texture->setOwnsTexture(true);
+ texture->setTextureSize(m_size);
+ } else {
+ texture->setTextureId(m_fbo->texture());
+ texture->setOwnsTexture(false);
+ texture->setTextureSize(m_fboSize);
+ }
+
+ if (m_texture)
+ delete m_texture;
+
+ texture->setTextureSize(m_size);
+ m_texture = texture;
+}
+
+void QSGPainterNode::updateFBOSize()
+{
+ int fboWidth;
+ int fboHeight;
+ if (m_fastFBOResizing) {
+ fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.width()));
+ fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.height()));
+ } else {
+ QSize minimumFBOSize = m_context->minimumFBOSize();
+ fboWidth = qMax(minimumFBOSize.width(), m_size.width());
+ fboHeight = qMax(minimumFBOSize.height(), m_size.height());
+ }
+
+ m_fboSize = QSize(fboWidth, fboHeight);
+}
+
+void QSGPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target)
+{
+ if (m_preferredRenderTarget == target)
+ return;
+
+ m_preferredRenderTarget = target;
+
+ m_dirtyRenderTarget = true;
+ m_dirtyGeometry = true;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+
+ m_size = size;
+ updateFBOSize();
+
+ if (m_fbo)
+ m_dirtyRenderTarget = m_fbo->size() != m_fboSize || m_dirtyRenderTarget;
+ else
+ m_dirtyRenderTarget = true;
+ m_dirtyGeometry = true;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setDirty(const QRect &dirtyRect)
+{
+ m_dirtyContents = true;
+ m_dirtyRect = dirtyRect;
+
+ if (m_mipmapping)
+ m_dirtyTexture = true;
+
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setOpaquePainting(bool opaque)
+{
+ if (opaque == m_opaquePainting)
+ return;
+
+ m_opaquePainting = opaque;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setLinearFiltering(bool linearFiltering)
+{
+ if (linearFiltering == m_linear_filtering)
+ return;
+
+ m_linear_filtering = linearFiltering;
+
+ m_material.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
+ m_materialO.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setMipmapping(bool mipmapping)
+{
+ if (mipmapping == m_mipmapping)
+ return;
+
+ m_mipmapping = mipmapping;
+ m_material.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
+ m_materialO.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setSmoothPainting(bool s)
+{
+ if (s == m_smoothPainting)
+ return;
+
+ m_smoothPainting = s;
+ m_dirtyRenderTarget = true;
+}
+
+void QSGPainterNode::setFillColor(const QColor &c)
+{
+ if (c == m_fillColor)
+ return;
+
+ m_fillColor = c;
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setContentsScale(qreal s)
+{
+ if (s == m_contentsScale)
+ return;
+
+ m_contentsScale = s;
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setFastFBOResizing(bool dynamic)
+{
+ m_fastFBOResizing = dynamic;
+}
+
+QImage QSGPainterNode::toImage() const
+{
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ return m_image;
+ else
+ return m_fbo->toImage();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgpainternode_p.h b/src/quick/scenegraph/util/qsgpainternode_p.h
new file mode 100644
index 0000000000..85f26f6056
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgpainternode_p.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGPAINTERNODE_P_H
+#define QSGPAINTERNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+#include "qsgtexturematerial.h"
+#include "qsgtexture_p.h"
+
+#include <QtQuick/qquickpainteditem.h>
+
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLFramebufferObject;
+class QOpenGLPaintDevice;
+
+class Q_QUICK_EXPORT QSGPainterTexture : public QSGPlainTexture
+{
+public:
+ QSGPainterTexture();
+
+ void setDirtyRect(const QRect &rect) { m_dirty_rect = rect; }
+
+ void bind();
+
+private:
+ QRect m_dirty_rect;
+};
+
+class Q_QUICK_EXPORT QSGPainterNode : public QSGGeometryNode
+{
+public:
+ QSGPainterNode(QQuickPaintedItem *item);
+ virtual ~QSGPainterNode();
+
+ void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target);
+
+ void setSize(const QSize &size);
+ QSize size() const { return m_size; }
+
+ void setDirty(const QRect &dirtyRect = QRect());
+
+ void setOpaquePainting(bool opaque);
+ bool opaquePainting() const { return m_opaquePainting; }
+
+ void setLinearFiltering(bool linearFiltering);
+ bool linearFiltering() const { return m_linear_filtering; }
+
+ void setMipmapping(bool mipmapping);
+ bool mipmapping() const { return m_mipmapping; }
+
+ void setSmoothPainting(bool s);
+ bool smoothPainting() const { return m_smoothPainting; }
+
+ void setFillColor(const QColor &c);
+ QColor fillColor() const { return m_fillColor; }
+
+ void setContentsScale(qreal s);
+ qreal contentsScale() const { return m_contentsScale; }
+
+ void setFastFBOResizing(bool dynamic);
+ bool fastFBOResizing() const { return m_fastFBOResizing; }
+
+ QImage toImage() const;
+ void update();
+
+ void paint();
+
+private:
+ void updateTexture();
+ void updateGeometry();
+ void updateRenderTarget();
+ void updateFBOSize();
+
+ QSGContext *m_context;
+
+ QQuickPaintedItem::RenderTarget m_preferredRenderTarget;
+ QQuickPaintedItem::RenderTarget m_actualRenderTarget;
+
+ QQuickPaintedItem *m_item;
+
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_multisampledFbo;
+ QImage m_image;
+
+ QSGOpaqueTextureMaterial m_material;
+ QSGTextureMaterial m_materialO;
+ QSGGeometry m_geometry;
+ QSGPainterTexture *m_texture;
+ QOpenGLPaintDevice *m_gl_device;
+
+ QSize m_size;
+ QSize m_fboSize;
+ bool m_dirtyContents;
+ QRect m_dirtyRect;
+ bool m_opaquePainting;
+ bool m_linear_filtering;
+ bool m_mipmapping;
+ bool m_smoothPainting;
+ bool m_extensionsChecked;
+ bool m_multisamplingSupported;
+ bool m_fastFBOResizing;
+ QColor m_fillColor;
+ qreal m_contentsScale;
+
+ bool m_dirtyGeometry;
+ bool m_dirtyRenderTarget;
+ bool m_dirtyTexture;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QSGPAINTERNODE_P_H
diff --git a/src/quick/scenegraph/util/qsgsimplematerial.h b/src/quick/scenegraph/util/qsgsimplematerial.h
new file mode 100644
index 0000000000..44beb135f7
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimplematerial.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGSIMPLEMATERIAL_H
+#define QSGSIMPLEMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+template <typename State>
+class QSGSimpleMaterialShader : public QSGMaterialShader
+{
+public:
+ void initialize() {
+ QSGMaterialShader::initialize();
+
+ m_id_matrix = program()->uniformLocation(uniformMatrixName());
+ if (m_id_matrix < 0) {
+ qFatal("QSGSimpleMaterialShader does not implement 'uniform highp mat4 %s;' in its vertex shader",
+ uniformMatrixName());
+ }
+
+ const char *opacity = uniformOpacityName();
+ if (opacity) {
+ m_id_opacity = program()->uniformLocation(uniformOpacityName());
+ if (m_id_opacity < 0) {
+ qFatal("QSGSimpleMaterialShader does not implement 'uniform lowp float %s' in its fragment shader",
+ uniformOpacityName());
+ }
+ } else {
+ m_id_opacity = -1;
+ }
+
+ resolveUniforms();
+ }
+
+ const char *uniformMatrixName() const { return "qt_Matrix"; }
+ const char *uniformOpacityName() const { return "qt_Opacity"; }
+
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
+
+ virtual void updateState(const State *newState, const State *oldState) = 0;
+
+ virtual void resolveUniforms() {}
+
+ virtual QList<QByteArray> attributes() const = 0;
+
+ char const *const *attributeNames() const
+ {
+ if (m_attribute_pointers.size())
+ return m_attribute_pointers.constData();
+
+ QList<QByteArray> names = attributes();
+
+ // Calculate the total number of bytes needed, so we don't get rellocs and
+ // bad pointers while copying over the individual names.
+ // Add an extra byte pr entry for the '\0' char.
+ int total = 0;
+ for (int i=0; i<names.size(); ++i)
+ total += names.at(i).size() + 1;
+ m_attribute_name_data.reserve(total);
+
+ // Copy over the names
+ for (int i=0; i<names.size(); ++i) {
+ m_attribute_pointers << m_attribute_name_data.constData() + m_attribute_name_data.size();
+ m_attribute_name_data.append(names.at(i));
+ m_attribute_name_data.append('\0');
+ }
+
+ // Append the "null" terminator
+ m_attribute_pointers << 0;
+
+ return m_attribute_pointers.constData();
+ }
+
+private:
+ int m_id_matrix;
+ int m_id_opacity;
+
+ mutable QByteArray m_attribute_name_data;
+ mutable QVector<const char *> m_attribute_pointers;
+};
+
+#define QSG_DECLARE_SIMPLE_SHADER(Shader, State) \
+static QSGMaterialShader *createShader() \
+{ \
+ return new Shader; \
+} \
+public: \
+static QSGSimpleMaterial<State> *createMaterial() \
+{ \
+ return new QSGSimpleMaterial<State>(createShader); \
+}
+
+
+typedef QSGMaterialShader *(*PtrShaderCreateFunc)();
+
+
+template <typename State>
+class QSGSimpleMaterial : public QSGMaterial
+{
+
+public:
+ QSGSimpleMaterial(const State &state, PtrShaderCreateFunc func)
+ : m_state(state)
+ , m_func(func)
+ {
+ }
+
+ QSGSimpleMaterial(PtrShaderCreateFunc func)
+ : m_func(func)
+ {
+ }
+
+ QSGMaterialShader *createShader() const { return m_func(); }
+ QSGMaterialType *type() const { return &m_type; }
+
+ State *state() { return &m_state; }
+ const State *state() const { return &m_state; }
+
+private:
+ static QSGMaterialType m_type;
+ State m_state;
+ PtrShaderCreateFunc m_func;
+};
+
+#define QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State) \
+static QSGMaterialShader *createShader() \
+{ \
+ return new Shader; \
+} \
+public: \
+static QSGSimpleMaterialComparableMaterial<State> *createMaterial() \
+{ \
+ return new QSGSimpleMaterialComparableMaterial<State>(createShader); \
+}
+
+template <typename State>
+class QSGSimpleMaterialComparableMaterial : public QSGSimpleMaterial<State>
+{
+
+public:
+ QSGSimpleMaterialComparableMaterial(const State &state, PtrShaderCreateFunc func)
+ : QSGSimpleMaterial<State>(state, func) {}
+
+ QSGSimpleMaterialComparableMaterial(PtrShaderCreateFunc func)
+ : QSGSimpleMaterial<State>(func) {}
+
+ int compare(const QSGMaterial *other) const {
+ return QSGSimpleMaterialComparableMaterial<State>::state()->compare(static_cast<const QSGSimpleMaterialComparableMaterial<State> *>(other)->state());
+ }
+};
+
+
+template <typename State>
+QSGMaterialType QSGSimpleMaterial<State>::m_type;
+
+
+template <typename State>
+Q_INLINE_TEMPLATE void QSGSimpleMaterialShader<State>::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+{
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+ if (state.isOpacityDirty() && m_id_opacity >= 0)
+ program()->setUniformValue(m_id_opacity, state.opacity());
+
+ State *ns = static_cast<QSGSimpleMaterial<State> *>(newMaterial)->state();
+ State *old = 0;
+ if (oldMaterial)
+ old = static_cast<QSGSimpleMaterial<State> *>(oldMaterial)->state();
+ updateState(ns, old);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/declarative/scenegraph/util/qsgsimplerectnode.cpp b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
index c3dc5354ca..c3dc5354ca 100644
--- a/src/declarative/scenegraph/util/qsgsimplerectnode.cpp
+++ b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
diff --git a/src/quick/scenegraph/util/qsgsimplerectnode.h b/src/quick/scenegraph/util/qsgsimplerectnode.h
new file mode 100644
index 0000000000..6519290cfe
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimplerectnode.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 SOLIDRECTNODE_H
+#define SOLIDRECTNODE_H
+
+#include <QtQuick/qsgnode.h>
+#include "qsgflatcolormaterial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGSimpleRectNode : public QSGGeometryNode
+{
+public:
+ QSGSimpleRectNode(const QRectF &rect, const QColor &color);
+ QSGSimpleRectNode();
+
+ void setRect(const QRectF &rect);
+ inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
+ QRectF rect() const;
+
+ void setColor(const QColor &color);
+ QColor color() const;
+
+private:
+ QSGFlatColorMaterial m_material;
+ QSGGeometry m_geometry;
+ void *reserved;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SOLIDRECTNODE_H
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
new file mode 100644
index 0000000000..00b240e435
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgsimpletexturenode.h"
+
+QT_BEGIN_NAMESPACE
+
+static void qsgsimpletexturenode_update(QSGGeometry *g,
+ QSGTexture *texture,
+ const QRectF &rect)
+{
+ if (!texture)
+ return;
+
+ QSize ts = texture->textureSize();
+ QRectF sourceRect(0, 0, ts.width(), ts.height());
+ QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect));
+}
+
+/*!
+ \class QSGSimpleTextureNode
+ \brief The QSGSimpleTextureNode class is provided for convenience to easily draw
+ textured content using the QML scene graph.
+
+ \inmodule QtQuick
+
+ \warning The simple texture node class must have a texture before being
+ added to the scene graph to be rendered.
+*/
+
+/*!
+ Constructs a new simple texture node
+ */
+QSGSimpleTextureNode::QSGSimpleTextureNode()
+ : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+{
+ setGeometry(&m_geometry);
+ setMaterial(&m_material);
+ setOpaqueMaterial(&m_opaque_material);
+}
+
+/*!
+ Sets the filtering to be used for this texture node to \a filtering.
+
+ For smooth scaling, use QSGTexture::Linear; for normal scaling, use
+ QSGTexture::Nearest.
+ */
+void QSGSimpleTextureNode::setFiltering(QSGTexture::Filtering filtering)
+{
+ if (m_material.filtering() == filtering)
+ return;
+
+ m_material.setFiltering(filtering);
+ m_opaque_material.setFiltering(filtering);
+ markDirty(DirtyMaterial);
+}
+
+
+/*!
+ Returns the filtering currently set on this texture node
+ */
+QSGTexture::Filtering QSGSimpleTextureNode::filtering() const
+{
+ return m_material.filtering();
+}
+
+
+/*!
+ Sets the target rect of this texture node to \a r
+ */
+void QSGSimpleTextureNode::setRect(const QRectF &r)
+{
+ if (m_rect == r)
+ return;
+ m_rect = r;
+ qsgsimpletexturenode_update(&m_geometry, texture(), m_rect);
+ markDirty(DirtyGeometry);
+}
+
+
+/*!
+ Returns the target rect of this texture node.
+ */
+QRectF QSGSimpleTextureNode::rect() const
+{
+ return m_rect;
+}
+
+/*!
+ Sets the texture of this texture node to \a texture.
+
+ \warning A texture node must have a texture before being added
+ to the scenegraph to be rendered.
+ */
+void QSGSimpleTextureNode::setTexture(QSGTexture *texture)
+{
+ if (m_material.texture() == texture)
+ return;
+ m_material.setTexture(texture);
+ m_opaque_material.setTexture(texture);
+ qsgsimpletexturenode_update(&m_geometry, texture, m_rect);
+ markDirty(DirtyMaterial);
+}
+
+
+
+/*!
+ Returns the texture for this texture node
+ */
+QSGTexture *QSGSimpleTextureNode::texture() const
+{
+ return m_material.texture();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h
new file mode 100644
index 0000000000..605cae11e4
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGSIMPLETEXTURENODE_H
+#define QSGSIMPLETEXTURENODE_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsggeometry.h>
+#include "qsgtexturematerial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGSimpleTextureNode : public QSGGeometryNode
+{
+public:
+ QSGSimpleTextureNode();
+
+ void setRect(const QRectF &rect);
+ inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
+ QRectF rect() const;
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const;
+
+ void setFiltering(QSGTexture::Filtering filtering);
+ QSGTexture::Filtering filtering() const;
+
+private:
+ QSGGeometry m_geometry;
+ QSGOpaqueTextureMaterial m_opaque_material;
+ QSGTextureMaterial m_material;
+
+ QRectF m_rect;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGSIMPLETEXTURENODE_H
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
new file mode 100644
index 0000000000..0abbc8dae1
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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$
+**
+****************************************************************************/
+
+#define GL_GLEXT_PROTOTYPES
+
+#include "qsgtexture_p.h"
+#include <qopenglfunctions.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <qthread.h>
+#include <private/qdeclarativedebugtrace_p.h>
+
+#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC))
+#include <execinfo.h>
+#include <QHash>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+QSGTexturePrivate::QSGTexturePrivate()
+ : wrapChanged(false)
+ , filteringChanged(false)
+ , horizontalWrap(QSGTexture::ClampToEdge)
+ , verticalWrap(QSGTexture::ClampToEdge)
+ , mipmapMode(QSGTexture::None)
+ , filterMode(QSGTexture::Nearest)
+{
+}
+
+#ifndef QT_NO_DEBUG
+
+static int qt_debug_texture_count = 0;
+
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
+
+#define BACKTRACE_SIZE 20
+class SGTextureTraceItem
+{
+public:
+ void *backTrace[BACKTRACE_SIZE];
+ size_t backTraceSize;
+};
+
+static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
+#endif
+
+inline static void qt_debug_print_texture_count()
+{
+ qDebug("Number of leaked textures: %i", qt_debug_texture_count);
+ qt_debug_texture_count = -1;
+
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ while (!qt_debug_allocated_textures.isEmpty()) {
+ QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
+ QSGTexture* texture = it.key();
+ SGTextureTraceItem* item = it.value();
+
+ qt_debug_allocated_textures.erase(it);
+
+ qDebug() << "------";
+ qDebug() << "Leaked" << texture << "backtrace:";
+
+ char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
+
+ if (symbols) {
+ for (int i=0; i<(int) item->backTraceSize; i++)
+ qDebug("Backtrace <%02d>: %s", i, symbols[i]);
+ free(symbols);
+ }
+
+ qDebug() << "------";
+
+ delete item;
+ }
+ }
+#endif
+}
+
+inline static void qt_debug_add_texture(QSGTexture* texture)
+{
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = new SGTextureTraceItem;
+ item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
+ qt_debug_allocated_textures.insert(texture, item);
+ }
+#else
+ Q_UNUSED(texture);
+#endif // Q_OS_LINUX
+
+ ++qt_debug_texture_count;
+
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_debug_print_texture_count);
+ atexit_registered = true;
+ }
+}
+
+static void qt_debug_remove_texture(QSGTexture* texture)
+{
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
+ if (item) {
+ qt_debug_allocated_textures.remove(texture);
+ delete item;
+ }
+ }
+#else
+ Q_UNUSED(texture)
+#endif
+
+ --qt_debug_texture_count;
+
+ if (qt_debug_texture_count < 0)
+ qDebug("Material destroyed after qt_debug_print_texture_count() was called.");
+}
+
+#endif // QT_NO_DEBUG
+
+
+QSGTexture::QSGTexture()
+ : QObject(*(new QSGTexturePrivate))
+{
+#ifndef QT_NO_DEBUG
+ qt_debug_add_texture(this);
+#endif
+}
+
+QSGTexture::~QSGTexture()
+{
+#ifndef QT_NO_DEBUG
+ qt_debug_remove_texture(this);
+#endif
+}
+
+
+/*!
+ \fn void QSGTexture::bind()
+
+ Call this function to bind this texture to the current texture
+ target.
+
+ Binding a texture may also include uploading the texture data from
+ a previously set QImage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+/*!
+ This function returns a copy of the current texture which is removed
+ from its atlas.
+
+ The current texture remains unchanged, so texture coordinates do not
+ need to be updated.
+
+ Removing a texture from an atlas is primarily useful when passing
+ it to a shader that operates on the texture coordinates 0-1 instead
+ of the texture subrect inside the atlas.
+
+ If the texture is not part of a texture atlas, this function returns 0.
+
+ Implementations of this function are recommended to return the same instance
+ for multiple calls to limit memory usage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+QSGTexture *QSGTexture::removedFromAtlas() const
+{
+ Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
+ return 0;
+}
+
+/*!
+ Returns weither this texture is part of an atlas or not.
+
+ The default implementation returns false.
+ */
+bool QSGTexture::isAtlasTexture() const
+{
+ return false;
+}
+
+/*!
+ \fn int QSGTexture::textureId() const
+
+ Returns the OpenGL texture id for this texture.
+
+ The default value is 0, indicating that it is an invalid texture id.
+
+ The function should at all times return the correct texture id.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+
+
+/*!
+ Returns the rectangle inside textureSize() that this texture
+ represents in normalized coordinates.
+
+ The default implementation returns a rect at position (0, 0) with
+ width and height of 1.
+ */
+QRectF QSGTexture::textureSubRect() const
+{
+ return QRectF(0, 0, 1, 1);
+}
+
+/*!
+ \fn bool QSGTexture::hasMipmaps() const
+
+ Returns true if the texture data contains mipmap levels.
+ */
+
+
+/*!
+ Sets the mipmap sampling mode to be used for the upcoming bind() call to \a filter.
+
+ Setting the mipmap filtering has no effect it the texture does not have mipmaps.
+
+ \sa hasMipmaps()
+ */
+void QSGTexture::setMipmapFiltering(Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->mipmapMode != (uint) filter) {
+ d->mipmapMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+/*!
+ Returns whether mipmapping should be used when sampling from this texture.
+ */
+QSGTexture::Filtering QSGTexture::mipmapFiltering() const
+{
+ return (QSGTexture::Filtering) d_func()->mipmapMode;
+}
+
+
+/*!
+ Sets the sampling mode to be used for the upcoming bind() call to \a filter.
+ */
+void QSGTexture::setFiltering(QSGTexture::Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->filterMode != (uint) filter) {
+ d->filterMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+QSGTexture::Filtering QSGTexture::filtering() const
+{
+ return (QSGTexture::Filtering) d_func()->filterMode;
+}
+
+
+
+/*!
+ Sets the horizontal wrap mode to be used for the upcoming bind() call to \a hwrap
+ */
+
+void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) hwrap != d->horizontalWrap) {
+ d->horizontalWrap = hwrap;
+ d->wrapChanged = true;
+ }
+}
+
+QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->horizontalWrap;
+}
+
+
+
+void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) vwrap != d->verticalWrap) {
+ d->verticalWrap = vwrap;
+ d->wrapChanged = true;
+ }
+}
+
+QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->verticalWrap;
+}
+
+
+/*!
+ Update the texture state to match the filtering, mipmap and wrap options
+ currently set.
+
+ If \a force is true, all properties will be updated regardless of weither
+ they have changed or not.
+ */
+void QSGTexture::updateBindOptions(bool force)
+{
+ Q_D(QSGTexture);
+ if (force || d->filteringChanged) {
+ bool linear = d->filterMode == Linear;
+ GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
+ GLint magFilter = linear ? GL_LINEAR : GL_NEAREST;
+
+ if (hasMipmaps()) {
+ if (d->mipmapMode == Nearest)
+ minFilter = linear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST;
+ else if (d->mipmapMode == Linear)
+ minFilter = linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR;
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+ d->filteringChanged = false;
+ }
+
+ if (force || d->wrapChanged) {
+#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2)
+ if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) {
+ bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ QSize size = textureSize();
+ bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (!npotSupported && isNpot)
+ qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
+ }
+#endif
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, d->horizontalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, d->verticalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
+ d->wrapChanged = false;
+ }
+}
+
+QSGPlainTexture::QSGPlainTexture()
+ : QSGTexture()
+ , m_texture_id(0)
+ , m_has_alpha(false)
+ , m_has_mipmaps(false)
+ , m_dirty_bind_options(false)
+ , m_owns_texture(true)
+ , m_mipmaps_generated(false)
+{
+}
+
+
+QSGPlainTexture::~QSGPlainTexture()
+{
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+}
+
+#ifdef QT_OPENGL_ES
+static void swizzleBGRAToRGBA(QImage *image)
+{
+ const int width = image->width();
+ const int height = image->height();
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) image->scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+}
+#endif
+
+void QSGPlainTexture::setImage(const QImage &image)
+{
+ m_image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+#ifdef QT_OPENGL_ES
+ swizzleBGRAToRGBA(&m_image);
+#endif
+
+ m_texture_size = image.size();
+ m_has_alpha = image.hasAlphaChannel();
+ m_dirty_texture = true;
+ m_dirty_bind_options = true;
+ }
+
+int QSGPlainTexture::textureId() const
+{
+ if (m_dirty_texture) {
+ if (m_image.isNull()) {
+ // The actual texture and id will be updated/deleted in a later bind()
+ // or ~QSGPlainTexture so just keep it minimal here.
+ return 0;
+ } else {
+ // Generate a texture id for use later and return it.
+ glGenTextures(1, &const_cast<QSGPlainTexture *>(this)->m_texture_id);
+ return m_texture_id;
+ }
+ }
+ return m_texture_id;
+}
+
+void QSGPlainTexture::setTextureId(int id)
+{
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+
+ m_texture_id = id;
+ m_dirty_texture = false;
+ m_dirty_bind_options = true;
+ m_image = QImage();
+ m_mipmaps_generated = false;
+}
+
+void QSGPlainTexture::setHasMipmaps(bool mm)
+{
+ m_has_mipmaps = mm;
+ m_mipmaps_generated = false;
+}
+
+
+void QSGPlainTexture::bind()
+{
+ if (!m_dirty_texture) {
+ glBindTexture(GL_TEXTURE_2D, m_texture_id);
+ if (m_has_mipmaps && !m_mipmaps_generated) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+ updateBindOptions(m_dirty_bind_options);
+ m_dirty_bind_options = false;
+ return;
+ }
+
+ m_dirty_texture = false;
+
+
+ if (m_image.isNull()) {
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+ m_texture_id = 0;
+ m_texture_size = QSize();
+ m_has_mipmaps = false;
+ m_has_alpha = false;
+ return;
+ }
+
+ if (m_texture_id == 0)
+ glGenTextures(1, &m_texture_id);
+ glBindTexture(GL_TEXTURE_2D, m_texture_id);
+
+ // ### TODO: check for out-of-memory situations...
+ int w = m_image.width();
+ int h = m_image.height();
+
+#ifdef QT_OPENGL_ES
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_image.constBits());
+#else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_image.constBits());
+#endif
+
+ if (m_has_mipmaps) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+
+ m_texture_size = QSize(w, h);
+ m_texture_rect = QRectF(0, 0, 1, 1);
+
+ updateBindOptions(m_dirty_bind_options);
+ m_dirty_bind_options = false;
+}
+
+
+/*!
+ \class QSGDynamicTexture
+ \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
+ such as content that is rendered to FBO's.
+
+ To update the content of the texture, call updateTexture() explicitly. Simply calling bind()
+ will not update the texture.
+ */
+
+
+/*!
+ \fn bool QSGDynamicTexture::updateTexture()
+
+ Call this function to explicitely update the dynamic texture. Calling bind() will bind
+ the content that was previously updated.
+
+ The function returns true if the texture was changed as a resul of the update; otherwise
+ returns false.
+ */
+
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h
new file mode 100644
index 0000000000..6fdab9f401
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGTEXTURE_H
+#define QSGTEXTURE_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QObject>
+#include <QImage>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGTexturePrivate;
+class Q_QUICK_EXPORT QSGTexture : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGTexture)
+
+public:
+ QSGTexture();
+ ~QSGTexture();
+
+ enum WrapMode {
+ Repeat,
+ ClampToEdge
+ };
+
+ enum Filtering {
+ None,
+ Nearest,
+ Linear
+ };
+
+ virtual int textureId() const = 0;
+ virtual QSize textureSize() const = 0;
+ virtual bool hasAlphaChannel() const = 0;
+ virtual bool hasMipmaps() const = 0;
+
+ virtual QRectF textureSubRect() const;
+
+ virtual bool isAtlasTexture() const;
+
+ virtual QSGTexture *removedFromAtlas() const;
+
+ virtual void bind() = 0;
+ void updateBindOptions(bool force = false);
+
+ void setMipmapFiltering(Filtering filter);
+ QSGTexture::Filtering mipmapFiltering() const;
+
+ void setFiltering(Filtering filter);
+ QSGTexture::Filtering filtering() const;
+
+ void setHorizontalWrapMode(WrapMode hwrap);
+ QSGTexture::WrapMode horizontalWrapMode() const;
+
+ void setVerticalWrapMode(WrapMode vwrap);
+ QSGTexture::WrapMode verticalWrapMode() const;
+
+ inline QRectF convertToNormalizedSourceRect(const QRectF &rect) const;
+
+protected:
+ QSGTexture(QSGTexturePrivate &dd);
+};
+
+QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
+{
+ QSize s = textureSize();
+ QRectF r = textureSubRect();
+
+ qreal sx = r.width() / s.width();
+ qreal sy = r.height() / s.height();
+
+ return QRectF(r.x() + rect.x() * sx,
+ r.y() + rect.y() * sy,
+ rect.width() * sx,
+ rect.height() * sy);
+}
+
+
+class Q_QUICK_EXPORT QSGDynamicTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ virtual bool updateTexture() = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
new file mode 100644
index 0000000000..e1d6dd0e32
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGTEXTURE_P_H
+#define QSGTEXTURE_P_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <private/qobject_p.h>
+
+#include <QtGui/qopengl.h>
+
+#include "qsgtexture.h"
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGTexturePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGTexture);
+public:
+ QSGTexturePrivate();
+
+ uint wrapChanged : 1;
+ uint filteringChanged : 1;
+
+ uint horizontalWrap : 1;
+ uint verticalWrap : 1;
+ uint mipmapMode : 2;
+ uint filterMode : 2;
+};
+
+class Q_QUICK_EXPORT QSGPlainTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ QSGPlainTexture();
+ virtual ~QSGPlainTexture();
+
+ void setOwnsTexture(bool owns) { m_owns_texture = owns; }
+ bool ownsTexture() const { return m_owns_texture; }
+
+ void setTextureId(int id);
+ int textureId() const;
+ void setTextureSize(const QSize &size) { m_texture_size = size; }
+ QSize textureSize() const { return m_texture_size; }
+
+ void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
+ bool hasAlphaChannel() const { return m_has_alpha; }
+
+ void setHasMipmaps(bool mm);
+ bool hasMipmaps() const { return m_has_mipmaps; }
+
+ void setImage(const QImage &image);
+ const QImage &image() { return m_image; }
+
+ virtual void bind();
+
+ static QSGPlainTexture *fromImage(const QImage &image) {
+ QSGPlainTexture *t = new QSGPlainTexture();
+ t->setImage(image);
+ return t;
+ }
+
+protected:
+ QImage m_image;
+
+ GLuint m_texture_id;
+ QSize m_texture_size;
+ QRectF m_texture_rect;
+
+ uint m_has_alpha : 1;
+ uint m_has_mipmaps : 1;
+ uint m_dirty_texture : 1;
+ uint m_dirty_bind_options : 1;
+ uint m_owns_texture : 1;
+ uint m_mipmaps_generated : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGTEXTURE_P_H
diff --git a/src/declarative/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index 0bee81993c..0bee81993c 100644
--- a/src/declarative/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.h b/src/quick/scenegraph/util/qsgtexturematerial.h
new file mode 100644
index 0000000000..b2b3ce6374
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexturematerial.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 TEXTUREMATERIAL_H
+#define TEXTUREMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+#include <QtQuick/qsgtexture.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGOpaqueTextureMaterial : public QSGMaterial
+{
+public:
+ QSGOpaqueTextureMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const { return m_texture; }
+
+ void setMipmapFiltering(QSGTexture::Filtering filtering) { m_mipmap_filtering = filtering; }
+ QSGTexture::Filtering mipmapFiltering() const { return (QSGTexture::Filtering) m_mipmap_filtering; }
+
+ void setFiltering(QSGTexture::Filtering filtering) { m_filtering = filtering; }
+ QSGTexture::Filtering filtering() const { return (QSGTexture::Filtering) m_filtering; }
+
+ void setHorizontalWrapMode(QSGTexture::WrapMode mode) { m_horizontal_wrap = mode; }
+ QSGTexture::WrapMode horizontalWrapMode() const { return (QSGTexture::WrapMode) m_horizontal_wrap; }
+
+ void setVerticalWrapMode(QSGTexture::WrapMode mode) { m_vertical_wrap = mode; }
+ QSGTexture::WrapMode verticalWrapMode() const { return (QSGTexture::WrapMode) m_vertical_wrap; }
+
+protected:
+ QSGTexture *m_texture;
+
+ uint m_filtering: 2;
+ uint m_mipmap_filtering: 2;
+ uint m_horizontal_wrap : 1;
+ uint m_vertical_wrap: 1;
+
+ uint m_reserved : 26;
+};
+
+
+class Q_QUICK_EXPORT QSGTextureMaterial : public QSGOpaqueTextureMaterial
+{
+public:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // TEXTUREMATERIAL_H
diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h
new file mode 100644
index 0000000000..0ab552f4e9
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 TEXTUREMATERIAL_P_H
+#define TEXTUREMATERIAL_P_H
+
+#include "qsgtexturematerial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGOpaqueTextureMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+protected:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGTEXTUREMATERIAL_P_H
diff --git a/src/declarative/scenegraph/util/qsgtextureprovider.cpp b/src/quick/scenegraph/util/qsgtextureprovider.cpp
index 10faf2e5d4..10faf2e5d4 100644
--- a/src/declarative/scenegraph/util/qsgtextureprovider.cpp
+++ b/src/quick/scenegraph/util/qsgtextureprovider.cpp
diff --git a/src/quick/scenegraph/util/qsgtextureprovider_p.h b/src/quick/scenegraph/util/qsgtextureprovider_p.h
new file mode 100644
index 0000000000..bc4ffec03d
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtextureprovider_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QSGTEXTUREPROVIDER_H
+#define QSGTEXTUREPROVIDER_H
+
+#include "qsgtexture.h"
+#include "qobject.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGTextureProvider : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QSGTexture *texture() const = 0;
+
+Q_SIGNALS:
+ void textureChanged();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
new file mode 100644
index 0000000000..8c6996642b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qsgvertexcolormaterial.h"
+
+#include <qopenglshaderprogram.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVertexColorMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+ int m_opacity_id;
+};
+
+QSGMaterialType QSGVertexColorMaterialShader::type;
+
+void QSGVertexColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+{
+ if (!(newEffect->flags() & QSGMaterial::Blending) || state.isOpacityDirty())
+ program()->setUniformValue(m_opacity_id, state.opacity());
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+char const *const *QSGVertexColorMaterialShader::attributeNames() const
+{
+ static const char *const attr[] = { "vertexCoord", "vertexColor", 0 };
+ return attr;
+}
+
+void QSGVertexColorMaterialShader::initialize()
+{
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_opacity_id = program()->uniformLocation("opacity");
+}
+
+const char *QSGVertexColorMaterialShader::vertexShader() const {
+ return
+ "attribute highp vec4 vertexCoord; \n"
+ "attribute highp vec4 vertexColor; \n"
+ "uniform highp mat4 matrix; \n"
+ "uniform highp float opacity; \n"
+ "varying lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_Position = matrix * vertexCoord; \n"
+ " color = vertexColor * opacity; \n"
+ "}";
+}
+
+const char *QSGVertexColorMaterialShader::fragmentShader() const {
+ return
+ "varying lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "}";
+}
+
+
+
+/*!
+ \class QSGVertexColorMaterial
+ \brief The QSGVertexColorMaterial class provides a convenient way of rendering per-vertex
+ colored geometry in the scene graph.
+
+ \inmodule QtQuick
+
+ The vertex color material will give each vertex in a geometry a color. Pixels between
+ vertices will be linearly interpolated. The colors can contain transparency.
+
+ The geometry to be rendered with vertex color must have the following layout. Attribute
+ position 0 must contain vertices. Attribute position 1 must contain colors, a tuple of
+ 4 values with RGBA layout. Both floats in the range of 0 to 1 and unsigned bytes in
+ the range 0 to 255 are valid for the color values. The
+ QSGGeometry::defaultAttributes_ColoredPoint2D() constructs an attribute set
+ compatible with this material.
+
+ The vertex color material respects both current opacity and current matrix when
+ updating it's rendering state.
+ */
+
+
+QSGVertexColorMaterial::QSGVertexColorMaterial()
+{
+ setFlag(Blending, true);
+}
+
+
+/*!
+ int QSGVertexColorMaterial::compare() const
+
+ As the vertex color material has all its state in the vertex attributes,
+ all materials will be equal.
+
+ \internal
+ */
+
+int QSGVertexColorMaterial::compare(const QSGMaterial * /* other */) const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ */
+
+QSGMaterialType *QSGVertexColorMaterial::type() const
+{
+ return &QSGVertexColorMaterialShader::type;
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialShader *QSGVertexColorMaterial::createShader() const
+{
+ return new QSGVertexColorMaterialShader;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.h b/src/quick/scenegraph/util/qsgvertexcolormaterial.h
new file mode 100644
index 0000000000..1d3b5a82e0
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 VERTEXCOLORMATERIAL_H
+#define VERTEXCOLORMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGVertexColorMaterial : public QSGMaterial
+{
+public:
+ QSGVertexColorMaterial();
+
+ int compare(const QSGMaterial *other) const;
+
+protected:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // VERTEXCOLORMATERIAL_H
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/quick/util/qdeclarativeanimation.cpp
index 8c21d11037..8c21d11037 100644
--- a/src/declarative/util/qdeclarativeanimation.cpp
+++ b/src/quick/util/qdeclarativeanimation.cpp
diff --git a/src/quick/util/qdeclarativeanimation_p.h b/src/quick/util/qdeclarativeanimation_p.h
new file mode 100644
index 0000000000..6c8f552888
--- /dev/null
+++ b/src/quick/util/qdeclarativeanimation_p.h
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEANIMATION_H
+#define QDECLARATIVEANIMATION_H
+
+#include "qdeclarativestate_p.h"
+#include <QtGui/qvector3d.h>
+
+#include <qdeclarativepropertyvaluesource.h>
+#include <qdeclarative.h>
+#include <qdeclarativescriptstring.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/QAbstractAnimation>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAbstractAnimationPrivate;
+class QDeclarativeAnimationGroup;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeAbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeAbstractAnimation)
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_INTERFACES(QDeclarativePropertyValueSource)
+ Q_ENUMS(Loops)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged)
+ Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopCountChanged)
+ Q_CLASSINFO("DefaultMethod", "start()")
+
+public:
+ QDeclarativeAbstractAnimation(QObject *parent=0);
+ virtual ~QDeclarativeAbstractAnimation();
+
+ enum Loops { Infinite = -2 };
+
+ bool isRunning() const;
+ void setRunning(bool);
+ bool isPaused() const;
+ void setPaused(bool);
+ bool alwaysRunToEnd() const;
+ void setAlwaysRunToEnd(bool);
+
+ int loops() const;
+ void setLoops(int);
+
+ int currentTime();
+ void setCurrentTime(int);
+
+ QDeclarativeAnimationGroup *group() const;
+ void setGroup(QDeclarativeAnimationGroup *);
+
+ void setDefaultTarget(const QDeclarativeProperty &);
+ void setDisableUserControl();
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void started();
+ void completed();
+ void runningChanged(bool);
+ void pausedChanged(bool);
+ void alwaysRunToEndChanged(bool);
+ void loopCountChanged(int);
+
+public Q_SLOTS:
+ void restart();
+ void start();
+ void pause();
+ void resume();
+ void stop();
+ void complete();
+
+protected:
+ QDeclarativeAbstractAnimation(QDeclarativeAbstractAnimationPrivate &dd, QObject *parent);
+
+public:
+ enum TransitionDirection { Forward, Backward };
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation() = 0;
+
+private Q_SLOTS:
+ void timelineComplete();
+ void componentFinalized();
+private:
+ virtual void setTarget(const QDeclarativeProperty &);
+ void notifyRunningChanged(bool running);
+ friend class QDeclarativeBehavior;
+
+
+};
+
+class QDeclarativePauseAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativePauseAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePauseAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+
+public:
+ QDeclarativePauseAnimation(QObject *parent=0);
+ virtual ~QDeclarativePauseAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+Q_SIGNALS:
+ void durationChanged(int);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarativeScriptActionPrivate;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeScriptAction : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeScriptAction)
+
+ Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName)
+
+public:
+ QDeclarativeScriptAction(QObject *parent=0);
+ virtual ~QDeclarativeScriptAction();
+
+ QDeclarativeScriptString script() const;
+ void setScript(const QDeclarativeScriptString &);
+
+ QString stateChangeScriptName() const;
+ void setStateChangeScriptName(const QString &);
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarativePropertyActionPrivate;
+class QDeclarativePropertyAction : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyAction)
+
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ QDeclarativePropertyAction(QObject *parent=0);
+ virtual ~QDeclarativePropertyAction();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QDeclarativeListProperty<QObject> targets();
+ QDeclarativeListProperty<QObject> exclude();
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &);
+ void propertiesChanged(const QString &);
+ void targetChanged();
+ void propertyChanged();
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarativePropertyAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativePropertyAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
+
+public:
+ QDeclarativePropertyAnimation(QObject *parent=0);
+ virtual ~QDeclarativePropertyAnimation();
+
+ virtual int duration() const;
+ virtual void setDuration(int);
+
+ QVariant from() const;
+ void setFrom(const QVariant &);
+
+ QVariant to() const;
+ void setTo(const QVariant &);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QDeclarativeListProperty<QObject> targets();
+ QDeclarativeListProperty<QObject> exclude();
+
+protected:
+ QDeclarativePropertyAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent);
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(QVariant);
+ void toChanged(QVariant);
+ void easingChanged(const QEasingCurve &);
+ void propertiesChanged(const QString &);
+ void targetChanged();
+ void propertyChanged();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeColorAnimation : public QDeclarativePropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
+ Q_PROPERTY(QColor from READ from WRITE setFrom)
+ Q_PROPERTY(QColor to READ to WRITE setTo)
+
+public:
+ QDeclarativeColorAnimation(QObject *parent=0);
+ virtual ~QDeclarativeColorAnimation();
+
+ QColor from() const;
+ void setFrom(const QColor &);
+
+ QColor to() const;
+ void setTo(const QColor &);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeNumberAnimation : public QDeclarativePropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
+
+ Q_PROPERTY(qreal from READ from WRITE setFrom)
+ Q_PROPERTY(qreal to READ to WRITE setTo)
+
+public:
+ QDeclarativeNumberAnimation(QObject *parent=0);
+ virtual ~QDeclarativeNumberAnimation();
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+protected:
+ QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent);
+
+private:
+ void init();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation)
+
+ Q_PROPERTY(QVector3D from READ from WRITE setFrom)
+ Q_PROPERTY(QVector3D to READ to WRITE setTo)
+
+public:
+ QDeclarativeVector3dAnimation(QObject *parent=0);
+ virtual ~QDeclarativeVector3dAnimation();
+
+ QVector3D from() const;
+ void setFrom(QVector3D);
+
+ QVector3D to() const;
+ void setTo(QVector3D);
+};
+
+class QDeclarativeRotationAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeRotationAnimation : public QDeclarativePropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeRotationAnimation)
+ Q_ENUMS(RotationDirection)
+
+ Q_PROPERTY(qreal from READ from WRITE setFrom)
+ Q_PROPERTY(qreal to READ to WRITE setTo)
+ Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+public:
+ QDeclarativeRotationAnimation(QObject *parent=0);
+ virtual ~QDeclarativeRotationAnimation();
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+ enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ RotationDirection direction() const;
+ void setDirection(RotationDirection direction);
+
+Q_SIGNALS:
+ void directionChanged();
+};
+
+class QDeclarativeAnimationGroupPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeAnimationGroup : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
+
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations)
+
+public:
+ QDeclarativeAnimationGroup(QObject *parent);
+ virtual ~QDeclarativeAnimationGroup();
+
+ QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations();
+ friend class QDeclarativeAbstractAnimation;
+
+protected:
+ QDeclarativeAnimationGroup(QDeclarativeAnimationGroupPrivate &dd, QObject *parent);
+};
+
+class QDeclarativeSequentialAnimation : public QDeclarativeAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
+
+public:
+ QDeclarativeSequentialAnimation(QObject *parent=0);
+ virtual ~QDeclarativeSequentialAnimation();
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarativeParallelAnimation : public QDeclarativeAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup)
+
+public:
+ QDeclarativeParallelAnimation(QObject *parent=0);
+ virtual ~QDeclarativeParallelAnimation();
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeAbstractAnimation)
+QML_DECLARE_TYPE(QDeclarativePauseAnimation)
+QML_DECLARE_TYPE(QDeclarativeScriptAction)
+QML_DECLARE_TYPE(QDeclarativePropertyAction)
+QML_DECLARE_TYPE(QDeclarativePropertyAnimation)
+QML_DECLARE_TYPE(QDeclarativeColorAnimation)
+QML_DECLARE_TYPE(QDeclarativeNumberAnimation)
+QML_DECLARE_TYPE(QDeclarativeSequentialAnimation)
+QML_DECLARE_TYPE(QDeclarativeParallelAnimation)
+QML_DECLARE_TYPE(QDeclarativeVector3dAnimation)
+QML_DECLARE_TYPE(QDeclarativeRotationAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEANIMATION_H
diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/quick/util/qdeclarativeanimation_p_p.h
index dfeb767877..dfeb767877 100644
--- a/src/declarative/util/qdeclarativeanimation_p_p.h
+++ b/src/quick/util/qdeclarativeanimation_p_p.h
diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/quick/util/qdeclarativebehavior.cpp
index 6fb36197ef..6fb36197ef 100644
--- a/src/declarative/util/qdeclarativebehavior.cpp
+++ b/src/quick/util/qdeclarativebehavior.cpp
diff --git a/src/quick/util/qdeclarativebehavior_p.h b/src/quick/util/qdeclarativebehavior_p.h
new file mode 100644
index 0000000000..1f8873de22
--- /dev/null
+++ b/src/quick/util/qdeclarativebehavior_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEBEHAVIOR_H
+#define QDECLARATIVEBEHAVIOR_H
+
+#include <private/qtquickglobal_p.h>
+
+#include <private/qdeclarativepropertyvalueinterceptor_p.h>
+#include <qdeclarative.h>
+#include <QtCore/QAbstractAnimation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAbstractAnimation;
+class QDeclarativeBehaviorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeBehavior : public QObject, public QDeclarativePropertyValueInterceptor
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeBehavior)
+
+ Q_INTERFACES(QDeclarativePropertyValueInterceptor)
+ Q_CLASSINFO("DefaultProperty", "animation")
+ Q_PROPERTY(QDeclarativeAbstractAnimation *animation READ animation WRITE setAnimation)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_CLASSINFO("DeferredPropertyNames", "animation")
+
+public:
+ QDeclarativeBehavior(QObject *parent=0);
+ ~QDeclarativeBehavior();
+
+ virtual void setTarget(const QDeclarativeProperty &);
+ virtual void write(const QVariant &value);
+
+ QDeclarativeAbstractAnimation *animation();
+ void setAnimation(QDeclarativeAbstractAnimation *);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+Q_SIGNALS:
+ void enabledChanged();
+
+private Q_SLOTS:
+ void componentFinalized();
+ void qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeBehavior)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEBEHAVIOR_H
diff --git a/src/declarative/util/qdeclarativebind.cpp b/src/quick/util/qdeclarativebind.cpp
index 20b2caa582..20b2caa582 100644
--- a/src/declarative/util/qdeclarativebind.cpp
+++ b/src/quick/util/qdeclarativebind.cpp
diff --git a/src/quick/util/qdeclarativebind_p.h b/src/quick/util/qdeclarativebind_p.h
new file mode 100644
index 0000000000..dfb6103a37
--- /dev/null
+++ b/src/quick/util/qdeclarativebind_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEBIND_H
+#define QDECLARATIVEBIND_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeBindPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeBind : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeBind)
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_INTERFACES(QDeclarativePropertyValueSource)
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
+
+public:
+ QDeclarativeBind(QObject *parent=0);
+ ~QDeclarativeBind();
+
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+protected:
+ virtual void setTarget(const QDeclarativeProperty &);
+ virtual void classBegin();
+ virtual void componentComplete();
+
+private:
+ void eval();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeBind)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qdeclarativechangeset.cpp b/src/quick/util/qdeclarativechangeset.cpp
index 81cbe3e10a..81cbe3e10a 100644
--- a/src/declarative/util/qdeclarativechangeset.cpp
+++ b/src/quick/util/qdeclarativechangeset.cpp
diff --git a/src/declarative/util/qdeclarativechangeset_p.h b/src/quick/util/qdeclarativechangeset_p.h
index b7554da503..b7554da503 100644
--- a/src/declarative/util/qdeclarativechangeset_p.h
+++ b/src/quick/util/qdeclarativechangeset_p.h
diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/quick/util/qdeclarativeconnections.cpp
index ee2c6edcc5..ee2c6edcc5 100644
--- a/src/declarative/util/qdeclarativeconnections.cpp
+++ b/src/quick/util/qdeclarativeconnections.cpp
diff --git a/src/quick/util/qdeclarativeconnections_p.h b/src/quick/util/qdeclarativeconnections_p.h
new file mode 100644
index 0000000000..bab29e5521
--- /dev/null
+++ b/src/quick/util/qdeclarativeconnections_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVECONNECTIONS_H
+#define QDECLARATIVECONNECTIONS_H
+
+#include <qdeclarative.h>
+#include <private/qdeclarativecustomparser_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeBoundSignal;
+class QDeclarativeContext;
+class QDeclarativeConnectionsPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeConnections : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeConnections)
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
+
+public:
+ QDeclarativeConnections(QObject *parent=0);
+ ~QDeclarativeConnections();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ bool ignoreUnknownSignals() const;
+ void setIgnoreUnknownSignals(bool ignore);
+
+Q_SIGNALS:
+ void targetChanged();
+
+private:
+ void connectSignals();
+ void classBegin();
+ void componentComplete();
+};
+
+class QDeclarativeConnectionsParser : public QDeclarativeCustomParser
+{
+public:
+ virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeConnections)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/quick/util/qdeclarativefontloader.cpp
index e95bd11a7b..e95bd11a7b 100644
--- a/src/declarative/util/qdeclarativefontloader.cpp
+++ b/src/quick/util/qdeclarativefontloader.cpp
diff --git a/src/quick/util/qdeclarativefontloader_p.h b/src/quick/util/qdeclarativefontloader_p.h
new file mode 100644
index 0000000000..2511908a8e
--- /dev/null
+++ b/src/quick/util/qdeclarativefontloader_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEFONTLOADER_H
+#define QDECLARATIVEFONTLOADER_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeFontLoaderPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeFontLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeFontLoader)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+public:
+ enum Status { Null = 0, Ready, Loading, Error };
+
+ QDeclarativeFontLoader(QObject *parent = 0);
+ ~QDeclarativeFontLoader();
+
+ QUrl source() const;
+ void setSource(const QUrl &url);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ Status status() const;
+
+private Q_SLOTS:
+ void updateFontInfo(const QString&, QDeclarativeFontLoader::Status);
+
+Q_SIGNALS:
+ void sourceChanged();
+ void nameChanged();
+ void statusChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFontLoader)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFONTLOADER_H
+
diff --git a/src/declarative/util/qdeclarativelistaccessor.cpp b/src/quick/util/qdeclarativelistaccessor.cpp
index 0063514e59..0063514e59 100644
--- a/src/declarative/util/qdeclarativelistaccessor.cpp
+++ b/src/quick/util/qdeclarativelistaccessor.cpp
diff --git a/src/quick/util/qdeclarativelistaccessor_p.h b/src/quick/util/qdeclarativelistaccessor_p.h
new file mode 100644
index 0000000000..b9fcdd01d2
--- /dev/null
+++ b/src/quick/util/qdeclarativelistaccessor_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVELISTACCESSOR_H
+#define QDECLARATIVELISTACCESSOR_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+class Q_AUTOTEST_EXPORT QDeclarativeListAccessor
+{
+public:
+ QDeclarativeListAccessor();
+ ~QDeclarativeListAccessor();
+
+ QVariant list() const;
+ void setList(const QVariant &, QDeclarativeEngine * = 0);
+
+ bool isValid() const;
+
+ int count() const;
+ QVariant at(int) const;
+
+ enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer };
+ Type type() const { return m_type; }
+
+private:
+ Type m_type;
+ QVariant d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVELISTACCESSOR_H
diff --git a/src/declarative/util/qdeclarativelistcompositor.cpp b/src/quick/util/qdeclarativelistcompositor.cpp
index d73d76e386..d73d76e386 100644
--- a/src/declarative/util/qdeclarativelistcompositor.cpp
+++ b/src/quick/util/qdeclarativelistcompositor.cpp
diff --git a/src/declarative/util/qdeclarativelistcompositor_p.h b/src/quick/util/qdeclarativelistcompositor_p.h
index c808f6fe80..c808f6fe80 100644
--- a/src/declarative/util/qdeclarativelistcompositor_p.h
+++ b/src/quick/util/qdeclarativelistcompositor_p.h
diff --git a/src/declarative/util/qdeclarativepackage.cpp b/src/quick/util/qdeclarativepackage.cpp
index 1d46574f02..1d46574f02 100644
--- a/src/declarative/util/qdeclarativepackage.cpp
+++ b/src/quick/util/qdeclarativepackage.cpp
diff --git a/src/quick/util/qdeclarativepackage_p.h b/src/quick/util/qdeclarativepackage_p.h
new file mode 100644
index 0000000000..76797430ce
--- /dev/null
+++ b/src/quick/util/qdeclarativepackage_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEPACKAGE_H
+#define QDECLARATIVEPACKAGE_H
+
+#include <qdeclarative.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePackagePrivate;
+class QDeclarativePackageAttached;
+class Q_AUTOTEST_EXPORT QDeclarativePackage : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePackage)
+
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data)
+
+public:
+ QDeclarativePackage(QObject *parent=0);
+ virtual ~QDeclarativePackage();
+
+ QDeclarativeListProperty<QObject> data();
+
+ QObject *part(const QString & = QString());
+ bool hasPart(const QString &);
+
+ static QDeclarativePackageAttached *qmlAttachedProperties(QObject *);
+};
+
+class QDeclarativePackageAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+public:
+ QDeclarativePackageAttached(QObject *parent);
+ virtual ~QDeclarativePackageAttached();
+
+ QString name() const;
+ void setName(const QString &n);
+
+ static QHash<QObject *, QDeclarativePackageAttached *> attached;
+private:
+ QString _name;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePackage)
+QML_DECLARE_TYPEINFO(QDeclarativePackage, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPACKAGE_H
diff --git a/src/declarative/util/qdeclarativepath.cpp b/src/quick/util/qdeclarativepath.cpp
index 2ba7c372e2..2ba7c372e2 100644
--- a/src/declarative/util/qdeclarativepath.cpp
+++ b/src/quick/util/qdeclarativepath.cpp
diff --git a/src/quick/util/qdeclarativepath_p.h b/src/quick/util/qdeclarativepath_p.h
new file mode 100644
index 0000000000..afa5b0240e
--- /dev/null
+++ b/src/quick/util/qdeclarativepath_p.h
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEPATH_H
+#define QDECLARATIVEPATH_H
+
+#include <qdeclarative.h>
+
+#include <private/qdeclarativenullablevalue_p_p.h>
+#include <private/qbezier_p.h>
+
+#include <QtCore/QObject>
+#include <QtGui/QPainterPath>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeCurve;
+struct QDeclarativePathData
+{
+ int index;
+ QPointF endPoint;
+ QList<QDeclarativeCurve*> curves;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathElement : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarativePathElement(QObject *parent=0) : QObject(parent) {}
+Q_SIGNALS:
+ void changed();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathAttribute : public QDeclarativePathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+public:
+ QDeclarativePathAttribute(QObject *parent=0) : QDeclarativePathElement(parent), _value(0) {}
+
+
+ QString name() const;
+ void setName(const QString &name);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+Q_SIGNALS:
+ void nameChanged();
+ void valueChanged();
+
+private:
+ QString _name;
+ qreal _value;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeCurve : public QDeclarativePathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
+ Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
+public:
+ QDeclarativeCurve(QObject *parent=0) : QDeclarativePathElement(parent) {}
+
+ qreal x() const;
+ void setX(qreal x);
+ bool hasX();
+
+ qreal y() const;
+ void setY(qreal y);
+ bool hasY();
+
+ qreal relativeX() const;
+ void setRelativeX(qreal x);
+ bool hasRelativeX();
+
+ qreal relativeY() const;
+ void setRelativeY(qreal y);
+ bool hasRelativeY();
+
+ virtual void addToPath(QPainterPath &, const QDeclarativePathData &) {}
+
+Q_SIGNALS:
+ void xChanged();
+ void yChanged();
+ void relativeXChanged();
+ void relativeYChanged();
+
+private:
+ QDeclarativeNullableValue<qreal> _x;
+ QDeclarativeNullableValue<qreal> _y;
+ QDeclarativeNullableValue<qreal> _relativeX;
+ QDeclarativeNullableValue<qreal> _relativeY;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathLine : public QDeclarativeCurve
+{
+ Q_OBJECT
+public:
+ QDeclarativePathLine(QObject *parent=0) : QDeclarativeCurve(parent) {}
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathQuad : public QDeclarativeCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
+ Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
+ Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
+ Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
+public:
+ QDeclarativePathQuad(QObject *parent=0) : QDeclarativeCurve(parent), _controlX(0), _controlY(0) {}
+
+ qreal controlX() const;
+ void setControlX(qreal x);
+
+ qreal controlY() const;
+ void setControlY(qreal y);
+
+ qreal relativeControlX() const;
+ void setRelativeControlX(qreal x);
+ bool hasRelativeControlX();
+
+ qreal relativeControlY() const;
+ void setRelativeControlY(qreal y);
+ bool hasRelativeControlY();
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void controlXChanged();
+ void controlYChanged();
+ void relativeControlXChanged();
+ void relativeControlYChanged();
+
+private:
+ qreal _controlX;
+ qreal _controlY;
+ QDeclarativeNullableValue<qreal> _relativeControlX;
+ QDeclarativeNullableValue<qreal> _relativeControlY;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathCubic : public QDeclarativeCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)
+ Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
+ Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
+ Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
+ Q_PROPERTY(qreal relativeControl1X READ relativeControl1X WRITE setRelativeControl1X NOTIFY relativeControl1XChanged)
+ Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
+ Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
+ Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
+public:
+ QDeclarativePathCubic(QObject *parent=0) : QDeclarativeCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
+
+ qreal control1X() const;
+ void setControl1X(qreal x);
+
+ qreal control1Y() const;
+ void setControl1Y(qreal y);
+
+ qreal control2X() const;
+ void setControl2X(qreal x);
+
+ qreal control2Y() const;
+ void setControl2Y(qreal y);
+
+ qreal relativeControl1X() const;
+ void setRelativeControl1X(qreal x);
+ bool hasRelativeControl1X();
+
+ qreal relativeControl1Y() const;
+ void setRelativeControl1Y(qreal y);
+ bool hasRelativeControl1Y();
+
+ qreal relativeControl2X() const;
+ void setRelativeControl2X(qreal x);
+ bool hasRelativeControl2X();
+
+ qreal relativeControl2Y() const;
+ void setRelativeControl2Y(qreal y);
+ bool hasRelativeControl2Y();
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void control1XChanged();
+ void control1YChanged();
+ void control2XChanged();
+ void control2YChanged();
+ void relativeControl1XChanged();
+ void relativeControl1YChanged();
+ void relativeControl2XChanged();
+ void relativeControl2YChanged();
+
+private:
+ qreal _control1X;
+ qreal _control1Y;
+ qreal _control2X;
+ qreal _control2Y;
+ QDeclarativeNullableValue<qreal> _relativeControl1X;
+ QDeclarativeNullableValue<qreal> _relativeControl1Y;
+ QDeclarativeNullableValue<qreal> _relativeControl2X;
+ QDeclarativeNullableValue<qreal> _relativeControl2Y;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathCatmullRomCurve : public QDeclarativeCurve
+{
+ Q_OBJECT
+public:
+ QDeclarativePathCatmullRomCurve(QObject *parent=0) : QDeclarativeCurve(parent) {}
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathArc : public QDeclarativeCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
+ Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
+ Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
+ Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+public:
+ QDeclarativePathArc(QObject *parent=0)
+ : QDeclarativeCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
+
+ enum ArcDirection { Clockwise, Counterclockwise };
+ Q_ENUMS(ArcDirection)
+
+ qreal radiusX() const;
+ void setRadiusX(qreal);
+
+ qreal radiusY() const;
+ void setRadiusY(qreal);
+
+ bool useLargeArc() const;
+ void setUseLargeArc(bool);
+
+ ArcDirection direction() const;
+ void setDirection(ArcDirection direction);
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void radiusXChanged();
+ void radiusYChanged();
+ void useLargeArcChanged();
+ void directionChanged();
+
+private:
+ qreal _radiusX;
+ qreal _radiusY;
+ bool _useLargeArc;
+ ArcDirection _direction;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathSvg : public QDeclarativeCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
+public:
+ QDeclarativePathSvg(QObject *parent=0) : QDeclarativeCurve(parent) {}
+
+ QString path() const;
+ void setPath(const QString &path);
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void pathChanged();
+
+private:
+ QString _path;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathPercent : public QDeclarativePathElement
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+public:
+ QDeclarativePathPercent(QObject *parent=0) : QDeclarativePathElement(parent) {}
+
+ qreal value() const;
+ void setValue(qreal value);
+
+signals:
+ void valueChanged();
+
+private:
+ qreal _value;
+};
+
+struct QDeclarativeCachedBezier
+{
+ QDeclarativeCachedBezier() : isValid(false) {}
+ QBezier bezier;
+ int element;
+ qreal bezLength;
+ qreal currLength;
+ qreal p;
+ bool isValid;
+};
+
+class QDeclarativePathPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativePath : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativePathElement> pathElements READ pathElements)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
+ Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
+ Q_CLASSINFO("DefaultProperty", "pathElements")
+ Q_INTERFACES(QDeclarativeParserStatus)
+public:
+ QDeclarativePath(QObject *parent=0);
+ ~QDeclarativePath();
+
+ QDeclarativeListProperty<QDeclarativePathElement> pathElements();
+
+ qreal startX() const;
+ void setStartX(qreal x);
+ bool hasStartX() const;
+
+ qreal startY() const;
+ void setStartY(qreal y);
+ bool hasStartY() const;
+
+ bool isClosed() const;
+ bool hasEnd() const;
+
+ QPainterPath path() const;
+ QStringList attributes() const;
+ qreal attributeAt(const QString &, qreal) const;
+ QPointF pointAt(qreal) const;
+ QPointF sequentialPointAt(qreal p, qreal *angle = 0) const;
+
+Q_SIGNALS:
+ void changed();
+ void startXChanged();
+ void startYChanged();
+
+protected:
+ virtual void componentComplete();
+ virtual void classBegin();
+
+private Q_SLOTS:
+ void processPath();
+
+private:
+ struct AttributePoint {
+ AttributePoint() : percent(0), scale(1), origpercent(0) {}
+ AttributePoint(const AttributePoint &other)
+ : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
+ AttributePoint &operator=(const AttributePoint &other) {
+ percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
+ }
+ qreal percent; //massaged percent along the painter path
+ qreal scale;
+ qreal origpercent; //'real' percent along the painter path
+ QHash<QString, qreal> values;
+ };
+
+ void interpolate(int idx, const QString &name, qreal value);
+ void endpoint(const QString &name);
+ void createPointCache() const;
+
+ static void interpolate(QList<AttributePoint> &points, int idx, const QString &name, qreal value);
+ static void endpoint(QList<AttributePoint> &attributePoints, const QString &name);
+ static QPointF forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
+ static QPointF backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
+
+private:
+ Q_DISABLE_COPY(QDeclarativePath)
+ Q_DECLARE_PRIVATE(QDeclarativePath)
+ friend class QQuickPathAnimationUpdater;
+
+public:
+ QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = 0);
+ static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePathElement)
+QML_DECLARE_TYPE(QDeclarativePathAttribute)
+QML_DECLARE_TYPE(QDeclarativeCurve)
+QML_DECLARE_TYPE(QDeclarativePathLine)
+QML_DECLARE_TYPE(QDeclarativePathQuad)
+QML_DECLARE_TYPE(QDeclarativePathCubic)
+QML_DECLARE_TYPE(QDeclarativePathCatmullRomCurve)
+QML_DECLARE_TYPE(QDeclarativePathArc)
+QML_DECLARE_TYPE(QDeclarativePathSvg)
+QML_DECLARE_TYPE(QDeclarativePathPercent)
+QML_DECLARE_TYPE(QDeclarativePath)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPATH_H
diff --git a/src/declarative/util/qdeclarativepath_p_p.h b/src/quick/util/qdeclarativepath_p_p.h
index 910b7627d3..910b7627d3 100644
--- a/src/declarative/util/qdeclarativepath_p_p.h
+++ b/src/quick/util/qdeclarativepath_p_p.h
diff --git a/src/declarative/util/qdeclarativepathinterpolator.cpp b/src/quick/util/qdeclarativepathinterpolator.cpp
index 569884d33a..569884d33a 100644
--- a/src/declarative/util/qdeclarativepathinterpolator.cpp
+++ b/src/quick/util/qdeclarativepathinterpolator.cpp
diff --git a/src/quick/util/qdeclarativepathinterpolator_p.h b/src/quick/util/qdeclarativepathinterpolator_p.h
new file mode 100644
index 0000000000..11370a53fe
--- /dev/null
+++ b/src/quick/util/qdeclarativepathinterpolator_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEPATHINTERPOLATOR_P_H
+#define QDECLARATIVEPATHINTERPOLATOR_P_H
+
+#include <qdeclarative.h>
+#include <QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePath;
+class Q_AUTOTEST_EXPORT QDeclarativePathInterpolator : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
+ Q_PROPERTY(qreal x READ x NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y NOTIFY yChanged)
+ Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged)
+public:
+ explicit QDeclarativePathInterpolator(QObject *parent = 0);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *path);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ qreal x() const;
+ qreal y() const;
+ qreal angle() const;
+
+Q_SIGNALS:
+ void pathChanged();
+ void progressChanged();
+ void xChanged();
+ void yChanged();
+ void angleChanged();
+
+private Q_SLOTS:
+ void _q_pathUpdated();
+
+private:
+ QDeclarativePath *_path;
+ qreal _x;
+ qreal _y;
+ qreal _angle;
+ qreal _progress;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePathInterpolator)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPATHINTERPOLATOR_P_H
diff --git a/src/quick/util/qdeclarativepixmapcache.cpp b/src/quick/util/qdeclarativepixmapcache.cpp
new file mode 100644
index 0000000000..ba155abe98
--- /dev/null
+++ b/src/quick/util/qdeclarativepixmapcache.cpp
@@ -0,0 +1,1241 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "qdeclarativepixmapcache_p.h"
+#include <qdeclarativenetworkaccessmanagerfactory.h>
+#include <qdeclarativeimageprovider.h>
+
+#include <qdeclarativeengine.h>
+#include <private/qdeclarativeglobal_p.h>
+#include <private/qdeclarativeengine_p.h>
+
+#include <QtQuick/private/qsgtexture_p.h>
+
+#include <QCoreApplication>
+#include <QImageReader>
+#include <QHash>
+#include <QNetworkReply>
+#include <QPixmapCache>
+#include <QFile>
+#include <QThread>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QWaitCondition>
+#include <QBuffer>
+#include <QWaitCondition>
+#include <QtCore/qdebug.h>
+#include <private/qobject_p.h>
+#include <QSslError>
+#include <QOpenGLContext>
+
+#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
+#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
+#define CACHE_EXPIRE_TIME 30
+#define CACHE_REMOVAL_FRACTION 4
+
+QT_BEGIN_NAMESPACE
+
+// The cache limit describes the maximum "junk" in the cache.
+static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded in qpixmapcache.cpp
+
+QSGTexture *QDeclarativeDefaultTextureFactory::createTexture() const
+{
+ QSGPlainTexture *t = new QSGPlainTexture();
+ t->setImage(im);
+ return t;
+}
+
+class QDeclarativePixmapReader;
+class QDeclarativePixmapData;
+class QDeclarativePixmapReply : public QObject
+{
+ Q_OBJECT
+public:
+ enum ReadError { NoError, Loading, Decoding };
+
+ QDeclarativePixmapReply(QDeclarativePixmapData *);
+ ~QDeclarativePixmapReply();
+
+ QDeclarativePixmapData *data;
+ QDeclarativeEngine *engineForReader; // always access reader inside readerMutex
+ QSize requestSize;
+ QUrl url;
+
+ bool loading;
+ int redirectCount;
+
+ class Event : public QEvent {
+ public:
+ Event(ReadError, const QString &, const QSize &, QDeclarativeTextureFactory *factory, const QImage &image);
+
+ ReadError error;
+ QString errorString;
+ QSize implicitSize;
+ QImage image;
+ QDeclarativeTextureFactory *textureFactory;
+ };
+ void postReply(ReadError, const QString &, const QSize &, const QImage &image);
+ void postReply(ReadError, const QString &, const QSize &, QDeclarativeTextureFactory *factory, const QImage &image);
+
+
+Q_SIGNALS:
+ void finished();
+ void downloadProgress(qint64, qint64);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QDeclarativePixmapReply)
+
+public:
+ static int finishedIndex;
+ static int downloadProgressIndex;
+};
+
+class QDeclarativePixmapReaderThreadObject : public QObject {
+ Q_OBJECT
+public:
+ QDeclarativePixmapReaderThreadObject(QDeclarativePixmapReader *);
+ void processJobs();
+ virtual bool event(QEvent *e);
+private slots:
+ void networkRequestDone();
+private:
+ QDeclarativePixmapReader *reader;
+};
+
+class QDeclarativePixmapData;
+class QDeclarativePixmapReader : public QThread
+{
+ Q_OBJECT
+public:
+ QDeclarativePixmapReader(QDeclarativeEngine *eng);
+ ~QDeclarativePixmapReader();
+
+ QDeclarativePixmapReply *getImage(QDeclarativePixmapData *);
+ void cancel(QDeclarativePixmapReply *rep);
+
+ static QDeclarativePixmapReader *instance(QDeclarativeEngine *engine);
+ static QDeclarativePixmapReader *existingInstance(QDeclarativeEngine *engine);
+
+protected:
+ void run();
+
+private:
+ friend class QDeclarativePixmapReaderThreadObject;
+ void processJobs();
+ void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &);
+ void networkRequestDone(QNetworkReply *);
+
+ QList<QDeclarativePixmapReply*> jobs;
+ QList<QDeclarativePixmapReply*> cancelled;
+ QDeclarativeEngine *engine;
+ QObject *eventLoopQuitHack;
+
+ QMutex mutex;
+ QDeclarativePixmapReaderThreadObject *threadObject;
+ QWaitCondition waitCondition;
+
+ QNetworkAccessManager *networkAccessManager();
+ QNetworkAccessManager *accessManager;
+
+ QHash<QNetworkReply*,QDeclarativePixmapReply*> replies;
+
+ static int replyDownloadProgress;
+ static int replyFinished;
+ static int downloadProgress;
+ static int threadNetworkRequestDone;
+ static QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> readers;
+public:
+ static QMutex readerMutex;
+};
+
+class QDeclarativePixmapData
+{
+public:
+ QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QSize &s, const QString &e)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Error),
+ url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ declarativePixmaps.insert(pixmap);
+ }
+
+ QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QSize &r)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Loading),
+ url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
+ nextUnreferenced(0)
+ {
+ declarativePixmaps.insert(pixmap);
+ }
+
+ QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, const QImage &p, const QSize &s, const QSize &r)
+ : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
+ url(u), image(p), implicitSize(s), requestSize(r), textureFactory(new QDeclarativeDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ declarativePixmaps.insert(pixmap);
+ }
+
+ QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QUrl &u, QDeclarativeTextureFactory *factory, const QImage &p, const QSize &s, const QSize &r)
+ : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
+ url(u), image(p), implicitSize(s), requestSize(r), textureFactory(factory), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ declarativePixmaps.insert(pixmap);
+ }
+
+ QDeclarativePixmapData(QDeclarativePixmap *pixmap, const QImage &p)
+ : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarativePixmap::Ready),
+ image(p), implicitSize(p.size()), requestSize(p.size()), textureFactory(new QDeclarativeDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ declarativePixmaps.insert(pixmap);
+ }
+
+ ~QDeclarativePixmapData()
+ {
+ while (!declarativePixmaps.isEmpty()) {
+ QDeclarativePixmap *referencer = declarativePixmaps.first();
+ declarativePixmaps.remove(referencer);
+ referencer->d = 0;
+ }
+ delete textureFactory;
+ }
+
+ int cost() const;
+ void addref();
+ void release();
+ void addToCache();
+ void removeFromCache();
+
+ uint refCount;
+
+ bool inCache:1;
+ bool privatePixmap:1;
+
+ QDeclarativePixmap::Status pixmapStatus;
+ QUrl url;
+ QString errorString;
+ QImage image;
+ QSize implicitSize;
+ QSize requestSize;
+
+ QDeclarativeTextureFactory *textureFactory;
+
+ QIntrusiveList<QDeclarativePixmap, &QDeclarativePixmap::dataListNode> declarativePixmaps;
+ QDeclarativePixmapReply *reply;
+
+ QDeclarativePixmapData *prevUnreferenced;
+ QDeclarativePixmapData**prevUnreferencedPtr;
+ QDeclarativePixmapData *nextUnreferenced;
+};
+
+int QDeclarativePixmapReply::finishedIndex = -1;
+int QDeclarativePixmapReply::downloadProgressIndex = -1;
+
+// XXX
+QHash<QDeclarativeEngine *,QDeclarativePixmapReader*> QDeclarativePixmapReader::readers;
+QMutex QDeclarativePixmapReader::readerMutex;
+
+int QDeclarativePixmapReader::replyDownloadProgress = -1;
+int QDeclarativePixmapReader::replyFinished = -1;
+int QDeclarativePixmapReader::downloadProgress = -1;
+int QDeclarativePixmapReader::threadNetworkRequestDone = -1;
+
+
+void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString,
+ const QSize &implicitSize, const QImage &image)
+{
+ loading = false;
+ QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, new QDeclarativeDefaultTextureFactory(image), image));
+}
+
+void QDeclarativePixmapReply::postReply(ReadError error, const QString &errorString,
+ const QSize &implicitSize, QDeclarativeTextureFactory *factory,
+ const QImage &image)
+{
+ loading = false;
+ QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory, image));
+}
+
+QDeclarativePixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QDeclarativeTextureFactory *factory, const QImage &i)
+ : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i), textureFactory(factory)
+{
+}
+
+QNetworkAccessManager *QDeclarativePixmapReader::networkAccessManager()
+{
+ if (!accessManager) {
+ Q_ASSERT(threadObject);
+ accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
+ }
+ return accessManager;
+}
+
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
+ const QSize &requestSize)
+{
+ QImageReader imgio(dev);
+
+ bool force_scale = false;
+ if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
+ imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
+ force_scale = true;
+ }
+
+ bool scaled = false;
+ if (requestSize.width() > 0 || requestSize.height() > 0) {
+ QSize s = imgio.size();
+ if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
+ if (requestSize.height() <= 0)
+ s.setHeight(s.height()*requestSize.width()/s.width());
+ s.setWidth(requestSize.width()); scaled = true;
+ }
+ if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
+ if (requestSize.width() <= 0)
+ s.setWidth(s.width()*requestSize.height()/s.height());
+ s.setHeight(requestSize.height()); scaled = true;
+ }
+ if (scaled) { imgio.setScaledSize(s); }
+ }
+
+ if (impsize)
+ *impsize = imgio.size();
+
+ if (imgio.read(image)) {
+ if (impsize && impsize->width() < 0)
+ *impsize = image->size();
+ return true;
+ } else {
+ if (errorString)
+ *errorString = QDeclarativePixmap::tr("Error decoding: %1: %2").arg(url.toString())
+ .arg(imgio.errorString());
+ return false;
+ }
+}
+
+QDeclarativePixmapReader::QDeclarativePixmapReader(QDeclarativeEngine *eng)
+: QThread(eng), engine(eng), threadObject(0), accessManager(0)
+{
+ eventLoopQuitHack = new QObject;
+ eventLoopQuitHack->moveToThread(this);
+ connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
+ start(QThread::LowestPriority);
+}
+
+QDeclarativePixmapReader::~QDeclarativePixmapReader()
+{
+ readerMutex.lock();
+ readers.remove(engine);
+ readerMutex.unlock();
+
+ mutex.lock();
+ // manually cancel all outstanding jobs.
+ foreach (QDeclarativePixmapReply *reply, jobs) {
+ delete reply;
+ }
+ jobs.clear();
+ QList<QDeclarativePixmapReply*> activeJobs = replies.values();
+ foreach (QDeclarativePixmapReply *reply, activeJobs) {
+ if (reply->loading) {
+ cancelled.append(reply);
+ reply->data = 0;
+ }
+ }
+ if (threadObject) threadObject->processJobs();
+ mutex.unlock();
+
+ eventLoopQuitHack->deleteLater();
+ wait();
+}
+
+void QDeclarativePixmapReader::networkRequestDone(QNetworkReply *reply)
+{
+ QDeclarativePixmapReply *job = replies.take(reply);
+
+ if (job) {
+ job->redirectCount++;
+ if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) {
+ QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = reply->url().resolved(redirect.toUrl());
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+
+ reply->deleteLater();
+ reply = networkAccessManager()->get(req);
+
+ QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
+
+ replies.insert(reply, job);
+ return;
+ }
+ }
+
+ QImage image;
+ QDeclarativePixmapReply::ReadError error = QDeclarativePixmapReply::NoError;
+ QString errorString;
+ QSize readSize;
+ if (reply->error()) {
+ error = QDeclarativePixmapReply::Loading;
+ errorString = reply->errorString();
+ } else {
+ QByteArray all = reply->readAll();
+ QBuffer buff(&all);
+ buff.open(QIODevice::ReadOnly);
+ if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize))
+ error = QDeclarativePixmapReply::Decoding;
+ }
+ // send completion event to the QDeclarativePixmapReply
+ mutex.lock();
+ if (!cancelled.contains(job)) {
+ job->postReply(error, errorString, readSize, image);
+ }
+ mutex.unlock();
+ }
+ reply->deleteLater();
+
+ // kick off event loop again incase we have dropped below max request count
+ threadObject->processJobs();
+}
+
+QDeclarativePixmapReaderThreadObject::QDeclarativePixmapReaderThreadObject(QDeclarativePixmapReader *i)
+: reader(i)
+{
+}
+
+void QDeclarativePixmapReaderThreadObject::processJobs()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+}
+
+bool QDeclarativePixmapReaderThreadObject::event(QEvent *e)
+{
+ if (e->type() == QEvent::User) {
+ reader->processJobs();
+ return true;
+ } else {
+ return QObject::event(e);
+ }
+}
+
+void QDeclarativePixmapReaderThreadObject::networkRequestDone()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+ reader->networkRequestDone(reply);
+}
+
+void QDeclarativePixmapReader::processJobs()
+{
+ QMutexLocker locker(&mutex);
+
+ while (true) {
+ if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
+ return; // Nothing else to do
+
+ // Clean cancelled jobs
+ if (cancelled.count()) {
+ for (int i = 0; i < cancelled.count(); ++i) {
+ QDeclarativePixmapReply *job = cancelled.at(i);
+ QNetworkReply *reply = replies.key(job, 0);
+ if (reply && reply->isRunning()) {
+ // cancel any jobs already started
+ replies.remove(reply);
+ reply->close();
+ }
+ // deleteLater, since not owned by this thread
+ job->deleteLater();
+ }
+ cancelled.clear();
+ }
+
+ if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
+ QDeclarativePixmapReply *runningJob = jobs.takeLast();
+ runningJob->loading = true;
+
+ QUrl url = runningJob->url;
+ QSize requestSize = runningJob->requestSize;
+ locker.unlock();
+ processJob(runningJob, url, requestSize);
+ locker.relock();
+ }
+ }
+}
+
+void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url,
+ const QSize &requestSize)
+{
+ // fetch
+ if (url.scheme() == QLatin1String("image")) {
+ // Use QmlImageProvider
+ QSize readSize;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url);
+ if (imageType == QDeclarativeImageProvider::Invalid) {
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::Loading;
+ QString errorStr = QDeclarativePixmap::tr("Invalid image provider: %1").arg(url.toString());
+ QImage image;
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ mutex.unlock();
+ } else if (imageType == QDeclarativeImageProvider::Image) {
+ QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
+ QString errorStr;
+ if (image.isNull()) {
+ errorCode = QDeclarativePixmapReply::Loading;
+ errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ mutex.unlock();
+ } else {
+ QDeclarativeTextureFactory *t = ep->getTextureFromProvider(url, &readSize, requestSize);
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
+ QString errorStr;
+ if (!t) {
+ errorCode = QDeclarativePixmapReply::Loading;
+ errorStr = QDeclarativePixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, t, QImage());
+ mutex.unlock();
+
+ }
+
+ } else {
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ // Image is local - load/decode immediately
+ QImage image;
+ QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
+ QString errorStr;
+ QFile f(lf);
+ QSize readSize;
+ if (f.open(QIODevice::ReadOnly)) {
+ if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
+ errorCode = QDeclarativePixmapReply::Loading;
+ } else {
+ errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
+ errorCode = QDeclarativePixmapReply::Loading;
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ mutex.unlock();
+ } else {
+ // Network resource
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ QNetworkReply *reply = networkAccessManager()->get(req);
+
+ QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
+
+ replies.insert(reply, runningJob);
+ }
+ }
+}
+
+QDeclarativePixmapReader *QDeclarativePixmapReader::instance(QDeclarativeEngine *engine)
+{
+ // XXX NOTE: must be called within readerMutex locking.
+ QDeclarativePixmapReader *reader = readers.value(engine);
+ if (!reader) {
+ reader = new QDeclarativePixmapReader(engine);
+ readers.insert(engine, reader);
+ }
+
+ return reader;
+}
+
+QDeclarativePixmapReader *QDeclarativePixmapReader::existingInstance(QDeclarativeEngine *engine)
+{
+ // XXX NOTE: must be called within readerMutex locking.
+ return readers.value(engine, 0);
+}
+
+QDeclarativePixmapReply *QDeclarativePixmapReader::getImage(QDeclarativePixmapData *data)
+{
+ mutex.lock();
+ QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(data);
+ reply->engineForReader = engine;
+ jobs.append(reply);
+ // XXX
+ if (threadObject) threadObject->processJobs();
+ mutex.unlock();
+ return reply;
+}
+
+void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply)
+{
+ mutex.lock();
+ if (reply->loading) {
+ cancelled.append(reply);
+ reply->data = 0;
+ // XXX
+ if (threadObject) threadObject->processJobs();
+ } else {
+ jobs.removeAll(reply);
+ delete reply;
+ }
+ mutex.unlock();
+}
+
+void QDeclarativePixmapReader::run()
+{
+ if (replyDownloadProgress == -1) {
+ const QMetaObject *nr = &QNetworkReply::staticMetaObject;
+ const QMetaObject *pr = &QDeclarativePixmapReply::staticMetaObject;
+ const QMetaObject *ir = &QDeclarativePixmapReaderThreadObject::staticMetaObject;
+ replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished = nr->indexOfSignal("finished()");
+ downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
+ threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
+ }
+
+ mutex.lock();
+ threadObject = new QDeclarativePixmapReaderThreadObject(this);
+ mutex.unlock();
+
+ processJobs();
+ exec();
+
+ delete threadObject;
+ threadObject = 0;
+}
+
+class QDeclarativePixmapKey
+{
+public:
+ const QUrl *url;
+ const QSize *size;
+};
+
+inline bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs)
+{
+ return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
+}
+
+inline uint qHash(const QDeclarativePixmapKey &key)
+{
+ return qHash(*key.url) ^ key.size->width() ^ key.size->height();
+}
+
+class QSGContext;
+
+class QDeclarativePixmapStore : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarativePixmapStore();
+ ~QDeclarativePixmapStore();
+
+ void unreferencePixmap(QDeclarativePixmapData *);
+ void referencePixmap(QDeclarativePixmapData *);
+
+protected:
+ virtual void timerEvent(QTimerEvent *);
+
+public:
+ QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
+
+private:
+ void shrinkCache(int remove);
+
+ QDeclarativePixmapData *m_unreferencedPixmaps;
+ QDeclarativePixmapData *m_lastUnreferencedPixmap;
+
+ int m_unreferencedCost;
+ int m_timerId;
+};
+Q_GLOBAL_STATIC(QDeclarativePixmapStore, pixmapStore);
+
+
+QDeclarativePixmapStore::QDeclarativePixmapStore()
+: m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1)
+{
+}
+
+QDeclarativePixmapStore::~QDeclarativePixmapStore()
+{
+ int leakedPixmaps = 0;
+ QList<QDeclarativePixmapData*> cachedData = m_cache.values();
+
+ // unreference all (leaked) pixmaps
+ foreach (QDeclarativePixmapData* pixmap, cachedData) {
+ int currRefCount = pixmap->refCount;
+ if (currRefCount) {
+ leakedPixmaps++;
+ while (currRefCount > 0) {
+ pixmap->release();
+ currRefCount--;
+ }
+ }
+ }
+
+ // free all unreferenced pixmaps
+ while (m_lastUnreferencedPixmap) {
+ shrinkCache(20);
+ }
+
+ if (leakedPixmaps)
+ qDebug("Number of leaked pixmaps: %i", leakedPixmaps);
+}
+
+void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
+{
+ Q_ASSERT(data->prevUnreferenced == 0);
+ Q_ASSERT(data->prevUnreferencedPtr == 0);
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ data->nextUnreferenced = m_unreferencedPixmaps;
+ data->prevUnreferencedPtr = &m_unreferencedPixmaps;
+
+ m_unreferencedPixmaps = data;
+ if (m_unreferencedPixmaps->nextUnreferenced) {
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps;
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced;
+ }
+
+ if (!m_lastUnreferencedPixmap)
+ m_lastUnreferencedPixmap = data;
+
+ m_unreferencedCost += data->cost();
+
+ shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
+
+ if (m_timerId == -1 && m_unreferencedPixmaps)
+ m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
+}
+
+void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
+{
+ Q_ASSERT(data->prevUnreferencedPtr);
+
+ *data->prevUnreferencedPtr = data->nextUnreferenced;
+ if (data->nextUnreferenced) {
+ data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
+ data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
+ }
+ if (m_lastUnreferencedPixmap == data)
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+
+ data->nextUnreferenced = 0;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ m_unreferencedCost -= data->cost();
+}
+
+void QDeclarativePixmapStore::shrinkCache(int remove)
+{
+ while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
+ QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ *data->prevUnreferencedPtr = 0;
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ remove -= data->cost();
+ m_unreferencedCost -= data->cost();
+ data->removeFromCache();
+ delete data;
+ }
+}
+
+void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
+{
+ int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
+
+ shrinkCache(removalCost);
+
+ if (m_unreferencedPixmaps == 0) {
+ killTimer(m_timerId);
+ m_timerId = -1;
+ }
+}
+
+QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativePixmapData *d)
+: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0)
+{
+ if (finishedIndex == -1) {
+ finishedIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("finished()");
+ downloadProgressIndex = QDeclarativePixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ }
+}
+
+QDeclarativePixmapReply::~QDeclarativePixmapReply()
+{
+}
+
+bool QDeclarativePixmapReply::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+
+ if (data) {
+ Event *de = static_cast<Event *>(event);
+ data->pixmapStatus = (de->error == NoError) ? QDeclarativePixmap::Ready : QDeclarativePixmap::Error;
+
+ if (data->pixmapStatus == QDeclarativePixmap::Ready) {
+ if (de->textureFactory) {
+ data->textureFactory = de->textureFactory;
+ }
+ data->image = de->image;
+ data->implicitSize = de->implicitSize;
+ } else {
+ data->errorString = de->errorString;
+ data->removeFromCache(); // We don't continue to cache error'd pixmaps
+ }
+
+ data->reply = 0;
+ emit finished();
+ }
+
+ delete this;
+ return true;
+ } else {
+ return QObject::event(event);
+ }
+}
+
+int QDeclarativePixmapData::cost() const
+{
+ if (textureFactory)
+ return textureFactory->textureByteCount();
+ return image.byteCount();
+}
+
+void QDeclarativePixmapData::addref()
+{
+ ++refCount;
+ if (prevUnreferencedPtr)
+ pixmapStore()->referencePixmap(this);
+}
+
+void QDeclarativePixmapData::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0) {
+ if (reply) {
+ QDeclarativePixmapReply *cancelReply = reply;
+ reply->data = 0;
+ reply = 0;
+ QDeclarativePixmapReader::readerMutex.lock();
+ QDeclarativePixmapReader *reader = QDeclarativePixmapReader::existingInstance(cancelReply->engineForReader);
+ if (reader)
+ reader->cancel(cancelReply);
+ QDeclarativePixmapReader::readerMutex.unlock();
+ }
+
+ if (pixmapStatus == QDeclarativePixmap::Ready) {
+ pixmapStore()->unreferencePixmap(this);
+ } else {
+ removeFromCache();
+ delete this;
+ }
+ }
+}
+
+void QDeclarativePixmapData::addToCache()
+{
+ if (!inCache) {
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.insert(key, this);
+ inCache = true;
+ }
+}
+
+void QDeclarativePixmapData::removeFromCache()
+{
+ if (inCache) {
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.remove(key);
+ inCache = false;
+ }
+}
+
+static QDeclarativePixmapData* createPixmapDataSync(QDeclarativePixmap *declarativePixmap, QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok)
+{
+ if (url.scheme() == QLatin1String("image")) {
+ QSize readSize;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url);
+
+ switch (imageType) {
+ case QDeclarativeImageProvider::Invalid:
+ return new QDeclarativePixmapData(declarativePixmap, url, requestSize,
+ QDeclarativePixmap::tr("Invalid image provider: %1").arg(url.toString()));
+ case QDeclarativeImageProvider::Texture:
+ {
+ QDeclarativeTextureFactory *texture = ep->getTextureFromProvider(url, &readSize, requestSize);
+ if (texture) {
+ *ok = true;
+ return new QDeclarativePixmapData(declarativePixmap, url, texture, QImage(), readSize, requestSize);
+ }
+ }
+
+ case QDeclarativeImageProvider::Image:
+ {
+ QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
+ if (!image.isNull()) {
+ *ok = true;
+ return new QDeclarativePixmapData(declarativePixmap, url, image, readSize, requestSize);
+ }
+ }
+ case QDeclarativeImageProvider::Pixmap:
+ {
+ QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize);
+ if (!pixmap.isNull()) {
+ *ok = true;
+ return new QDeclarativePixmapData(declarativePixmap, url, pixmap.toImage(), readSize, requestSize);
+ }
+ }
+ }
+
+ // provider has bad image type, or provider returned null image
+ return new QDeclarativePixmapData(declarativePixmap, url, requestSize,
+ QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString()));
+ }
+
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (localFile.isEmpty())
+ return 0;
+
+ QFile f(localFile);
+ QSize readSize;
+ QString errorString;
+
+ if (f.open(QIODevice::ReadOnly)) {
+ QImage image;
+
+ if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
+ *ok = true;
+ return new QDeclarativePixmapData(declarativePixmap, url, image, readSize, requestSize);
+ }
+ errorString = QDeclarativePixmap::tr("Invalid image data: %1").arg(url.toString());
+
+ } else {
+ errorString = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
+ }
+ return new QDeclarativePixmapData(declarativePixmap, url, requestSize, errorString);
+}
+
+
+struct QDeclarativePixmapNull {
+ QUrl url;
+ QImage image;
+ QSize size;
+};
+Q_GLOBAL_STATIC(QDeclarativePixmapNull, nullPixmap);
+
+QDeclarativePixmap::QDeclarativePixmap()
+: d(0)
+{
+}
+
+QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url)
+: d(0)
+{
+ load(engine, url);
+}
+
+QDeclarativePixmap::QDeclarativePixmap(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+: d(0)
+{
+ load(engine, url, size);
+}
+
+QDeclarativePixmap::~QDeclarativePixmap()
+{
+ if (d) {
+ d->declarativePixmaps.remove(this);
+ d->release();
+ d = 0;
+ }
+}
+
+bool QDeclarativePixmap::isNull() const
+{
+ return d == 0;
+}
+
+bool QDeclarativePixmap::isReady() const
+{
+ return status() == Ready;
+}
+
+bool QDeclarativePixmap::isError() const
+{
+ return status() == Error;
+}
+
+bool QDeclarativePixmap::isLoading() const
+{
+ return status() == Loading;
+}
+
+QString QDeclarativePixmap::error() const
+{
+ if (d)
+ return d->errorString;
+ else
+ return QString();
+}
+
+QDeclarativePixmap::Status QDeclarativePixmap::status() const
+{
+ if (d)
+ return d->pixmapStatus;
+ else
+ return Null;
+}
+
+const QUrl &QDeclarativePixmap::url() const
+{
+ if (d)
+ return d->url;
+ else
+ return nullPixmap()->url;
+}
+
+const QSize &QDeclarativePixmap::implicitSize() const
+{
+ if (d)
+ return d->implicitSize;
+ else
+ return nullPixmap()->size;
+}
+
+const QSize &QDeclarativePixmap::requestSize() const
+{
+ if (d)
+ return d->requestSize;
+ else
+ return nullPixmap()->size;
+}
+
+QDeclarativeTextureFactory *QDeclarativePixmap::textureFactory() const
+{
+ if (d)
+ return d->textureFactory;
+
+ return 0;
+}
+
+const QImage &QDeclarativePixmap::image() const
+{
+ if (d)
+ return d->image;
+ else
+ return nullPixmap()->image;
+}
+
+void QDeclarativePixmap::setImage(const QImage &p)
+{
+ clear();
+
+ if (!p.isNull())
+ d = new QDeclarativePixmapData(this, p);
+}
+
+int QDeclarativePixmap::width() const
+{
+ if (d)
+ return d->textureFactory ? d->textureFactory->textureSize().width() : d->image.width();
+ else
+ return 0;
+}
+
+int QDeclarativePixmap::height() const
+{
+ if (d)
+ return d->textureFactory ? d->textureFactory->textureSize().height() : d->image.height();
+ else
+ return 0;
+}
+
+QRect QDeclarativePixmap::rect() const
+{
+ if (d)
+ return d->textureFactory ? QRect(QPoint(), d->textureFactory->textureSize()) : d->image.rect();
+ else
+ return QRect();
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url)
+{
+ load(engine, url, QSize(), QDeclarativePixmap::Cache);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options)
+{
+ load(engine, url, QSize(), options);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+{
+ load(engine, url, size, QDeclarativePixmap::Cache);
+}
+
+void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options)
+{
+ if (d) {
+ d->declarativePixmaps.remove(this);
+ d->release();
+ d = 0;
+ }
+
+ QDeclarativePixmapKey key = { &url, &requestSize };
+ QDeclarativePixmapStore *store = pixmapStore();
+
+ QHash<QDeclarativePixmapKey, QDeclarativePixmapData *>::Iterator iter = store->m_cache.find(key);
+
+ if (iter == store->m_cache.end()) {
+ if (options & QDeclarativePixmap::Asynchronous) {
+ // pixmaps can only be loaded synchronously
+ if (url.scheme() == QLatin1String("image")
+ && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) {
+ options &= ~QDeclarativePixmap::Asynchronous;
+ }
+ }
+
+ if (!(options & QDeclarativePixmap::Asynchronous)) {
+ bool ok = false;
+ d = createPixmapDataSync(this, engine, url, requestSize, &ok);
+ if (ok) {
+ if (options & QDeclarativePixmap::Cache)
+ d->addToCache();
+ return;
+ }
+ if (d) // loadable, but encountered error while loading
+ return;
+ }
+
+ if (!engine)
+ return;
+
+ d = new QDeclarativePixmapData(this, url, requestSize);
+ if (options & QDeclarativePixmap::Cache)
+ d->addToCache();
+
+ QDeclarativePixmapReader::readerMutex.lock();
+ d->reply = QDeclarativePixmapReader::instance(engine)->getImage(d);
+ QDeclarativePixmapReader::readerMutex.unlock();
+ } else {
+ d = *iter;
+ d->addref();
+ d->declarativePixmaps.insert(this);
+ }
+}
+
+void QDeclarativePixmap::clear()
+{
+ if (d) {
+ d->declarativePixmaps.remove(this);
+ d->release();
+ d = 0;
+ }
+}
+
+void QDeclarativePixmap::clear(QObject *obj)
+{
+ if (d) {
+ if (d->reply)
+ QObject::disconnect(d->reply, 0, obj, 0);
+ d->declarativePixmaps.remove(this);
+ d->release();
+ d = 0;
+ }
+}
+
+bool QDeclarativePixmap::connectFinished(QObject *object, const char *method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
+ return false;
+ }
+
+ return QObject::connect(d->reply, SIGNAL(finished()), object, method);
+}
+
+bool QDeclarativePixmap::connectFinished(QObject *object, int method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
+ return false;
+ }
+
+ return QMetaObject::connect(d->reply, QDeclarativePixmapReply::finishedIndex, object, method);
+}
+
+bool QDeclarativePixmap::connectDownloadProgress(QObject *object, const char *method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
+
+ return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
+}
+
+bool QDeclarativePixmap::connectDownloadProgress(QObject *object, int method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
+
+ return QMetaObject::connect(d->reply, QDeclarativePixmapReply::downloadProgressIndex, object, method);
+}
+
+QT_END_NAMESPACE
+
+#include <qdeclarativepixmapcache.moc>
diff --git a/src/quick/util/qdeclarativepixmapcache_p.h b/src/quick/util/qdeclarativepixmapcache_p.h
new file mode 100644
index 0000000000..ee55519f93
--- /dev/null
+++ b/src/quick/util/qdeclarativepixmapcache_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEPIXMAPCACHE_H
+#define QDECLARATIVEPIXMAPCACHE_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qpixmap.h>
+#include <QtCore/qurl.h>
+#include <QtQuick/qtquickglobal.h>
+
+#include <private/qintrusivelist_p.h>
+#include <qdeclarativeimageprovider.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+class QDeclarativePixmapData;
+class QDeclarativeTextureFactory;
+
+class QDeclarativeDefaultTextureFactory : public QDeclarativeTextureFactory
+{
+ Q_OBJECT
+public:
+ QDeclarativeDefaultTextureFactory(const QImage &i)
+ : im(i)
+ {
+ }
+
+ QSGTexture *createTexture() const;
+ QSize textureSize() const { return im.size(); }
+ int textureByteCount() const { return im.byteCount(); }
+ QImage image() const { return im; }
+
+private:
+ QImage im;
+};
+
+class Q_QUICK_EXPORT QDeclarativePixmap
+{
+ Q_DECLARE_TR_FUNCTIONS(QDeclarativePixmap)
+public:
+ QDeclarativePixmap();
+ QDeclarativePixmap(QDeclarativeEngine *, const QUrl &);
+ QDeclarativePixmap(QDeclarativeEngine *, const QUrl &, const QSize &);
+ ~QDeclarativePixmap();
+
+ enum Status { Null, Ready, Error, Loading };
+
+ enum Option {
+ Asynchronous = 0x00000001,
+ Cache = 0x00000002
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ Status status() const;
+ QString error() const;
+ const QUrl &url() const;
+ const QSize &implicitSize() const;
+ const QSize &requestSize() const;
+ const QImage &image() const;
+ void setImage(const QImage &);
+
+ QDeclarativeTextureFactory *textureFactory() const;
+
+ QRect rect() const;
+ int width() const;
+ int height() const;
+
+ void load(QDeclarativeEngine *, const QUrl &);
+ void load(QDeclarativeEngine *, const QUrl &, QDeclarativePixmap::Options options);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &, QDeclarativePixmap::Options options);
+
+ void clear();
+ void clear(QObject *);
+
+ bool connectFinished(QObject *, const char *);
+ bool connectFinished(QObject *, int);
+ bool connectDownloadProgress(QObject *, const char *);
+ bool connectDownloadProgress(QObject *, int);
+
+private:
+ Q_DISABLE_COPY(QDeclarativePixmap)
+ QDeclarativePixmapData *d;
+ QIntrusiveListNode dataListNode;
+ friend class QDeclarativePixmapData;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePixmap::Options)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPIXMAPCACHE_H
diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/quick/util/qdeclarativepropertychanges.cpp
index d6035fa9d2..d6035fa9d2 100644
--- a/src/declarative/util/qdeclarativepropertychanges.cpp
+++ b/src/quick/util/qdeclarativepropertychanges.cpp
diff --git a/src/quick/util/qdeclarativepropertychanges_p.h b/src/quick/util/qdeclarativepropertychanges_p.h
new file mode 100644
index 0000000000..73f308874d
--- /dev/null
+++ b/src/quick/util/qdeclarativepropertychanges_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEPROPERTYCHANGES_H
+#define QDECLARATIVEPROPERTYCHANGES_H
+
+#include "qdeclarativestateoperations_p.h"
+#include <private/qdeclarativecustomparser_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePropertyChangesPrivate;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativePropertyChanges)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
+ Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
+public:
+ QDeclarativePropertyChanges();
+ ~QDeclarativePropertyChanges();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ bool restoreEntryValues() const;
+ void setRestoreEntryValues(bool);
+
+ bool isExplicit() const;
+ void setIsExplicit(bool);
+
+ virtual ActionList actions();
+
+ bool containsProperty(const QString &name) const;
+ bool containsValue(const QString &name) const;
+ bool containsExpression(const QString &name) const;
+ void changeValue(const QString &name, const QVariant &value);
+ void changeExpression(const QString &name, const QString &expression);
+ void removeProperty(const QString &name);
+ QVariant value(const QString &name) const;
+ QString expression(const QString &name) const;
+
+ void detachFromState();
+ void attachToState();
+
+ QVariant property(const QString &name) const;
+};
+
+class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser
+{
+public:
+ QDeclarativePropertyChangesParser()
+ : QDeclarativeCustomParser(AcceptsAttachedProperties) {}
+
+ void compileList(QList<QPair<QString, QVariant> > &list, const QString &pre, const QDeclarativeCustomParserProperty &prop);
+
+ virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePropertyChanges)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPROPERTYCHANGES_H
diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/quick/util/qdeclarativesmoothedanimation.cpp
index 45c6885fbb..45c6885fbb 100644
--- a/src/declarative/util/qdeclarativesmoothedanimation.cpp
+++ b/src/quick/util/qdeclarativesmoothedanimation.cpp
diff --git a/src/quick/util/qdeclarativesmoothedanimation_p.h b/src/quick/util/qdeclarativesmoothedanimation_p.h
new file mode 100644
index 0000000000..d4c7716540
--- /dev/null
+++ b/src/quick/util/qdeclarativesmoothedanimation_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESMOOTHEDANIMATION_H
+#define QDECLARATIVESMOOTHEDANIMATION_H
+
+#include <qdeclarative.h>
+#include "qdeclarativeanimation_p.h"
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeProperty;
+class QDeclarativeSmoothedAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation)
+ Q_ENUMS(ReversingMode)
+
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
+ Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
+
+public:
+ enum ReversingMode { Eased, Immediate, Sync };
+
+ QDeclarativeSmoothedAnimation(QObject *parent = 0);
+ ~QDeclarativeSmoothedAnimation();
+
+ ReversingMode reversingMode() const;
+ void setReversingMode(ReversingMode);
+
+ virtual int duration() const;
+ virtual void setDuration(int);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ int maximumEasingTime() const;
+ void setMaximumEasingTime(int);
+
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ QAbstractAnimation* qtAnimation();
+
+Q_SIGNALS:
+ void velocityChanged();
+ void reversingModeChanged();
+ void maximumEasingTimeChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESMOOTHEDANIMATION_H
diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p_p.h b/src/quick/util/qdeclarativesmoothedanimation_p_p.h
index 08b1450342..08b1450342 100644
--- a/src/declarative/util/qdeclarativesmoothedanimation_p_p.h
+++ b/src/quick/util/qdeclarativesmoothedanimation_p_p.h
diff --git a/src/declarative/util/qdeclarativespringanimation.cpp b/src/quick/util/qdeclarativespringanimation.cpp
index b0b12c7ba4..b0b12c7ba4 100644
--- a/src/declarative/util/qdeclarativespringanimation.cpp
+++ b/src/quick/util/qdeclarativespringanimation.cpp
diff --git a/src/quick/util/qdeclarativespringanimation_p.h b/src/quick/util/qdeclarativespringanimation_p.h
new file mode 100644
index 0000000000..13e983b9a5
--- /dev/null
+++ b/src/quick/util/qdeclarativespringanimation_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESPRINGANIMATION_H
+#define QDECLARATIVESPRINGANIMATION_H
+
+#include <qdeclarative.h>
+#include "qdeclarativeanimation_p.h"
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSpringAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeSpringAnimation : public QDeclarativeNumberAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeSpringAnimation)
+ Q_INTERFACES(QDeclarativePropertyValueSource)
+
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
+ Q_PROPERTY(qreal spring READ spring WRITE setSpring)
+ Q_PROPERTY(qreal damping READ damping WRITE setDamping)
+ Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
+ Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
+ Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged)
+
+public:
+ QDeclarativeSpringAnimation(QObject *parent=0);
+ ~QDeclarativeSpringAnimation();
+
+ qreal velocity() const;
+ void setVelocity(qreal velocity);
+
+ qreal spring() const;
+ void setSpring(qreal spring);
+
+ qreal damping() const;
+ void setDamping(qreal damping);
+
+ qreal epsilon() const;
+ void setEpsilon(qreal epsilon);
+
+ qreal mass() const;
+ void setMass(qreal modulus);
+
+ qreal modulus() const;
+ void setModulus(qreal modulus);
+
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void modulusChanged();
+ void massChanged();
+ void syncChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeSpringAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESPRINGANIMATION_H
diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/quick/util/qdeclarativestate.cpp
index 1250c0c2b5..1250c0c2b5 100644
--- a/src/declarative/util/qdeclarativestate.cpp
+++ b/src/quick/util/qdeclarativestate.cpp
diff --git a/src/quick/util/qdeclarativestate_p.h b/src/quick/util/qdeclarativestate_p.h
new file mode 100644
index 0000000000..79038e50ea
--- /dev/null
+++ b/src/quick/util/qdeclarativestate_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESTATE_H
+#define QDECLARATIVESTATE_H
+
+#include <qdeclarative.h>
+#include <qdeclarativeproperty.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qsharedpointer.h>
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeActionEvent;
+class QDeclarativeAbstractBinding;
+class QDeclarativeBinding;
+class QDeclarativeExpression;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeAction
+{
+public:
+ QDeclarativeAction();
+ QDeclarativeAction(QObject *, const QString &, const QVariant &);
+ QDeclarativeAction(QObject *, const QString &,
+ QDeclarativeContext *, const QVariant &);
+
+ bool restore:1;
+ bool actionDone:1;
+ bool reverseEvent:1;
+ bool deletableToBinding:1;
+
+ QDeclarativeProperty property;
+ QVariant fromValue;
+ QVariant toValue;
+
+ QDeclarativeAbstractBinding *fromBinding;
+ QWeakPointer<QDeclarativeAbstractBinding> toBinding;
+ QDeclarativeActionEvent *event;
+
+ //strictly for matching
+ QObject *specifiedObject;
+ QString specifiedProperty;
+
+ void deleteFromBinding();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeActionEvent
+{
+public:
+ virtual ~QDeclarativeActionEvent();
+ virtual QString typeName() const;
+
+ enum Reason { ActualChange, FastForward };
+
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual void saveOriginals() {}
+ virtual bool needsCopy() { return false; }
+ virtual void copyOriginals(QDeclarativeActionEvent *) {}
+
+ virtual bool isRewindable() { return isReversable(); }
+ virtual void rewind() {}
+ virtual void saveCurrentValues() {}
+ virtual void saveTargetValues() {}
+
+ virtual bool changesBindings();
+ virtual void clearBindings();
+ virtual bool override(QDeclarativeActionEvent*other);
+};
+
+//### rename to QDeclarativeStateChange?
+class QDeclarativeStateGroup;
+class QDeclarativeState;
+class QDeclarativeStateOperationPrivate;
+class Q_QUICK_EXPORT QDeclarativeStateOperation : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarativeStateOperation(QObject *parent = 0)
+ : QObject(parent) {}
+ typedef QList<QDeclarativeAction> ActionList;
+
+ virtual ActionList actions();
+
+ QDeclarativeState *state() const;
+ void setState(QDeclarativeState *state);
+
+protected:
+ QDeclarativeStateOperation(QObjectPrivate &dd, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarativeStateOperation)
+ Q_DISABLE_COPY(QDeclarativeStateOperation)
+};
+
+typedef QDeclarativeStateOperation::ActionList QDeclarativeStateActions;
+
+class QDeclarativeTransition;
+class QDeclarativeStatePrivate;
+class Q_QUICK_EXPORT QDeclarativeState : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QDeclarativeBinding *when READ when WRITE setWhen)
+ Q_PROPERTY(QString extend READ extends WRITE setExtends)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeStateOperation> changes READ changes)
+ Q_CLASSINFO("DefaultProperty", "changes")
+ Q_CLASSINFO("DeferredPropertyNames", "changes")
+
+public:
+ QDeclarativeState(QObject *parent=0);
+ virtual ~QDeclarativeState();
+
+ QString name() const;
+ void setName(const QString &);
+ bool isNamed() const;
+
+ /*'when' is a QDeclarativeBinding to limit state changes oscillation
+ due to the unpredictable order of evaluation of bound expressions*/
+ bool isWhenKnown() const;
+ QDeclarativeBinding *when() const;
+ void setWhen(QDeclarativeBinding *);
+
+ QString extends() const;
+ void setExtends(const QString &);
+
+ QDeclarativeListProperty<QDeclarativeStateOperation> changes();
+ int operationCount() const;
+ QDeclarativeStateOperation *operationAt(int) const;
+
+ QDeclarativeState &operator<<(QDeclarativeStateOperation *);
+
+ void apply(QDeclarativeTransition *, QDeclarativeState *revert);
+ void cancel();
+
+ QDeclarativeStateGroup *stateGroup() const;
+ void setStateGroup(QDeclarativeStateGroup *);
+
+ bool containsPropertyInRevertList(QObject *target, const QString &name) const;
+ bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue);
+ bool changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding);
+ bool removeEntryFromRevertList(QObject *target, const QString &name);
+ void addEntryToRevertList(const QDeclarativeAction &action);
+ void removeAllEntriesFromRevertList(QObject *target);
+ void addEntriesToRevertList(const QList<QDeclarativeAction> &actions);
+ QVariant valueInRevertList(QObject *target, const QString &name) const;
+ QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QString &name) const;
+
+ bool isStateActive() const;
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarativeState)
+ Q_DISABLE_COPY(QDeclarativeState)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeStateOperation)
+QML_DECLARE_TYPE(QDeclarativeState)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATE_H
diff --git a/src/declarative/util/qdeclarativestate_p_p.h b/src/quick/util/qdeclarativestate_p_p.h
index 55aeecde11..55aeecde11 100644
--- a/src/declarative/util/qdeclarativestate_p_p.h
+++ b/src/quick/util/qdeclarativestate_p_p.h
diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/quick/util/qdeclarativestategroup.cpp
index 51e27e4bf0..51e27e4bf0 100644
--- a/src/declarative/util/qdeclarativestategroup.cpp
+++ b/src/quick/util/qdeclarativestategroup.cpp
diff --git a/src/quick/util/qdeclarativestategroup_p.h b/src/quick/util/qdeclarativestategroup_p.h
new file mode 100644
index 0000000000..0ddc3db312
--- /dev/null
+++ b/src/quick/util/qdeclarativestategroup_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESTATEGROUP_H
+#define QDECLARATIVESTATEGROUP_H
+
+#include "qdeclarativestate_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeStateGroupPrivate;
+class Q_QUICK_EXPORT QDeclarativeStateGroup : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_DECLARE_PRIVATE(QDeclarativeStateGroup)
+
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeState> states READ statesProperty DESIGNABLE false)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitionsProperty DESIGNABLE false)
+
+public:
+ QDeclarativeStateGroup(QObject * = 0);
+ virtual ~QDeclarativeStateGroup();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QDeclarativeListProperty<QDeclarativeState> statesProperty();
+ QList<QDeclarativeState *> states() const;
+
+ QDeclarativeListProperty<QDeclarativeTransition> transitionsProperty();
+
+ QDeclarativeState *findState(const QString &name) const;
+ void removeState(QDeclarativeState *state);
+
+ virtual void classBegin();
+ virtual void componentComplete();
+Q_SIGNALS:
+ void stateChanged(const QString &);
+
+private:
+ friend class QDeclarativeState;
+ friend class QDeclarativeStatePrivate;
+ bool updateAutoState();
+ void stateAboutToComplete();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeStateGroup)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATEGROUP_H
diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/quick/util/qdeclarativestateoperations.cpp
index d8a5369568..d8a5369568 100644
--- a/src/declarative/util/qdeclarativestateoperations.cpp
+++ b/src/quick/util/qdeclarativestateoperations.cpp
diff --git a/src/quick/util/qdeclarativestateoperations_p.h b/src/quick/util/qdeclarativestateoperations_p.h
new file mode 100644
index 0000000000..872a296025
--- /dev/null
+++ b/src/quick/util/qdeclarativestateoperations_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESTATEOPERATIONS_H
+#define QDECLARATIVESTATEOPERATIONS_H
+
+#include "qdeclarativestate_p.h"
+#include <qdeclarativescriptstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeStateChangeScriptPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeStateChangeScript : public QDeclarativeStateOperation, public QDeclarativeActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeStateChangeScript)
+
+ Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QDeclarativeStateChangeScript(QObject *parent=0);
+ ~QDeclarativeStateChangeScript();
+
+ virtual ActionList actions();
+
+ virtual QString typeName() const;
+
+ QDeclarativeScriptString script() const;
+ void setScript(const QDeclarativeScriptString &);
+
+ QString name() const;
+ void setName(const QString &);
+
+ virtual void execute(Reason reason = ActualChange);
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeStateChangeScript)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATEOPERATIONS_H
diff --git a/src/declarative/util/qdeclarativestyledtext.cpp b/src/quick/util/qdeclarativestyledtext.cpp
index 1c7ca5fbfd..1c7ca5fbfd 100644
--- a/src/declarative/util/qdeclarativestyledtext.cpp
+++ b/src/quick/util/qdeclarativestyledtext.cpp
diff --git a/src/declarative/util/qdeclarativestyledtext_p.h b/src/quick/util/qdeclarativestyledtext_p.h
index beffb4d22a..beffb4d22a 100644
--- a/src/declarative/util/qdeclarativestyledtext_p.h
+++ b/src/quick/util/qdeclarativestyledtext_p.h
diff --git a/src/declarative/util/qdeclarativesvgparser.cpp b/src/quick/util/qdeclarativesvgparser.cpp
index e8ceb2116c..e8ceb2116c 100644
--- a/src/declarative/util/qdeclarativesvgparser.cpp
+++ b/src/quick/util/qdeclarativesvgparser.cpp
diff --git a/src/declarative/util/qdeclarativesvgparser_p.h b/src/quick/util/qdeclarativesvgparser_p.h
index 0d7be10761..0d7be10761 100644
--- a/src/declarative/util/qdeclarativesvgparser_p.h
+++ b/src/quick/util/qdeclarativesvgparser_p.h
diff --git a/src/declarative/util/qdeclarativesystempalette.cpp b/src/quick/util/qdeclarativesystempalette.cpp
index 61d8406141..61d8406141 100644
--- a/src/declarative/util/qdeclarativesystempalette.cpp
+++ b/src/quick/util/qdeclarativesystempalette.cpp
diff --git a/src/quick/util/qdeclarativesystempalette_p.h b/src/quick/util/qdeclarativesystempalette_p.h
new file mode 100644
index 0000000000..25224fd4d1
--- /dev/null
+++ b/src/quick/util/qdeclarativesystempalette_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVESYSTEMPALETTE_H
+#define QDECLARATIVESYSTEMPALETTE_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QPalette>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSystemPalettePrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeSystemPalette : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ColorGroup)
+ Q_DECLARE_PRIVATE(QDeclarativeSystemPalette)
+
+ Q_PROPERTY(QDeclarativeSystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
+ Q_PROPERTY(QColor window READ window NOTIFY paletteChanged)
+ Q_PROPERTY(QColor windowText READ windowText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor base READ base NOTIFY paletteChanged)
+ Q_PROPERTY(QColor text READ text NOTIFY paletteChanged)
+ Q_PROPERTY(QColor alternateBase READ alternateBase NOTIFY paletteChanged)
+ Q_PROPERTY(QColor button READ button NOTIFY paletteChanged)
+ Q_PROPERTY(QColor buttonText READ buttonText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor light READ light NOTIFY paletteChanged)
+ Q_PROPERTY(QColor midlight READ midlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor dark READ dark NOTIFY paletteChanged)
+ Q_PROPERTY(QColor mid READ mid NOTIFY paletteChanged)
+ Q_PROPERTY(QColor shadow READ shadow NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged)
+
+public:
+ QDeclarativeSystemPalette(QObject *parent=0);
+ ~QDeclarativeSystemPalette();
+
+ enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
+
+ QColor window() const;
+ QColor windowText() const;
+
+ QColor base() const;
+ QColor text() const;
+ QColor alternateBase() const;
+
+ QColor button() const;
+ QColor buttonText() const;
+
+ QColor light() const;
+ QColor midlight() const;
+ QColor dark() const;
+ QColor mid() const;
+ QColor shadow() const;
+
+ QColor highlight() const;
+ QColor highlightedText() const;
+
+ QDeclarativeSystemPalette::ColorGroup colorGroup() const;
+ void setColorGroup(QDeclarativeSystemPalette::ColorGroup);
+
+Q_SIGNALS:
+ void paletteChanged();
+
+private:
+ bool eventFilter(QObject *watched, QEvent *event);
+ bool event(QEvent *event);
+
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeSystemPalette)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESYSTEMPALETTE_H
diff --git a/src/declarative/util/qdeclarativetimeline.cpp b/src/quick/util/qdeclarativetimeline.cpp
index 7066d3d062..7066d3d062 100644
--- a/src/declarative/util/qdeclarativetimeline.cpp
+++ b/src/quick/util/qdeclarativetimeline.cpp
diff --git a/src/declarative/util/qdeclarativetimeline_p_p.h b/src/quick/util/qdeclarativetimeline_p_p.h
index d84053903f..d84053903f 100644
--- a/src/declarative/util/qdeclarativetimeline_p_p.h
+++ b/src/quick/util/qdeclarativetimeline_p_p.h
diff --git a/src/declarative/util/qdeclarativetimer.cpp b/src/quick/util/qdeclarativetimer.cpp
index a4a2362680..a4a2362680 100644
--- a/src/declarative/util/qdeclarativetimer.cpp
+++ b/src/quick/util/qdeclarativetimer.cpp
diff --git a/src/quick/util/qdeclarativetimer_p.h b/src/quick/util/qdeclarativetimer_p.h
new file mode 100644
index 0000000000..acf728236d
--- /dev/null
+++ b/src/quick/util/qdeclarativetimer_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVETIMER_H
+#define QDECLARATIVETIMER_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractanimation.h>
+
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeTimerPrivate;
+class Q_QUICK_PRIVATE_EXPORT QDeclarativeTimer : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeTimer)
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged)
+ Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
+ Q_PROPERTY(QObject *parent READ parent CONSTANT)
+
+public:
+ QDeclarativeTimer(QObject *parent=0);
+
+ void setInterval(int interval);
+ int interval() const;
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ bool isRepeating() const;
+ void setRepeating(bool repeating);
+
+ bool triggeredOnStart() const;
+ void setTriggeredOnStart(bool triggeredOnStart);
+
+protected:
+ void classBegin();
+ void componentComplete();
+
+public Q_SLOTS:
+ void start();
+ void stop();
+ void restart();
+
+Q_SIGNALS:
+ void triggered();
+ void runningChanged();
+ void intervalChanged();
+ void repeatChanged();
+ void triggeredOnStartChanged();
+
+private:
+ void update();
+
+private Q_SLOTS:
+ void ticked();
+ void finished();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeTimer)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/quick/util/qdeclarativetransition.cpp
index 916e599cc6..916e599cc6 100644
--- a/src/declarative/util/qdeclarativetransition.cpp
+++ b/src/quick/util/qdeclarativetransition.cpp
diff --git a/src/quick/util/qdeclarativetransition_p.h b/src/quick/util/qdeclarativetransition_p.h
new file mode 100644
index 0000000000..439458b6af
--- /dev/null
+++ b/src/quick/util/qdeclarativetransition_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVETRANSITION_H
+#define QDECLARATIVETRANSITION_H
+
+#include "qdeclarativestate_p.h"
+
+#include <qdeclarative.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAbstractAnimation;
+class QDeclarativeTransitionPrivate;
+class QDeclarativeTransitionManager;
+class Q_QUICK_EXPORT QDeclarativeTransition : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeTransition)
+
+ Q_PROPERTY(QString from READ fromState WRITE setFromState NOTIFY fromChanged)
+ Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged)
+ Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_CLASSINFO("DeferredPropertyNames", "animations")
+
+public:
+ QDeclarativeTransition(QObject *parent=0);
+ ~QDeclarativeTransition();
+
+ QString fromState() const;
+ void setFromState(const QString &);
+
+ QString toState() const;
+ void setToState(const QString &);
+
+ bool reversible() const;
+ void setReversible(bool);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations();
+
+ void prepare(QDeclarativeStateOperation::ActionList &actions,
+ QList<QDeclarativeProperty> &after,
+ QDeclarativeTransitionManager *end);
+
+ void setReversed(bool r);
+ void stop();
+
+Q_SIGNALS:
+ void fromChanged();
+ void toChanged();
+ void reversibleChanged();
+ void enabledChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeTransition)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVETRANSITION_H
diff --git a/src/declarative/util/qdeclarativetransitionmanager.cpp b/src/quick/util/qdeclarativetransitionmanager.cpp
index 2dd1da70ed..2dd1da70ed 100644
--- a/src/declarative/util/qdeclarativetransitionmanager.cpp
+++ b/src/quick/util/qdeclarativetransitionmanager.cpp
diff --git a/src/declarative/util/qdeclarativetransitionmanager_p_p.h b/src/quick/util/qdeclarativetransitionmanager_p_p.h
index 94a2dd1539..94a2dd1539 100644
--- a/src/declarative/util/qdeclarativetransitionmanager_p_p.h
+++ b/src/quick/util/qdeclarativetransitionmanager_p_p.h
diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/quick/util/qdeclarativeutilmodule.cpp
index 2e82364a42..2e82364a42 100644
--- a/src/declarative/util/qdeclarativeutilmodule.cpp
+++ b/src/quick/util/qdeclarativeutilmodule.cpp
diff --git a/src/quick/util/qdeclarativeutilmodule_p.h b/src/quick/util/qdeclarativeutilmodule_p.h
new file mode 100644
index 0000000000..13739c8170
--- /dev/null
+++ b/src/quick/util/qdeclarativeutilmodule_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 QDECLARATIVEUTILMODULE_H
+#define QDECLARATIVEUTILMODULE_H
+
+#include <qdeclarative.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeUtilModule
+{
+public:
+ static void defineModule();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEUTILMODULE_H
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
new file mode 100644
index 0000000000..9c8964bfef
--- /dev/null
+++ b/src/quick/util/util.pri
@@ -0,0 +1,59 @@
+SOURCES += \
+ $$PWD/qdeclarativeutilmodule.cpp\
+ $$PWD/qdeclarativeconnections.cpp \
+ $$PWD/qdeclarativepackage.cpp \
+ $$PWD/qdeclarativeanimation.cpp \
+ $$PWD/qdeclarativesystempalette.cpp \
+ $$PWD/qdeclarativespringanimation.cpp \
+ $$PWD/qdeclarativesmoothedanimation.cpp \
+ $$PWD/qdeclarativestate.cpp\
+ $$PWD/qdeclarativetransitionmanager.cpp \
+ $$PWD/qdeclarativestateoperations.cpp \
+ $$PWD/qdeclarativepropertychanges.cpp \
+ $$PWD/qdeclarativestategroup.cpp \
+ $$PWD/qdeclarativetransition.cpp \
+ $$PWD/qdeclarativelistaccessor.cpp \
+ $$PWD/qdeclarativetimeline.cpp \
+ $$PWD/qdeclarativetimer.cpp \
+ $$PWD/qdeclarativebind.cpp \
+ $$PWD/qdeclarativepixmapcache.cpp \
+ $$PWD/qdeclarativebehavior.cpp \
+ $$PWD/qdeclarativefontloader.cpp \
+ $$PWD/qdeclarativestyledtext.cpp \
+ $$PWD/qdeclarativepath.cpp \
+ $$PWD/qdeclarativechangeset.cpp \
+ $$PWD/qdeclarativelistcompositor.cpp \
+ $$PWD/qdeclarativepathinterpolator.cpp \
+ $$PWD/qdeclarativesvgparser.cpp
+
+HEADERS += \
+ $$PWD/qdeclarativeutilmodule_p.h\
+ $$PWD/qdeclarativeconnections_p.h \
+ $$PWD/qdeclarativepackage_p.h \
+ $$PWD/qdeclarativeanimation_p.h \
+ $$PWD/qdeclarativeanimation_p_p.h \
+ $$PWD/qdeclarativesystempalette_p.h \
+ $$PWD/qdeclarativespringanimation_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p_p.h \
+ $$PWD/qdeclarativestate_p.h\
+ $$PWD/qdeclarativestateoperations_p.h \
+ $$PWD/qdeclarativepropertychanges_p.h \
+ $$PWD/qdeclarativestate_p_p.h\
+ $$PWD/qdeclarativetransitionmanager_p_p.h \
+ $$PWD/qdeclarativestategroup_p.h \
+ $$PWD/qdeclarativetransition_p.h \
+ $$PWD/qdeclarativelistaccessor_p.h \
+ $$PWD/qdeclarativetimeline_p_p.h \
+ $$PWD/qdeclarativetimer_p.h \
+ $$PWD/qdeclarativebind_p.h \
+ $$PWD/qdeclarativepixmapcache_p.h \
+ $$PWD/qdeclarativebehavior_p.h \
+ $$PWD/qdeclarativefontloader_p.h \
+ $$PWD/qdeclarativestyledtext_p.h \
+ $$PWD/qdeclarativepath_p.h \
+ $$PWD/qdeclarativepath_p_p.h \
+ $$PWD/qdeclarativechangeset_p.h \
+ $$PWD/qdeclarativelistcompositor_p.h \
+ $$PWD/qdeclarativepathinterpolator_p.h \
+ $$PWD/qdeclarativesvgparser_p.h
diff --git a/src/src.pro b/src/src.pro
index 3f71db2472..7518ccf8da 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS += declarative qtquick1 plugins
+SUBDIRS += declarative quick qtquick1 plugins
contains(QT_CONFIG, qmltest): SUBDIRS += qmltest
diff --git a/sync.profile b/sync.profile
index 55c3cdbad3..1b49f58b56 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,5 +1,6 @@
%modules = ( # path to module name map
"QtDeclarative" => "$basedir/src/declarative",
+ "QtQuick" => "$basedir/src/quick",
"QtQuick1" => "$basedir/src/qtquick1",
"QtQuickTest" => "$basedir/src/qmltest",
"QtQmlDevTools" => "$basedir/src/qmldevtools",
@@ -18,10 +19,92 @@
);
%modulepris = (
"QtDeclarative" => "$basedir/modules/qt_declarative.pri",
+ "QtQuick" => "$basedir/modules/qt_quick.pri",
"QtQuick1" => "$basedir/modules/qt_qtquick1.pri",
"QtQuickTest" => "$basedir/modules/qt_qmltest.pri",
"QtQmlDevTools" => "$basedir/modules/qt_qmldevtools.pri",
);
+%deprecatedheaders = (
+ "QtDeclarative" => {
+ "qquickcanvas.h" => "QtQuick/qquickcanvas.h",
+ "qquickitem.h" => "QtQuick/qquickitem.h",
+ "qquickpainteditem.h" => "QtQuick/qquickpainteditem.h",
+ "qquickview.h" => "QtQuick/qquickview.h",
+ "QQuickCanvas" => "QtQuick/QQuickCanvas",
+ "QQuickItem" => "QtQuick/QQuickItem",
+ "QQuickPaintedItem" => "QtQuick/QQuickPaintedItem",
+ "QQuickView" => "QtQuick/QQuickView",
+ "QQuickTransform" => "QtQuick/QQuickTransform",
+ "designersupport.h" => "QtQuick/designersupport.h",
+ "qsgengine.h" => "QtQuick/qsgengine.h",
+ "qsgflatcolormaterial.h" => "QtQuick/qsgflatcolormaterial.h",
+ "qsggeometry.h" => "QtQuick/qsggeometry.h",
+ "qsgmaterial.h" => "QtQuick/qsgmaterial.h",
+ "qsgnode.h" => "QtQuick/qsgnode.h",
+ "qsgsimplematerial.h" => "QtQuick/qsgsimplematerial.h",
+ "qsgsimplerectnode.h" => "QtQuick/qsgsimplerectnode.h",
+ "qsgsimpletexturenode.h" => "QtQuick/qsgsimpletexturenode.h",
+ "qsgtexture.h" => "QtQuick/qsgtexture.h",
+ "qsgtexturematerial.h" => "QtQuick/qsgtexturematerial.h",
+ "qsgvertexcolormaterial.h" => "QtQuick/qsgvertexcolormaterial.h",
+ "QSGBasicGeometryNode" => "QtQuick/QSGBasicGeometryNode",
+ "QSGClipNode" => "QtQuick/QSGClipNode",
+ "QSGDynamicTexture" => "QtQuick/QSGDynamicTexture",
+ "QSGEngine" => "QtQuick/QSGEngine",
+ "QSGFlatColorMaterial" => "QtQuick/QSGFlatColorMaterial",
+ "QSGGeometry" => "QtQuick/QSGGeometry",
+ "QSGGeometryNode" => "QtQuick/QSGGeometryNode",
+ "QSGMaterial" => "QtQuick/QSGMaterial",
+ "QSGMaterialShader" => "QtQuick/QSGMaterialShader",
+ "QSGMaterialType" => "QtQuick/QSGMaterialType",
+ "QSGNode" => "QtQuick/QSGNode",
+ "QSGNodeVisitor" => "QtQuick/QSGNodeVisitor",
+ "QSGOpacityNode" => "QtQuick/QSGOpacityNode",
+ "QSGOpaqueTextureMaterial" => "QtQuick/QSGOpaqueTextureMaterial",
+ "QSGRootNode" => "QtQuick/QSGRootNode",
+ "QSGSimpleMaterial" => "QtQuick/QSGSimpleMaterial",
+ "QSGSimpleMaterialComparableMaterial" => "QtQuick/QSGSimpleMaterialComparableMaterial",
+ "QSGSimpleMaterialShader" => "QtQuick/QSGSimpleMaterialShader",
+ "QSGSimpleRectNode" => "QtQuick/QSGSimpleRectNode",
+ "QSGSimpleTextureNode" => "QtQuick/QSGSimpleTextureNode",
+ "QSGTexture" => "QtQuick/QSGTexture",
+ "QSGTextureMaterial" => "QtQuick/QSGTextureMaterial",
+ "QSGTransformNode" => "QtQuick/QSGTransformNode",
+ "QSGVertexColorMaterial" => "QtQuick/QSGVertexColorMaterial",
+ "qquickanchors_p.h" => "QtQuick/private/qquickanchors_p.h",
+ "qquickcanvasitem_p.h" => "QtQuick/private/qquickcanvasitem_p.h",
+ "qquickcontext2d_p.h" => "QtQuick/private/qquickcontext2d_p.h",
+ "qquickevents_p_p.h" => "QtQuick/private/qquickevents_p_p.h",
+ "qquickmousearea_p.h" => "QtQuick/private/qquickmousearea_p.h",
+ "qquickpositioners_p.h" => "QtQuick/private/qquickpositioners_p.h",
+ "qquickrectangle_p.h" => "QtQuick/private/qquickrectangle_p.h",
+ "qquickscalegrid_p.h" => "QtQuick/private/qquickscalegrid_p.h",
+ "qquickshadereffectmesh_p.h" => "QtQuick/private/qquickshadereffectmesh_p.h",
+ "qquickshadereffectsource_p.h" => "QtQuick/private/qquickshadereffectsource_p.h",
+ "qquicktext_p.h" => "QtQuick/private/qquicktext_p.h",
+ "qquickvisualdatamodel_p.h" => "QtQuick/private/qquickvisualdatamodel_p.h",
+ "qsgnodeupdater_p.h" => "QtQuick/private/qsgnodeupdater_p.h",
+ "qsgrenderer_p.h" => "QtQuick/private/qsgrenderer_p.h",
+ "qsgadaptionlayer_p.h" => "QtQuick/private/qsgadaptionlayer_p.h",
+ "qsgcontext_p.h" => "QtQuick/private/qsgcontext_p.h",
+ "qsgcontextplugin_p.h" => "QtQuick/private/qsgcontextplugin_p.h",
+ "qsgdefaultdistancefieldglyphcache_p.h" => "QtQuick/private/qsgdefaultdistancefieldglyphcache_p.h",
+ "qsgareaallocator_p.h" => "QtQuick/private/qsgareaallocator_p.h",
+ "qsgdistancefieldutil_p.h" => "QtQuick/private/qsgdistancefieldutil_p.h",
+ "qsgpainternode_p.h" => "QtQuick/private/qsgpainternode_p.h",
+ "qsgtexture_p.h" => "QtQuick/private/qsgtexture_p.h",
+ "qsgtexturematerial_p.h" => "QtQuick/private/qsgtexturematerial_p.h",
+ "qsgtextureprovider_p.h" => "QtQuick/private/qsgtextureprovider_p.h",
+ "qdeclarativeanimation_p.h" => "QtQuick/private/qdeclarativeanimation_p.h",
+ "qdeclarativebehavior_p.h" => "QtQuick/private/qdeclarativebehavior_p.h",
+ "qdeclarativepixmapcache_p.h" => "QtQuick/private/qdeclarativepixmapcache_p.h",
+ "qdeclarativepropertychanges_p.h" => "QtQuick/private/qdeclarativepropertychanges_p.h",
+ "qdeclarativestate_p.h" => "QtQuick/private/qdeclarativestate_p.h",
+ "qdeclarativestategroup_p.h" => "QtQuick/private/qdeclarativestategroup_p.h",
+ "qdeclarativetimer_p.h" => "QtQuick/private/qdeclarativetimer_p.h",
+ "qdeclarativetransition_p.h" => "QtQuick/private/qdeclarativetransition_p.h",
+ }
+);
# Module dependencies.
# Every module that is required to build this module should have one entry.
# Each of the module version specifiers can take one of the following values:
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index c3ec7231cc..c4ed5aeee8 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -1,6 +1,7 @@
TEMPLATE=subdirs
SUBDIRS=\
declarative \
+ qtquick2 \
particles
# ### refactor: port properly
diff --git a/tests/auto/declarative/debugger/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp b/tests/auto/declarative/debugger/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
index 105700eedc..8967b844df 100644
--- a/tests/auto/declarative/debugger/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
@@ -51,7 +51,7 @@
//QDeclarativeDebugTest
#include "../shared/debugutil_p.h"
-#include "../../shared/util.h"
+#include "../../../shared/util.h"
const char *SEQ = "seq";
const char *TYPE = "type";
diff --git a/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
index 21aeca9040..6754503de9 100644
--- a/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
@@ -50,7 +50,7 @@
#include <private/qdeclarativedebugclient_p.h>
#include <private/qdeclarativedebugservice_p.h>
-#include "../../shared/util.h"
+#include "../../../shared/util.h"
#include "../shared/debugutil_p.h"
#define PORT 13769
diff --git a/tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp b/tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp
index fc2f0d6626..3b5311e617 100644
--- a/tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativedebugtrace/tst_qdeclarativedebugtrace.cpp
@@ -44,7 +44,7 @@
#include "QtDeclarative/private/qdeclarativedebugtrace_p.h"
#include "../shared/debugutil_p.h"
-#include "../../shared/util.h"
+#include "../../../shared/util.h"
#define PORT 13773
#define STR_PORT "13773"
diff --git a/tests/auto/declarative/debugger/qdeclarativeenginedebug/qdeclarativeenginedebug.pro b/tests/auto/declarative/debugger/qdeclarativeenginedebug/qdeclarativeenginedebug.pro
index 4805f37e55..6b414d3c32 100644
--- a/tests/auto/declarative/debugger/qdeclarativeenginedebug/qdeclarativeenginedebug.pro
+++ b/tests/auto/declarative/debugger/qdeclarativeenginedebug/qdeclarativeenginedebug.pro
@@ -8,4 +8,4 @@ SOURCES += tst_qdeclarativeenginedebug.cpp \
CONFIG += parallel_test declarative_debug
-QT += core-private declarative-private v8-private testlib
+QT += core-private declarative-private quick-private v8-private testlib
diff --git a/tests/auto/declarative/debugger/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp b/tests/auto/declarative/debugger/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp
index f48b281d3a..d5e4696936 100644
--- a/tests/auto/declarative/debugger/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp
@@ -50,7 +50,7 @@
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativeexpression.h>
#include <QtDeclarative/qdeclarativeproperty.h>
-#include <QtDeclarative/qquickitem.h>
+#include <QtQuick/qquickitem.h>
#include <private/qdeclarativebinding_p.h>
#include <private/qdeclarativeboundsignal_p.h>
diff --git a/tests/auto/declarative/debugger/qdeclarativeinspector/app/app.pro b/tests/auto/declarative/debugger/qdeclarativeinspector/app/app.pro
index 7b6783b112..90595df881 100644
--- a/tests/auto/declarative/debugger/qdeclarativeinspector/app/app.pro
+++ b/tests/auto/declarative/debugger/qdeclarativeinspector/app/app.pro
@@ -1,5 +1,5 @@
TARGET = app
-QT += declarative widgets qtquick1
+QT += declarative quick widgets qtquick1
CONFIG += declarative_debug
macx:CONFIG -= app_bundle
diff --git a/tests/auto/declarative/debugger/qdeclarativeinspector/app/main.cpp b/tests/auto/declarative/debugger/qdeclarativeinspector/app/main.cpp
index c851222461..67d0a4499e 100644
--- a/tests/auto/declarative/debugger/qdeclarativeinspector/app/main.cpp
+++ b/tests/auto/declarative/debugger/qdeclarativeinspector/app/main.cpp
@@ -41,7 +41,7 @@
#include <QtCore/QDebug>
#include <QtCore/QStringList>
-#include <QtDeclarative/QQuickView>
+#include <QtQuick/QQuickView>
#include <QtGui/QGuiApplication>
#include <QtQuick1/QDeclarativeView>
diff --git a/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
index 00ed1317a0..0739c746b9 100644
--- a/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
+++ b/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
@@ -44,7 +44,7 @@
#include "QtDeclarative/private/qv8profilerservice_p.h"
#include "../shared/debugutil_p.h"
-#include "../../shared/util.h"
+#include "../../../shared/util.h"
#define PORT 13774
#define STR_PORT "13774"
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 708127289b..8e52392941 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -4,9 +4,6 @@ METATYPETESTS += \
qdeclarativemetatype
PUBLICTESTS += \
- examples \
- geometry \
- nodes \
parserstress \
qdeclarativecomponent \
qdeclarativeconsole \
@@ -19,7 +16,6 @@ PUBLICTESTS += \
qdeclarativelistreference \
qdeclarativelocale \
qdeclarativemoduleplugin \
- qdeclarativepixmapcache \
qdeclarativeqt \
qdeclarativetranslation \
qdeclarativexmlhttprequest \
@@ -30,76 +26,28 @@ PUBLICTESTS += \
qmlplugindump
PRIVATETESTS += \
- qdeclarativeanimations \
- qdeclarativeapplication \
- qdeclarativebehaviors \
qdeclarativebinding \
qdeclarativechangeset \
qdeclarativeconnection \
qdeclarativecpputils \
qdeclarativeecmascript \
qdeclarativeexpression \
- qdeclarativefontloader \
qdeclarativeimageprovider \
qdeclarativeinstruction \
qdeclarativelanguage \
qdeclarativelistcompositor \
qdeclarativelistmodel \
- qdeclarativepath \
qdeclarativeproperty \
qdeclarativepropertymap \
- qdeclarativesmoothedanimation \
- qdeclarativespringanimation \
qdeclarativesqldatabase \
- qdeclarativestates \
- qdeclarativestyledtext \
- qdeclarativesystempalette \
- qdeclarativetimer \
qdeclarativevaluetypes \
qdeclarativeworkerscript \
- qdeclarativexmllistmodel \
v4
-# This test requires the xmlpatterns module
-!contains(QT_CONFIG,xmlpatterns):PRIVATETESTS -= qdeclarativexmllistmodel
-
-QUICKTESTS = \
- qquickanchors \
- qquickanimatedimage \
- qquickborderimage \
- qquickcanvas \
- qquickcanvasitem \
- qquickdrag \
- qquickdroparea \
- qquickflickable \
- qquickflipable \
- qquickfocusscope \
- qquickgridview \
- qquickimage \
- qquickitem \
- qquickitem2 \
- qquicklistview \
- qquickloader \
- qquickmousearea \
- qquickmultipointtoucharea \
- qquickpathview \
- qquickpincharea \
- qquickpositioners \
- qquickrepeater \
- qquickshadereffect \
- qquickspriteimage \
- qquicktext \
- qquicktextedit \
- qquicktextinput \
- qquickview \
- qquickvisualdatamodel \
-
-
SUBDIRS += $$PUBLICTESTS
SUBDIRS += $$METATYPETESTS
SUBDIRS += debugger
contains(QT_CONFIG, private_tests) {
SUBDIRS += $$PRIVATETESTS
- SUBDIRS += $$QUICKTESTS
}
diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro
deleted file mode 100644
index d70040d6ec..0000000000
--- a/tests/auto/declarative/examples/examples.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-CONFIG += testcase
-TARGET = tst_examples
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_examples.cpp
-DEFINES += SRCDIR=\\\"$$PWD\\\"
-
-CONFIG += parallel_test
-#temporary
-QT += core-private gui-private declarative-private qtquick1-private widgets-private v8-private testlib
diff --git a/tests/auto/declarative/examples/tst_examples.cpp b/tests/auto/declarative/examples/tst_examples.cpp
deleted file mode 100644
index bacd25d0da..0000000000
--- a/tests/auto/declarative/examples/tst_examples.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QLibraryInfo>
-#include <QDir>
-#include <QProcess>
-#include <QDebug>
-#include <QQuickItem>
-#include <QQuickView>
-#include <QDeclarativeComponent>
-#include <QDeclarativeEngine>
-#include <QDeclarativeError>
-
-class tst_examples : public QObject
-{
- Q_OBJECT
-public:
- tst_examples();
-
-private slots:
- void sgexamples_data();
- void sgexamples();
-
- void namingConvention();
-private:
- QStringList excludedDirs;
- QStringList excludedFiles;
-
- void namingConvention(const QDir &);
- QStringList findQmlFiles(const QDir &);
-
- QDeclarativeEngine engine;
-};
-
-tst_examples::tst_examples()
-{
- // Add files to exclude here
- excludedFiles << "doc/src/snippets/declarative/listmodel.qml"; //Just a ListModel, no root QQuickItem
-
- // Add directories you want excluded here
- excludedDirs << "examples/declarative/text/fonts"; // QTBUG-21415
-
- // Not run in QQuickView
- excludedDirs << "examples/declarative/qtquick1";
-
- // These snippets are not expected to run on their own.
- excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex";
- excludedDirs << "doc/src/snippets/declarative/qtbinding";
- excludedDirs << "doc/src/snippets/declarative/imports";
- excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
- excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
- excludedDirs << "doc/src/snippets/qtquick1/imports";
-
-#ifdef QT_NO_WEBKIT
- excludedDirs << "examples/declarative/modelviews/webview";
- excludedDirs << "examples/declarative/webbrowser";
- excludedDirs << "doc/src/snippets/declarative/webview";
- excludedDirs << "doc/src/snippets/qtquick1/webview";
-#endif
-
-#ifdef QT_NO_XMLPATTERNS
- excludedDirs << "examples/declarative/xml/xmldata";
- excludedDirs << "examples/declarative/twitter";
- excludedDirs << "examples/declarative/flickr";
- excludedDirs << "examples/declarative/photoviewer";
-#endif
-}
-
-/*
-This tests that the examples follow the naming convention required
-to have them tested by the examples() test.
-*/
-void tst_examples::namingConvention(const QDir &d)
-{
- for (int ii = 0; ii < excludedDirs.count(); ++ii) {
- QString s = excludedDirs.at(ii);
- if (d.absolutePath().endsWith(s))
- return;
- }
-
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
-
- bool seenQml = !files.isEmpty();
- bool seenLowercase = false;
-
- foreach (const QString &file, files) {
- if (file.at(0).isLower())
- seenLowercase = true;
- }
-
- if (!seenQml) {
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
- QDir sub = d;
- sub.cd(dir);
- namingConvention(sub);
- }
- } else if(!seenLowercase) {
- QFAIL(qPrintable(QString(
- "Directory %1 violates naming convention; expected at least one qml file "
- "starting with lower case, got: %2"
- ).arg(d.absolutePath()).arg(files.join(","))));
- }
-}
-
-void tst_examples::namingConvention()
-{
- QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
-
- namingConvention(QDir(examples));
-}
-
-QStringList tst_examples::findQmlFiles(const QDir &d)
-{
- for (int ii = 0; ii < excludedDirs.count(); ++ii) {
- QString s = excludedDirs.at(ii);
- if (d.absolutePath().endsWith(s))
- return QStringList();
- }
-
- QStringList rv;
-
- QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
- if (cppfiles.isEmpty()) {
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
- foreach (const QString &file, files) {
- if (file.at(0).isLower()) {
- bool superContinue = false;
- for (int ii = 0; ii < excludedFiles.count(); ++ii) {
- QString e = excludedFiles.at(ii);
- if (d.absoluteFilePath(file).endsWith(e)) {
- superContinue = true;
- break;
- }
- }
- if (superContinue)
- continue;
- rv << d.absoluteFilePath(file);
- }
- }
- }
-
-
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
- QDir sub = d;
- sub.cd(dir);
- rv << findQmlFiles(sub);
- }
-
- return rv;
-}
-
-/*
-This test runs all the examples in the declarative UI source tree and ensures
-that they start and exit cleanly.
-
-Examples are any .qml files under the examples/ directory that start
-with a lower case letter.
-*/
-static void silentErrorsMsgHandler(QtMsgType, const char *)
-{
-}
-
-
-void tst_examples::sgexamples_data()
-{
- QTest::addColumn<QString>("file");
-
- QString examples = QLatin1String(SRCDIR) + "/../../../../examples/declarative/";
- QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/declarative";
-
- QStringList files;
- files << findQmlFiles(QDir(examples));
- files << findQmlFiles(QDir(snippets));
-
- foreach (const QString &file, files)
- QTest::newRow(qPrintable(file)) << file;
-}
-
-void tst_examples::sgexamples()
-{
- QFETCH(QString, file);
-
- QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
- qInstallMsgHandler(old);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(file));
- if (component.status() == QDeclarativeComponent::Error)
- qWarning() << component.errors();
- QCOMPARE(component.status(), QDeclarativeComponent::Ready);
-
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
- QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
- if (!root)
- component.completeCreate();
- QVERIFY(root);
-
- QQuickCanvas canvas;
- root->setParentItem(canvas.rootItem());
- component.completeCreate();
- canvas.show();
-
- QTest::qWaitForWindowShown(&canvas);
-
-}
-
-QTEST_MAIN(tst_examples)
-
-#include "tst_examples.moc"
diff --git a/tests/auto/declarative/geometry/geometry.pro b/tests/auto/declarative/geometry/geometry.pro
deleted file mode 100644
index a66399a6e0..0000000000
--- a/tests/auto/declarative/geometry/geometry.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-CONFIG += testcase
-TARGET = tst_geometry
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_geometry.cpp
-
-CONFIG+=parallel_test
-
-QT += core-private gui-private declarative-private opengl testlib
diff --git a/tests/auto/declarative/geometry/tst_geometry.cpp b/tests/auto/declarative/geometry/tst_geometry.cpp
deleted file mode 100644
index 2915902fa4..0000000000
--- a/tests/auto/declarative/geometry/tst_geometry.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt scene graph research project.
-**
-** $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 <QtCore/QString>
-#include <QtTest/QtTest>
-
-#include <qsggeometry.h>
-
-class GeometryTest : public QObject
-{
- Q_OBJECT
-
-public:
-
-private Q_SLOTS:
- void testPoint2D();
- void testTexturedPoint2D();
- void testCustomGeometry();
-
-private:
-};
-
-void GeometryTest::testPoint2D()
-{
- QSGGeometry geometry(QSGGeometry::defaultAttributes_Point2D(), 4, 0);
-
- QCOMPARE(geometry.attributeCount(), 1);
- QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 2);
- QCOMPARE(geometry.vertexCount(), 4);
- QCOMPARE(geometry.indexCount(), 0);
- QVERIFY(geometry.indexData() == 0);
-
- QSGGeometry::updateRectGeometry(&geometry, QRectF(1, 2, 3, 4));
-
- QSGGeometry::Point2D *pts = geometry.vertexDataAsPoint2D();
- QVERIFY(pts != 0);
-
- QCOMPARE(pts[0].x, (float) 1);
- QCOMPARE(pts[0].y, (float) 2);
- QCOMPARE(pts[3].x, (float) 4);
- QCOMPARE(pts[3].y, (float) 6);
-
- // Verify that resize gives me enough allocated data without crashing...
- geometry.allocate(100, 100);
- pts = geometry.vertexDataAsPoint2D();
- quint16 *is = geometry.indexDataAsUShort();
- for (int i=0; i<100; ++i) {
- pts[i].x = i;
- pts[i].y = i + 100;
- is[i] = i;
- }
- QVERIFY(true);
-}
-
-
-void GeometryTest::testTexturedPoint2D()
-{
- QSGGeometry geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4, 0);
-
- QCOMPARE(geometry.attributeCount(), 2);
- QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 4);
- QCOMPARE(geometry.vertexCount(), 4);
- QCOMPARE(geometry.indexCount(), 0);
- QVERIFY(geometry.indexData() == 0);
-
- QSGGeometry::updateTexturedRectGeometry(&geometry, QRectF(1, 2, 3, 4), QRectF(5, 6, 7, 8));
-
- QSGGeometry::TexturedPoint2D *pts = geometry.vertexDataAsTexturedPoint2D();
- QVERIFY(pts != 0);
-
- QCOMPARE(pts[0].x, (float) 1);
- QCOMPARE(pts[0].y, (float) 2);
- QCOMPARE(pts[0].tx, (float) 5);
- QCOMPARE(pts[0].ty, (float) 6);
-
- QCOMPARE(pts[3].x, (float) 4);
- QCOMPARE(pts[3].y, (float) 6);
- QCOMPARE(pts[3].tx, (float) 12);
- QCOMPARE(pts[3].ty, (float) 14);
-
- // Verify that resize gives me enough allocated data without crashing...
- geometry.allocate(100, 100);
- pts = geometry.vertexDataAsTexturedPoint2D();
- quint16 *is = geometry.indexDataAsUShort();
- for (int i=0; i<100; ++i) {
- pts[i].x = i;
- pts[i].y = i + 100;
- pts[i].tx = i + 200;
- pts[i].ty = i + 300;
- is[i] = i;
- }
- QVERIFY(true);
-}
-
-void GeometryTest::testCustomGeometry()
-{
- struct V {
- float x, y;
- unsigned char r, g, b, a;
- float v1, v2, v3, v4;
- };
-
- static QSGGeometry::Attribute attributes[] = {
- { 0, 2, GL_FLOAT },
- { 1, 4, GL_UNSIGNED_BYTE },
- { 2, 4, GL_FLOAT },
- };
- static QSGGeometry::AttributeSet set = { 4, 6 * sizeof(float) + 4 * sizeof(unsigned char), attributes };
-
- QSGGeometry geometry(set, 1000, 4000);
-
- // Verify that space has been allocated.
- quint16 *ii = geometry.indexDataAsUShort();
- for (int i=0; i<geometry.indexCount(); ++i) {
- ii[i] = i;
- }
-
- V *v = (V *) geometry.vertexData();
- for (int i=0; i<geometry.vertexCount(); ++i) {
- v[i].x = 0;
- v[i].y = 1;
- v[i].r = 2;
- v[i].g = 3;
- v[i].b = 4;
- v[i].a = 5;
- v[i].v1 = 6;
- v[i].v2 = 7;
- v[i].v3 = 8;
- v[i].v4 = 9;
- }
-
- // Verify the data's integrity
- for (int i=0; i<4000; ++i)
- QCOMPARE(ii[i], (quint16) i);
- for (int i=0; i<1000; ++i)
- QVERIFY(v[i].v1 == 6);
-
-}
-
-
-QTEST_MAIN(GeometryTest);
-
-#include "tst_geometry.moc"
diff --git a/tests/auto/declarative/nodes/nodes.pro b/tests/auto/declarative/nodes/nodes.pro
deleted file mode 100644
index b622c6a4b3..0000000000
--- a/tests/auto/declarative/nodes/nodes.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-CONFIG += testcase
-TARGET = tst_nodestest
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_nodestest.cpp
-
-CONFIG+=parallel_test
-
-QT += core-private gui-private declarative-private opengl widgets testlib
diff --git a/tests/auto/declarative/nodes/tst_nodestest.cpp b/tests/auto/declarative/nodes/tst_nodestest.cpp
deleted file mode 100644
index d4782f93f4..0000000000
--- a/tests/auto/declarative/nodes/tst_nodestest.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt scene graph research project.
-**
-** $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 <QtCore/QString>
-#include <QtTest/QtTest>
-
-#include <qsgnode.h>
-#include <private/qsgrenderer_p.h>
-#include <private/qsgnodeupdater_p.h>
-
-#include <qsgsimplerectnode.h>
-#include <QtOpenGL/QGLWidget>
-class NodesTest : public QObject
-{
- Q_OBJECT
-
-public:
- NodesTest();
-
-private Q_SLOTS:
- void initTestCase();
- void cleanupTestCase() {
- delete widget;
- }
-
- // Root nodes
- void propegate();
- void propegateWithMultipleRoots();
- void simulatedEffect_data();
- void simulatedEffect();
-
- // Opacity nodes
- void basicOpacityNode();
- void opacityPropegation();
-
- // QSGNodeUpdater
- void isBlockedCheck();
-
-private:
- QGLWidget *widget;
-
- QSGNodeUpdater updater;
-};
-
-void NodesTest::initTestCase()
-{
- widget = new QGLWidget();
- widget->resize(100, 30);
- widget->show();
-}
-
-class DummyRenderer : public QSGRenderer
-{
-public:
- DummyRenderer(QSGRootNode *root)
- : QSGRenderer(QSGContext::createDefaultContext())
- , changedNode(0)
- , changedFlags(0)
- , renderCount(0)
- {
- setRootNode(root);
- }
-
- void render() {
- ++renderCount;
- renderingOrder = ++globalRendereringOrder;
- }
-
- void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) {
- changedNode = node;
- changedFlags = flags;
- QSGRenderer::nodeChanged(node, flags);
- }
-
- QSGNode *changedNode;
- QSGNode::DirtyFlags changedFlags;
-
- int renderCount;
- int renderingOrder;
- static int globalRendereringOrder;
-};
-
-int DummyRenderer::globalRendereringOrder;
-
-NodesTest::NodesTest()
-{
-}
-
-
-void NodesTest::propegate()
-{
- QSGRootNode root;
- QSGNode child; child.setFlag(QSGNode::OwnedByParent, false);
- root.appendChildNode(&child);
-
- DummyRenderer renderer(&root);
-
- child.markDirty(QSGNode::DirtyGeometry);
-
- QCOMPARE(&child, renderer.changedNode);
- QCOMPARE((int) renderer.changedFlags, (int) QSGNode::DirtyGeometry);
-}
-
-
-void NodesTest::propegateWithMultipleRoots()
-{
- QSGRootNode root1;
- QSGNode child2; child2.setFlag(QSGNode::OwnedByParent, false);
- QSGRootNode root3; root3.setFlag(QSGNode::OwnedByParent, false);
- QSGNode child4; child4.setFlag(QSGNode::OwnedByParent, false);
-
- root1.appendChildNode(&child2);
- child2.appendChildNode(&root3);
- root3.appendChildNode(&child4);
-
- DummyRenderer ren1(&root1);
- DummyRenderer ren2(&root3);
-
- child4.markDirty(QSGNode::DirtyGeometry);
-
- QCOMPARE(ren1.changedNode, &child4);
- QCOMPARE(ren2.changedNode, &child4);
-
- QCOMPARE((int) ren1.changedFlags, (int) QSGNode::DirtyGeometry);
- QCOMPARE((int) ren2.changedFlags, (int) QSGNode::DirtyGeometry);
-}
-
-
-
-class SimulatedEffectRenderer : public DummyRenderer
-{
-public:
- SimulatedEffectRenderer(QSGRootNode *root, QSGBasicGeometryNode *c)
- : DummyRenderer(root)
- {
- child = c;
- }
-
- void render() {
- matrix = child->matrix() ? *child->matrix() : QMatrix4x4();
- DummyRenderer::render();
- }
-
- QSGBasicGeometryNode *child;
- QMatrix4x4 matrix;
-};
-
-
-class PseudoEffectNode : public QSGNode {
-public:
- PseudoEffectNode(QSGRenderer *r)
- : renderer(r)
- {
- setFlag(UsePreprocess);
- }
-
- void preprocess() {
-
- if (renderer->rootNode()->parent()) {
- // Mark the root dirty to build a clean state from the root and down
- renderer->rootNode()->markDirty(QSGNode::DirtyForceUpdate);
- }
-
- renderer->renderScene();
-
- if (renderer->rootNode()->parent()) {
- // Mark the parent of the root dirty to force the root and down to be updated.
- renderer->rootNode()->parent()->markDirty(QSGNode::DirtyForceUpdate);
- }
- }
-
- QSGRenderer *renderer;
-};
-
-void NodesTest::simulatedEffect_data()
-{
- QTest::addColumn<bool>("connected");
-
- QTest::newRow("connected") << true;
- QTest::newRow("disconnected") << false;
-}
-
-void NodesTest::simulatedEffect()
-{
- QFETCH(bool, connected);
-
- QSGRootNode root;
- QSGRootNode source;
- QSGTransformNode xform;
- QSGSimpleRectNode geometry;
- geometry.setRect(QRectF(0, 0, 1, 1));
- geometry.setColor(Qt::red);
-
- root.setFlag(QSGNode::OwnedByParent, false);
- source.setFlag(QSGNode::OwnedByParent, false);
- xform.setFlag(QSGNode::OwnedByParent, false);
- geometry.setFlag(QSGNode::OwnedByParent, false);
-
- SimulatedEffectRenderer rootRenderer(&root, &geometry);
- SimulatedEffectRenderer sourceRenderer(&source, &geometry);
-
- PseudoEffectNode effect(&sourceRenderer);
-
- /*
- root Source is redirected into effect using the SimulatedEffectRenderer
- / \
- xform effect
- |
- source
- |
- geometry
- */
-
- root.appendChildNode(&xform);
- root.appendChildNode(&effect);
- if (connected)
- xform.appendChildNode(&source);
- source.appendChildNode(&geometry);
- QMatrix4x4 m; m.translate(1, 2, 3);
- xform.setMatrix(m);
-
- // Clear all dirty states...
- updater.updateStates(&root);
-
- rootRenderer.renderScene();
-
- // compare that we got one render call to each
- QCOMPARE(rootRenderer.renderCount, 1);
- QCOMPARE(sourceRenderer.renderCount, 1);
- QVERIFY(sourceRenderer.renderingOrder < rootRenderer.renderingOrder);
- if (connected) // geometry is not rendered in this case, so skip it...
- QCOMPARE(rootRenderer.matrix, xform.matrix());
- QCOMPARE(sourceRenderer.matrix, QMatrix4x4());
-}
-
-void NodesTest::basicOpacityNode()
-{
- QSGOpacityNode n;
- QCOMPARE(n.opacity(), 1.);
-
- n.setOpacity(0.5);
- QCOMPARE(n.opacity(), 0.5);
-
- n.setOpacity(-1);
- QCOMPARE(n.opacity(), 0.);
-
- n.setOpacity(2);
- QCOMPARE(n.opacity(), 1.);
-}
-
-void NodesTest::opacityPropegation()
-{
- QSGRootNode root;
- QSGOpacityNode *a = new QSGOpacityNode;
- QSGOpacityNode *b = new QSGOpacityNode;
- QSGOpacityNode *c = new QSGOpacityNode;
-
- QSGSimpleRectNode *geometry = new QSGSimpleRectNode;
- geometry->setRect(0, 0, 100, 100);
-
- root.appendChildNode(a);
- a->appendChildNode(b);
- b->appendChildNode(c);
- c->appendChildNode(geometry);
-
- a->setOpacity(0.9);
- b->setOpacity(0.8);
- c->setOpacity(0.7);
-
- updater.updateStates(&root);
-
- QCOMPARE(a->combinedOpacity(), 0.9);
- QCOMPARE(b->combinedOpacity(), 0.9 * 0.8);
- QCOMPARE(c->combinedOpacity(), 0.9 * 0.8 * 0.7);
- QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.8 * 0.7);
-
- b->setOpacity(0.1);
- updater.updateStates(&root);
-
- QCOMPARE(a->combinedOpacity(), 0.9);
- QCOMPARE(b->combinedOpacity(), 0.9 * 0.1);
- QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
- QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
-
- b->setOpacity(0);
- updater.updateStates(&root);
-
- QVERIFY(b->isSubtreeBlocked());
-
- // Verify that geometry did not get updated as it is in a blocked
- // subtree
- QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
- QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
-}
-
-void NodesTest::isBlockedCheck()
-{
- QSGRootNode root;
- QSGOpacityNode *opacity = new QSGOpacityNode();
- QSGNode *node = new QSGNode();
-
- root.appendChildNode(opacity);
- opacity->appendChildNode(node);
-
- QSGNodeUpdater updater;
-
- opacity->setOpacity(0);
- QVERIFY(updater.isNodeBlocked(node, &root));
-
- opacity->setOpacity(1);
- QVERIFY(!updater.isNodeBlocked(node, &root));
-}
-
-QTEST_MAIN(NodesTest);
-
-#include "tst_nodestest.moc"
diff --git a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro b/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro
deleted file mode 100644
index 5870d74ab2..0000000000
--- a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativeanimations
-SOURCES += tst_qdeclarativeanimations.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
deleted file mode 100644
index 515c8fa918..0000000000
--- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
+++ /dev/null
@@ -1,1106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/private/qquickrectangle_p.h>
-#include <QtDeclarative/private/qdeclarativeanimation_p.h>
-#include <QtDeclarative/private/qdeclarativetransition_p.h>
-#include <QtDeclarative/private/qquickanimation_p.h>
-#include <QtDeclarative/private/qdeclarativepathinterpolator_p.h>
-#include <QtDeclarative/private/qquickitem_p.h>
-#include <QVariantAnimation>
-#include <QEasingCurve>
-
-#include <limits.h>
-#include <math.h>
-
-#include "../shared/util.h"
-
-class tst_qdeclarativeanimations : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativeanimations() {}
-
-private slots:
- void initTestCase() { QDeclarativeEngine engine; } // ensure types are registered
-
- void simpleProperty();
- void simpleNumber();
- void simpleColor();
- void simpleRotation();
- void simplePath();
- void pathInterpolator();
- void pathInterpolatorBackwardJump();
- void pathWithNoStart();
- void alwaysRunToEnd();
- void complete();
- void resume();
- void dotProperty();
- void badTypes();
- void badProperties();
- void mixedTypes();
- void properties();
- void propertiesTransition();
- void pathTransition();
- void disabledTransition();
- void invalidDuration();
- void attached();
- void propertyValueSourceDefaultStart();
- void dontStart();
- void easingProperties();
- void rotation();
- void runningTrueBug();
- void nonTransitionBug();
- void registrationBug();
- void doubleRegistrationBug();
- void alwaysRunToEndRestartBug();
- void transitionAssignmentBug();
- void pauseBindingBug();
- void pauseBug();
-};
-
-#define QTIMED_COMPARE(lhs, rhs) do { \
- for (int ii = 0; ii < 5; ++ii) { \
- if (lhs == rhs) \
- break; \
- QTest::qWait(50); \
- } \
- QCOMPARE(lhs, rhs); \
-} while (false)
-
-void tst_qdeclarativeanimations::simpleProperty()
-{
- QQuickRectangle rect;
- QDeclarativePropertyAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setTo(200);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "x");
- QVERIFY(animation.to().toReal() == 200.0);
- animation.start();
- QVERIFY(animation.isRunning());
- QTest::qWait(animation.duration());
- QTIMED_COMPARE(rect.x(), 200.0);
-
- rect.setPos(QPointF(0,0));
- animation.start();
- animation.pause();
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.x(),100.0);
-}
-
-void tst_qdeclarativeanimations::simpleNumber()
-{
- QQuickRectangle rect;
- QDeclarativeNumberAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setTo(200);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "x");
- QVERIFY(animation.to() == 200);
- animation.start();
- QVERIFY(animation.isRunning());
- QTest::qWait(animation.duration());
- QTIMED_COMPARE(rect.x(), qreal(200));
-
- rect.setX(0);
- animation.start();
- animation.pause();
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.x(), qreal(100));
-}
-
-void tst_qdeclarativeanimations::simpleColor()
-{
- QQuickRectangle rect;
- QDeclarativeColorAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("color");
- animation.setTo(QColor("red"));
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "color");
- QVERIFY(animation.to() == QColor("red"));
- animation.start();
- QVERIFY(animation.isRunning());
- QTest::qWait(animation.duration());
- QTIMED_COMPARE(rect.color(), QColor("red"));
-
- rect.setColor(QColor("blue"));
- animation.start();
- animation.pause();
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
-
- rect.setColor(QColor("green"));
- animation.setFrom(QColor("blue"));
- QVERIFY(animation.from() == QColor("blue"));
- animation.restart();
- QCOMPARE(rect.color(), QColor("blue"));
- QVERIFY(animation.isRunning());
- animation.setCurrentTime(125);
- QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
-}
-
-void tst_qdeclarativeanimations::simpleRotation()
-{
- QQuickRectangle rect;
- QDeclarativeRotationAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("rotation");
- animation.setTo(270);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "rotation");
- QVERIFY(animation.to() == 270);
- QVERIFY(animation.direction() == QDeclarativeRotationAnimation::Numerical);
- animation.start();
- QVERIFY(animation.isRunning());
- QTest::qWait(animation.duration());
- QTIMED_COMPARE(rect.rotation(), qreal(270));
-
- rect.setRotation(0);
- animation.start();
- animation.pause();
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.rotation(), qreal(135));
-}
-
-void tst_qdeclarativeanimations::simplePath()
-{
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimation.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
- QVERIFY(redRect);
- QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
- QVERIFY(pathAnim);
-
- pathAnim->start();
- pathAnim->pause();
-
- pathAnim->setCurrentTime(30);
- QCOMPARE(redRect->x(), qreal(167));
- QCOMPARE(redRect->y(), qreal(104));
-
- pathAnim->setCurrentTime(100);
- QCOMPARE(redRect->x(), qreal(300));
- QCOMPARE(redRect->y(), qreal(300));
-
- //verify animation runs to end
- pathAnim->start();
- QCOMPARE(redRect->x(), qreal(50));
- QCOMPARE(redRect->y(), qreal(50));
- QTRY_COMPARE(redRect->x(), qreal(300));
- QCOMPARE(redRect->y(), qreal(300));
-
- pathAnim->setOrientation(QQuickPathAnimation::RightFirst);
- QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
- pathAnim->start();
- QTRY_VERIFY(redRect->rotation() != 0);
- pathAnim->stop();
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimation2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
- QVERIFY(redRect);
- QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
- QVERIFY(pathAnim);
-
- QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
-
- pathAnim->start();
- pathAnim->pause();
- QCOMPARE(redRect->x(), qreal(50));
- QCOMPARE(redRect->y(), qreal(50));
- QCOMPARE(redRect->rotation(), qreal(-360));
-
- pathAnim->setCurrentTime(50);
- QCOMPARE(redRect->x(), qreal(175));
- QCOMPARE(redRect->y(), qreal(175));
- QCOMPARE(redRect->rotation(), qreal(-315));
-
- pathAnim->setCurrentTime(100);
- QCOMPARE(redRect->x(), qreal(300));
- QCOMPARE(redRect->y(), qreal(300));
- QCOMPARE(redRect->rotation(), qreal(0));
- }
-}
-
-void tst_qdeclarativeanimations::pathInterpolator()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathInterpolator.qml")));
- QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
- QVERIFY(interpolator);
-
- QCOMPARE(interpolator->progress(), qreal(0));
- QCOMPARE(interpolator->x(), qreal(50));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(0));
-
- interpolator->setProgress(.5);
- QCOMPARE(interpolator->progress(), qreal(.5));
- QCOMPARE(interpolator->x(), qreal(175));
- QCOMPARE(interpolator->y(), qreal(175));
- QCOMPARE(interpolator->angle(), qreal(270));
-
- interpolator->setProgress(1);
- QCOMPARE(interpolator->progress(), qreal(1));
- QCOMPARE(interpolator->x(), qreal(300));
- QCOMPARE(interpolator->y(), qreal(300));
- QCOMPARE(interpolator->angle(), qreal(0));
-}
-
-void tst_qdeclarativeanimations::pathInterpolatorBackwardJump()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathInterpolatorBack.qml")));
- QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
- QVERIFY(interpolator);
-
- QCOMPARE(interpolator->progress(), qreal(0));
- QCOMPARE(interpolator->x(), qreal(50));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(270));
-
- interpolator->setProgress(.5);
- QCOMPARE(interpolator->progress(), qreal(.5));
- QCOMPARE(interpolator->x(), qreal(100));
- QCOMPARE(interpolator->y(), qreal(75));
- QCOMPARE(interpolator->angle(), qreal(90));
-
- interpolator->setProgress(1);
- QCOMPARE(interpolator->progress(), qreal(1));
- QCOMPARE(interpolator->x(), qreal(200));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(0));
-
- //make sure we don't get caught in infinite loop here
- interpolator->setProgress(0);
- QCOMPARE(interpolator->progress(), qreal(0));
- QCOMPARE(interpolator->x(), qreal(50));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(270));
-}
-
-void tst_qdeclarativeanimations::pathWithNoStart()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimationNoStart.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
- QVERIFY(redRect);
- QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
- QVERIFY(pathAnim);
-
- pathAnim->start();
- pathAnim->pause();
- QCOMPARE(redRect->x(), qreal(50));
- QCOMPARE(redRect->y(), qreal(50));
-
- pathAnim->setCurrentTime(50);
- QCOMPARE(redRect->x(), qreal(175));
- QCOMPARE(redRect->y(), qreal(175));
-
- pathAnim->setCurrentTime(100);
- QCOMPARE(redRect->x(), qreal(300));
- QCOMPARE(redRect->y(), qreal(300));
-
- redRect->setX(100);
- redRect->setY(100);
- pathAnim->start();
- QCOMPARE(redRect->x(), qreal(100));
- QCOMPARE(redRect->y(), qreal(100));
- QTRY_COMPARE(redRect->x(), qreal(300));
- QCOMPARE(redRect->y(), qreal(300));
-}
-
-void tst_qdeclarativeanimations::alwaysRunToEnd()
-{
- QQuickRectangle rect;
- QDeclarativePropertyAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setTo(200);
- animation.setDuration(1000);
- animation.setLoops(-1);
- animation.setAlwaysRunToEnd(true);
- QVERIFY(animation.loops() == -1);
- QVERIFY(animation.alwaysRunToEnd() == true);
- animation.start();
- QTest::qWait(1500);
- animation.stop();
- QVERIFY(rect.x() != qreal(200));
- QTest::qWait(500);
- QTIMED_COMPARE(rect.x(), qreal(200));
-}
-
-void tst_qdeclarativeanimations::complete()
-{
- QQuickRectangle rect;
- QDeclarativePropertyAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setFrom(1);
- animation.setTo(200);
- animation.setDuration(500);
- QVERIFY(animation.from() == 1);
- animation.start();
- QTest::qWait(50);
- animation.stop();
- QVERIFY(rect.x() != qreal(200));
- animation.start();
- QTest::qWait(50);
- QVERIFY(animation.isRunning());
- animation.complete();
- QCOMPARE(rect.x(), qreal(200));
-}
-
-void tst_qdeclarativeanimations::resume()
-{
- QQuickRectangle rect;
- QDeclarativePropertyAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setFrom(10);
- animation.setTo(200);
- animation.setDuration(1000);
- QVERIFY(animation.from() == 10);
-
- animation.start();
- QTest::qWait(400);
- animation.pause();
- qreal x = rect.x();
- QVERIFY(x != qreal(200) && x != qreal(10));
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
-
- animation.resume();
- QVERIFY(animation.isRunning());
- QVERIFY(!animation.isPaused());
- QTest::qWait(400);
- animation.stop();
- QVERIFY(rect.x() > x);
-}
-
-void tst_qdeclarativeanimations::dotProperty()
-{
- QQuickRectangle rect;
- QDeclarativeNumberAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("border.width");
- animation.setTo(10);
- animation.start();
- QTest::qWait(animation.duration()+50);
- QTIMED_COMPARE(rect.border()->width(), 10.0);
-
- rect.border()->setWidth(0);
- animation.start();
- animation.pause();
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.border()->width(), 5.0);
-}
-
-void tst_qdeclarativeanimations::badTypes()
-{
- //don't crash
- {
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("badtype1.qml")));
-
- qApp->processEvents();
-
- delete view;
- }
-
- //make sure we get a compiler error
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype2.qml")));
- QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
- c.create();
-
- QVERIFY(c.errors().count() == 1);
- QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
- }
-
- //make sure we get a compiler error
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype3.qml")));
- QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
- c.create();
-
- QVERIFY(c.errors().count() == 1);
- QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
- }
-
- //don't crash
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype4.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QTest::qWait(1000 + 50);
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
- QVERIFY(myRect);
- QCOMPARE(myRect->x(),qreal(200));
- }
-}
-
-void tst_qdeclarativeanimations::badProperties()
-{
- //make sure we get a runtime error
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c1(&engine, QUrl::fromLocalFile(TESTDATA("badproperty1.qml")));
- QByteArray message = QUrl::fromLocalFile(TESTDATA("badproperty1.qml")).toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate non-existent property \"border.colr\"";
- QTest::ignoreMessage(QtWarningMsg, message);
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c1.create());
- QVERIFY(rect);
-
- QDeclarativeComponent c2(&engine, QUrl::fromLocalFile(TESTDATA("badproperty2.qml")));
- message = QUrl::fromLocalFile(TESTDATA("badproperty2.qml")).toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate read-only property \"border\"";
- QTest::ignoreMessage(QtWarningMsg, message);
- rect = qobject_cast<QQuickRectangle*>(c2.create());
- QVERIFY(rect);
-
- //### should we warn here are well?
- //rect->setState("state1");
- }
-}
-
-//test animating mixed types with property animation in a transition
-//for example, int + real; color + real; etc
-void tst_qdeclarativeanimations::mixedTypes()
-{
- //assumes border.width stays a real -- not real robust
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("mixedtype1.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QTest::qWait(500);
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
- QVERIFY(myRect);
-
- //rather inexact -- is there a better way?
- QVERIFY(myRect->x() > 100 && myRect->x() < 200);
- QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10);
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("mixedtype2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QTest::qWait(500);
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
- QVERIFY(myRect);
-
- //rather inexact -- is there a better way?
- QVERIFY(myRect->x() > 100 && myRect->x() < 200);
- QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue"));
- }
-}
-
-void tst_qdeclarativeanimations::properties()
-{
- const int waitDuration = 300;
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties3.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(300));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties4.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->y(),qreal(200));
- QTIMED_COMPARE(myRect->x(),qreal(100));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties5.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(100));
- QTIMED_COMPARE(myRect->y(),qreal(200));
- }
-}
-
-void tst_qdeclarativeanimations::propertiesTransition()
-{
- const int waitDuration = 300;
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(200));
- QCOMPARE(myRect->y(),qreal(100));
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->y(),qreal(200));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition3.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(200));
- QCOMPARE(myRect->y(),qreal(100));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition4.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(100));
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition5.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(100));
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
- /*{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition6.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(100));
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(100));
- }*/
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition7.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
- QTest::qWait(waitDuration);
- QTIMED_COMPARE(myRect->x(),qreal(200));
- }
-
-}
-
-void tst_qdeclarativeanimations::pathTransition()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathTransition.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("redRect");
- QVERIFY(myRect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
- QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(100)) && qFuzzyCompare(myRect->y(), qreal(700)));
- QTest::qWait(100);
-
- QQuickItemPrivate::get(rect)->setState("");
- QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
- QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(500)) && qFuzzyCompare(myRect->y(), qreal(50)));
-}
-
-void tst_qdeclarativeanimations::disabledTransition()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("disabledTransition.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
- QVERIFY(myRect);
-
- QDeclarativeTransition *trans = rect->findChild<QDeclarativeTransition*>();
- QVERIFY(trans);
-
- QCOMPARE(trans->enabled(), false);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QCOMPARE(myRect->x(),qreal(200));
-
- trans->setEnabled(true);
-
- QQuickItemPrivate::get(rect)->setState("");
- QCOMPARE(myRect->x(),qreal(200));
- QTest::qWait(300);
- QTIMED_COMPARE(myRect->x(),qreal(100));
-}
-
-void tst_qdeclarativeanimations::invalidDuration()
-{
- QDeclarativePropertyAnimation *animation = new QDeclarativePropertyAnimation;
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PropertyAnimation: Cannot set a duration of < 0");
- animation->setDuration(-1);
- QCOMPARE(animation->duration(), 250);
-
- QDeclarativePauseAnimation *pauseAnimation = new QDeclarativePauseAnimation;
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PauseAnimation: Cannot set a duration of < 0");
- pauseAnimation->setDuration(-1);
- QCOMPARE(pauseAnimation->duration(), 250);
-}
-
-void tst_qdeclarativeanimations::attached()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("attached.qml")));
- QTest::ignoreMessage(QtDebugMsg, "off");
- QTest::ignoreMessage(QtDebugMsg, "on");
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-}
-
-void tst_qdeclarativeanimations::propertyValueSourceDefaultStart()
-{
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valuesource.qml")));
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim);
- QVERIFY(myAnim->isRunning());
- }
-
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valuesource2.qml")));
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim);
- QVERIFY(myAnim->isRunning() == false);
- }
-
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontAutoStart.qml")));
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim && myAnim->qtAnimation());
- QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
- }
-}
-
-
-void tst_qdeclarativeanimations::dontStart()
-{
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart.qml")));
-
- QString warning = c.url().toString() + ":14:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim && myAnim->qtAnimation());
- QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
- }
-
- {
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart2.qml")));
-
- QString warning = c.url().toString() + ":15:17: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim && myAnim->qtAnimation());
- QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
- }
-}
-
-void tst_qdeclarativeanimations::easingProperties()
-{
- {
- QDeclarativeEngine engine;
- QString componentStr = "import QtQuick 2.0\nNumberAnimation { easing.type: \"InOutQuad\" }";
- QDeclarativeComponent animationComponent(&engine);
- animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
-
- QVERIFY(animObject != 0);
- QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
- }
-
- {
- QDeclarativeEngine engine;
- QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutBounce\"; easing.amplitude: 5.0 }";
- QDeclarativeComponent animationComponent(&engine);
- animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
-
- QVERIFY(animObject != 0);
- QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
- QCOMPARE(animObject->easing().amplitude(), 5.0);
- }
-
- {
- QDeclarativeEngine engine;
- QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutElastic\"; easing.amplitude: 5.0; easing.period: 3.0}";
- QDeclarativeComponent animationComponent(&engine);
- animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
-
- QVERIFY(animObject != 0);
- QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
- QCOMPARE(animObject->easing().amplitude(), 5.0);
- QCOMPARE(animObject->easing().period(), 3.0);
- }
-
- {
- QDeclarativeEngine engine;
- QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"InOutBack\"; easing.overshoot: 2 }";
- QDeclarativeComponent animationComponent(&engine);
- animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
-
- QVERIFY(animObject != 0);
- QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
- QCOMPARE(animObject->easing().overshoot(), 2.0);
- }
-}
-
-void tst_qdeclarativeanimations::rotation()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("rotation.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *rr = rect->findChild<QQuickRectangle*>("rr");
- QQuickRectangle *rr2 = rect->findChild<QQuickRectangle*>("rr2");
- QQuickRectangle *rr3 = rect->findChild<QQuickRectangle*>("rr3");
- QQuickRectangle *rr4 = rect->findChild<QQuickRectangle*>("rr4");
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QTest::qWait(800);
- qreal r1 = rr->rotation();
- qreal r2 = rr2->rotation();
- qreal r3 = rr3->rotation();
- qreal r4 = rr4->rotation();
-
- QVERIFY(r1 > qreal(0) && r1 < qreal(370));
- QVERIFY(r2 > qreal(0) && r2 < qreal(370));
- QVERIFY(r3 < qreal(0) && r3 > qreal(-350));
- QVERIFY(r4 > qreal(0) && r4 < qreal(10));
- QCOMPARE(r1,r2);
- QVERIFY(r4 < r2);
-
- QTest::qWait(800);
- QTIMED_COMPARE(rr->rotation() + rr2->rotation() + rr3->rotation() + rr4->rotation(), qreal(370*4));
-}
-
-void tst_qdeclarativeanimations::runningTrueBug()
-{
- //ensure we start correctly when "running: true" is explicitly set
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("runningTrueBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *cloud = rect->findChild<QQuickRectangle*>("cloud");
- QVERIFY(cloud);
- QTest::qWait(1000);
- QVERIFY(cloud->x() > qreal(0));
-}
-
-//QTBUG-12805
-void tst_qdeclarativeanimations::nonTransitionBug()
-{
- //tests that the animation values from the previous transition are properly cleared
- //in the case where an animation in the transition doesn't match anything (but previously did)
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("nonTransitionBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
-
- mover->setX(100);
- QCOMPARE(mover->x(), qreal(100));
-
- rectPrivate->setState("left");
- QTRY_COMPARE(mover->x(), qreal(0));
-
- mover->setX(100);
- QCOMPARE(mover->x(), qreal(100));
-
- //make sure we don't try to animate back to 0
- rectPrivate->setState("free");
- QTest::qWait(300);
- QCOMPARE(mover->x(), qreal(100));
-}
-
-//QTBUG-14042
-void tst_qdeclarativeanimations::registrationBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("registrationBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
-}
-
-void tst_qdeclarativeanimations::doubleRegistrationBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("doubleRegistrationBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QDeclarativeAbstractAnimation *anim = rect->findChild<QDeclarativeAbstractAnimation*>("animation");
- QVERIFY(anim != 0);
- QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Stopped);
-}
-
-//QTBUG-16736
-void tst_qdeclarativeanimations::alwaysRunToEndRestartBug()
-{
- QQuickRectangle rect;
- QDeclarativePropertyAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setTo(200);
- animation.setDuration(1000);
- animation.setLoops(-1);
- animation.setAlwaysRunToEnd(true);
- QVERIFY(animation.loops() == -1);
- QVERIFY(animation.alwaysRunToEnd() == true);
- animation.start();
- animation.stop();
- animation.start();
- animation.stop();
- QTest::qWait(500);
- QVERIFY(rect.x() != qreal(200));
- QTest::qWait(800);
- QTIMED_COMPARE(rect.x(), qreal(200));
- QCOMPARE(static_cast<QDeclarativeAbstractAnimation*>(&animation)->qtAnimation()->state(), QAbstractAnimation::Stopped);
-}
-
-//QTBUG-20227
-void tst_qdeclarativeanimations::transitionAssignmentBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("transitionAssignmentBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->property("nullObject").toBool(), false);
-}
-
-//QTBUG-19080
-void tst_qdeclarativeanimations::pauseBindingBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pauseBindingBug.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QDeclarativeAbstractAnimation *anim = rect->findChild<QDeclarativeAbstractAnimation*>("animation");
- QVERIFY(anim->qtAnimation()->state() == QAbstractAnimation::Paused);
-
- delete rect;
-}
-
-//QTBUG-13598
-void tst_qdeclarativeanimations::pauseBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pauseBug.qml")));
- QDeclarativeAbstractAnimation *anim = qobject_cast<QDeclarativeAbstractAnimation*>(c.create());
- QVERIFY(anim != 0);
- QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Paused);
- QCOMPARE(anim->isPaused(), true);
- QCOMPARE(anim->isRunning(), true);
-
- delete anim;
-}
-
-QTEST_MAIN(tst_qdeclarativeanimations)
-
-#include "tst_qdeclarativeanimations.moc"
diff --git a/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro b/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro
deleted file mode 100644
index 3b01fcf9e3..0000000000
--- a/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativeapplication
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativeapplication.cpp
-QT += core-private gui-private declarative-private testlib
-
diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp
deleted file mode 100644
index 72313ab054..0000000000
--- a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qquickitem.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtGui/qinputpanel.h>
-
-class tst_qdeclarativeapplication : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativeapplication();
-
-private slots:
- void active();
- void layoutDirection();
- void inputPanel();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qdeclarativeapplication::tst_qdeclarativeapplication()
-{
-}
-
-void tst_qdeclarativeapplication::active()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Item { property bool active: Qt.application.active }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
- QVERIFY(item);
- QQuickView view;
- item->setParentItem(view.rootObject());
-
- // not active
- QVERIFY(!item->property("active").toBool());
- QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
-
- // active
- view.show();
- view.requestActivateWindow();
- QTest::qWait(50);
- QEXPECT_FAIL("", "QTBUG-21573", Abort);
- QTRY_COMPARE(view.status(), QQuickView::Ready);
- QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
-
-#if 0
- // QGuiApplication has no equivalent of setActiveWindow(0). QTBUG-21573
- // Is this different to clearing the active state of the window or can it be removed?
- // On Mac, setActiveWindow(0) on mac does not deactivate the current application,
- // must switch to a different app or hide the current app to trigger this
- // on mac, setActiveWindow(0) on mac does not deactivate the current application
- // (you have to switch to a different app or hide the current app to trigger this)
-
- // not active again
- QGuiApplication::setActiveWindow(0);
- QVERIFY(!item->property("active").toBool());
- QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
-#endif
-
-}
-
-void tst_qdeclarativeapplication::layoutDirection()
-{
-
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Item { property bool layoutDirection: Qt.application.layoutDirection }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
- QVERIFY(item);
- QQuickView view;
- item->setParentItem(view.rootObject());
-
- // not mirrored
- QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight);
-
- // mirrored
- QGuiApplication::setLayoutDirection(Qt::RightToLeft);
- QEXPECT_FAIL("", "QTBUG-21573", Abort);
- QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::RightToLeft);
-
- // not mirrored again
- QGuiApplication::setLayoutDirection(Qt::LeftToRight);
- QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight);
-}
-
-void tst_qdeclarativeapplication::inputPanel()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Item { property variant inputPanel: Qt.application.inputPanel }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
- QVERIFY(item);
- QQuickView view;
- item->setParentItem(view.rootObject());
-
- // check that the inputPanel property maches with application's input panel
- QCOMPARE(qvariant_cast<QObject*>(item->property("inputPanel")), qApp->inputPanel());
-}
-
-QTEST_MAIN(tst_qdeclarativeapplication)
-
-#include "tst_qdeclarativeapplication.moc"
diff --git a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro b/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro
deleted file mode 100644
index 0e7c73ab90..0000000000
--- a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativebehaviors
-SOURCES += tst_qdeclarativebehaviors.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp b/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp
deleted file mode 100644
index d1c1ca7d9c..0000000000
--- a/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp
+++ /dev/null
@@ -1,474 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <qsignalspy.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquicktext_p.h>
-#include <private/qdeclarativebehavior_p.h>
-#include <private/qdeclarativeanimation_p.h>
-#include <private/qquickitem_p.h>
-#include "../shared/util.h"
-
-class tst_qdeclarativebehaviors : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativebehaviors() {}
-
-private slots:
- void init() { qApp->processEvents(); } //work around animation timer bug (QTBUG-22865)
- void simpleBehavior();
- void scriptTriggered();
- void cppTriggered();
- void loop();
- void colorBehavior();
- void parentBehavior();
- void replaceBinding();
- //void transitionOverrides();
- void group();
- void valueType();
- void emptyBehavior();
- void explicitSelection();
- void nonSelectingBehavior();
- void reassignedAnimation();
- void disabled();
- void dontStart();
- void startup();
- void groupedPropertyCrash();
- void runningTrue();
- void sameValue();
- void delayedRegistration();
- void startOnCompleted();
-};
-
-void tst_qdeclarativebehaviors::simpleBehavior()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("simple.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
- QTRY_VERIFY(qobject_cast<QDeclarativeBehavior*>(rect->findChild<QDeclarativeBehavior*>("MyBehavior"))->animation());
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
- //i.e. the behavior has been triggered
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::scriptTriggered()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("scripttrigger.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- rect->setColor(QColor("red"));
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
- //i.e. the behavior has been triggered
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::cppTriggered()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("cpptrigger.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QTRY_VERIFY(innerRect);
-
- innerRect->setProperty("x", 200);
- QTRY_VERIFY(innerRect->x() > 0);
- QTRY_VERIFY(innerRect->x() < 200); //i.e. the behavior has been triggered
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::loop()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("loop.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- //don't crash
- QQuickItemPrivate::get(rect)->setState("moved");
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::colorBehavior()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("color.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("red");
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("red"));
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("green"));
- //i.e. the behavior has been triggered
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::parentBehavior()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("parent.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("reparented");
- QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() != rect->findChild<QQuickItem*>("NewParent"));
- QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() == rect->findChild<QQuickItem*>("NewParent"));
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::replaceBinding()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("binding.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QTRY_VERIFY(innerRect);
- QTRY_VERIFY(innerRect->x() > 0);
- QTRY_VERIFY(innerRect->x() < 200);
- //i.e. the behavior has been triggered
- QTRY_COMPARE(innerRect->x(), (qreal)200);
- rect->setProperty("basex", 10);
- QTRY_COMPARE(innerRect->x(), (qreal)200);
- rect->setProperty("movedx", 210);
- QTRY_COMPARE(innerRect->x(), (qreal)210);
-
- QQuickItemPrivate::get(rect)->setState("");
- QTRY_VERIFY(innerRect->x() > 10);
- QTRY_VERIFY(innerRect->x() < 210); //i.e. the behavior has been triggered
- QTRY_COMPARE(innerRect->x(), (qreal)10);
- rect->setProperty("movedx", 200);
- QTRY_COMPARE(innerRect->x(), (qreal)10);
- rect->setProperty("basex", 20);
- QTRY_COMPARE(innerRect->x(), (qreal)20);
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::group()
-{
- /* XXX TODO Create a test element for this case.
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupProperty.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- qDebug() << c.errorString();
- QTRY_VERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- //QTest::qWait(200);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
- //i.e. the behavior has been triggered
-
- delete rect;
- }
- */
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupProperty2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QTRY_VERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() > 0);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() < 4);
- //i.e. the behavior has been triggered
-
- delete rect;
- }
-}
-
-void tst_qdeclarativebehaviors::valueType()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valueType.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- //QTBUG-20827
- QCOMPARE(rect->color(), QColor::fromRgb(255,0,255));
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::emptyBehavior()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("empty.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
- QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::explicitSelection()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("explicit.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
- QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
- //i.e. the behavior has been triggered
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::nonSelectingBehavior()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("nonSelecting2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
- QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::reassignedAnimation()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("reassignedAnimation.qml")));
- QString warning = QUrl::fromLocalFile(TESTDATA("reassignedAnimation.qml")).toString() + ":9:9: QML Behavior: Cannot change the animation assigned to a Behavior.";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
- QCOMPARE(qobject_cast<QDeclarativeNumberAnimation*>(
- rect->findChild<QDeclarativeBehavior*>("MyBehavior")->animation())->duration(), 200);
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::disabled()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("disabled.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
- QCOMPARE(rect->findChild<QDeclarativeBehavior*>("MyBehavior")->enabled(), false);
-
- QQuickItemPrivate::get(rect)->setState("moved");
- qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
- QCOMPARE(x, qreal(200)); //should change immediately
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::dontStart()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart.qml")));
-
- QString warning = c.url().toString() + ":13:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
- QVERIFY(myAnim && myAnim->qtAnimation());
- QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
-
- delete rect;
-}
-
-void tst_qdeclarativebehaviors::startup()
-{
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startup.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
- QVERIFY(innerRect);
-
- QCOMPARE(innerRect->x(), qreal(100)); //should be set immediately
-
- delete rect;
- }
-
- {
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startup2.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
- QVERIFY(innerRect);
-
- QQuickText *text = rect->findChild<QQuickText*>();
- QVERIFY(text);
-
- QCOMPARE(innerRect->x(), text->width()); //should be set immediately
-
- delete rect;
- }
-}
-
-//QTBUG-10799
-void tst_qdeclarativebehaviors::groupedPropertyCrash()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupedPropertyCrash.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect); //don't crash
-
- delete rect;
-}
-
-//QTBUG-5491
-void tst_qdeclarativebehaviors::runningTrue()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("runningTrue.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QDeclarativeAbstractAnimation *animation = rect->findChild<QDeclarativeAbstractAnimation*>("rotAnim");
- QVERIFY(animation);
-
- QSignalSpy runningSpy(animation, SIGNAL(runningChanged(bool)));
- rect->setProperty("myValue", 180);
- QTRY_VERIFY(runningSpy.count() > 0);
-
- delete rect;
-}
-
-//QTBUG-12295
-void tst_qdeclarativebehaviors::sameValue()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("qtbug12295.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *target = rect->findChild<QQuickRectangle*>("myRect");
- QVERIFY(target);
-
- target->setX(100);
- QCOMPARE(target->x(), qreal(100));
-
- target->setProperty("x", 0);
- QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100));
- QTRY_VERIFY(target->x() == qreal(0)); //make sure Behavior has finished.
-
- target->setX(100);
- QCOMPARE(target->x(), qreal(100));
-
- //this is the main point of the test -- the behavior needs to be triggered again
- //even though we set 0 twice in a row.
- target->setProperty("x", 0);
- QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100));
-
- delete rect;
-}
-
-//QTBUG-18362
-void tst_qdeclarativebehaviors::delayedRegistration()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("delayedRegistration.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickItem *innerRect = rect->property("myItem").value<QQuickItem*>();
- QVERIFY(innerRect != 0);
-
- QCOMPARE(innerRect->property("x").toInt(), int(0));
-
- QTRY_COMPARE(innerRect->property("x").toInt(), int(100));
-}
-
-//QTBUG-22555
-void tst_qdeclarativebehaviors::startOnCompleted()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startOnCompleted.qml")));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickItem *innerRect = rect->findChild<QQuickRectangle*>();
- QVERIFY(innerRect != 0);
-
- QCOMPARE(innerRect->property("x").toInt(), int(0));
-
- QTRY_COMPARE(innerRect->property("x").toInt(), int(100));
-
- delete rect;
-}
-
-QTEST_MAIN(tst_qdeclarativebehaviors)
-
-#include "tst_qdeclarativebehaviors.moc"
diff --git a/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro b/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro
index d0bbfe6faa..5f8ee634f4 100644
--- a/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro
+++ b/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro
@@ -10,4 +10,4 @@ DEPLOYMENT += testDataFiles
CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp b/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
index 091a87b5a8..80ed10cd25 100644
--- a/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
+++ b/tests/auto/declarative/qdeclarativebinding/tst_qdeclarativebinding.cpp
@@ -42,8 +42,8 @@
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
#include <private/qdeclarativebind_p.h>
-#include <private/qquickrectangle_p.h>
-#include "../shared/util.h"
+#include <QtQuick/private/qquickrectangle_p.h>
+#include "../../shared/util.h"
class tst_qdeclarativebinding : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativechangeset/qdeclarativechangeset.pro b/tests/auto/declarative/qdeclarativechangeset/qdeclarativechangeset.pro
index b2f88b630b..7c52ef5dfd 100644
--- a/tests/auto/declarative/qdeclarativechangeset/qdeclarativechangeset.pro
+++ b/tests/auto/declarative/qdeclarativechangeset/qdeclarativechangeset.pro
@@ -6,4 +6,4 @@ SOURCES += tst_qdeclarativechangeset.cpp
CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
index 1dcaaa1b06..da15458d27 100644
--- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
+++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
@@ -43,11 +43,10 @@
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickitem.h>
#include <QtDeclarative/qdeclarativeproperty.h>
#include <QtDeclarative/qdeclarativeincubator.h>
#include <qcolor.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class MyIC : public QObject, public QDeclarativeIncubationController
{
diff --git a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro
index ef3ef536f0..702f3fc542 100644
--- a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro
+++ b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro
@@ -10,4 +10,4 @@ DEPLOYMENT += testDataFiles
CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
index 450f16c036..cd8f7b7b0c 100644
--- a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
+++ b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
@@ -43,7 +43,7 @@
#include <QtDeclarative/qdeclarativecomponent.h>
#include <private/qdeclarativeconnections_p.h>
#include <private/qquickitem_p.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
#include <QtDeclarative/qdeclarativescriptstring.h>
class tst_qdeclarativeconnection : public QObject
diff --git a/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp b/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp
index 24095e3c35..0025798854 100644
--- a/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp
+++ b/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp
@@ -42,7 +42,7 @@
#include <QDebug>
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativeconsole : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
index ba9db4f875..c57cbeceba 100644
--- a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
+++ b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
@@ -46,7 +46,7 @@
#include <QDeclarativeComponent>
#include <QDeclarativeExpression>
#include <private/qdeclarativecontext_p.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
inline QUrl TEST_FILE(const QString &filename)
{
diff --git a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro
index d6d17c5869..1908e6bae1 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro
+++ b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro
@@ -4,10 +4,10 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qdeclarativeecmascript.cpp \
testtypes.cpp \
- ../shared/testhttpserver.cpp
+ ../../shared/testhttpserver.cpp
HEADERS += testtypes.h \
- ../shared/testhttpserver.h
-INCLUDEPATH += ../shared
+ ../../shared/testhttpserver.h
+INCLUDEPATH += ../../shared
# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
# LIBS += -lgcov
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 4891e5088e..3d50d6ee3d 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -54,7 +54,7 @@
#include <private/qv4compiler_p.h>
#include "testtypes.h"
#include "testhttpserver.h"
-#include "../shared/util.h"
+#include "../../shared/util.h"
/*
This test covers evaluation of ECMAScript expressions and bindings from within
diff --git a/tests/auto/declarative/qdeclarativeerror/tst_qdeclarativeerror.cpp b/tests/auto/declarative/qdeclarativeerror/tst_qdeclarativeerror.cpp
index ab97d04d4c..8fab5e5e50 100644
--- a/tests/auto/declarative/qdeclarativeerror/tst_qdeclarativeerror.cpp
+++ b/tests/auto/declarative/qdeclarativeerror/tst_qdeclarativeerror.cpp
@@ -42,7 +42,7 @@
#include <qtest.h>
#include <QDeclarativeError>
#include <QDebug>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativeerror : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativeexpression/tst_qdeclarativeexpression.cpp b/tests/auto/declarative/qdeclarativeexpression/tst_qdeclarativeexpression.cpp
index a65045b48f..f7699e2bac 100644
--- a/tests/auto/declarative/qdeclarativeexpression/tst_qdeclarativeexpression.cpp
+++ b/tests/auto/declarative/qdeclarativeexpression/tst_qdeclarativeexpression.cpp
@@ -44,7 +44,7 @@
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativeexpression.h>
#include <QtDeclarative/qdeclarativescriptstring.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativeexpression : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp
index f8c91e6000..f85a6f14b6 100644
--- a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp
+++ b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp
@@ -46,7 +46,7 @@
#include <QtCore/qfile.h>
#include <QtCore/qabstractitemmodel.h>
#include <QDebug>
-#include "../shared/util.h"
+#include "../../shared/util.h"
// From qdeclarastivefolderlistmodel.h
const int FileNameRole = Qt::UserRole+1;
diff --git a/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro b/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro
deleted file mode 100644
index 3efde621b2..0000000000
--- a/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativefontloader
-macx:CONFIG -= app_bundle
-
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativefontloader.cpp ../../declarative/shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp b/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
deleted file mode 100644
index 6e81befad8..0000000000
--- a/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/private/qdeclarativefontloader_p.h>
-#include "../shared/util.h"
-#include "../../declarative/shared/testhttpserver.h"
-#include <QQuickView>
-#include <QQuickItem>
-
-#define SERVER_PORT 14448
-
-class tst_qdeclarativefontloader : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativefontloader();
-
-private slots:
- void init();
- void noFont();
- void namedFont();
- void localFont();
- void failLocalFont();
- void webFont();
- void redirWebFont();
- void failWebFont();
- void changeFont();
- void changeFontSourceViaState();
-
-private:
- QDeclarativeEngine engine;
- TestHTTPServer server;
-};
-
-tst_qdeclarativefontloader::tst_qdeclarativefontloader() :
- server(SERVER_PORT)
-{
- server.serveDirectory(TESTDATA(""));
-}
-
-void tst_qdeclarativefontloader::init()
-{
- QVERIFY(server.isValid());
-}
-
-void tst_qdeclarativefontloader::noFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QCOMPARE(fontObject->name(), QString(""));
- QCOMPARE(fontObject->source(), QUrl(""));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Null);
-
- delete fontObject;
-}
-
-void tst_qdeclarativefontloader::namedFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { name: \"Helvetica\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QCOMPARE(fontObject->source(), QUrl(""));
- QCOMPARE(fontObject->name(), QString("Helvetica"));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
-}
-
-void tst_qdeclarativefontloader::localFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + TESTDATA("tarzeau_ocr_a.ttf") + "\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
-}
-
-void tst_qdeclarativefontloader::failLocalFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + QUrl::fromLocalFile(TESTDATA("dummy.ttf")).toString() + "\" }";
- QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + QUrl::fromLocalFile(TESTDATA("dummy.ttf")).toString() + "\"").toUtf8().constData());
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString(""));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error);
-}
-
-void tst_qdeclarativefontloader::webFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }";
- QDeclarativeComponent component(&engine);
-
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
-}
-
-void tst_qdeclarativefontloader::redirWebFont()
-{
- server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf");
-
- QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }";
- QDeclarativeComponent component(&engine);
-
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
-}
-
-void tst_qdeclarativefontloader::failWebFont()
-{
- 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\"");
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString(""));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error);
-}
-
-void tst_qdeclarativefontloader::changeFont()
-{
- QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("font", QUrl::fromLocalFile(TESTDATA("tarzeau_ocr_a.ttf")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
-
- QVERIFY(fontObject != 0);
-
- QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged()));
- QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged()));
-
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QCOMPARE(nameSpy.count(), 0);
- QCOMPARE(statusSpy.count(), 0);
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
-
- ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf");
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Loading);
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QCOMPARE(nameSpy.count(), 1);
- QCOMPARE(statusSpy.count(), 2);
- QTRY_COMPARE(fontObject->name(), QString("Daniel"));
-
- ctxt->setContextProperty("font", QUrl::fromLocalFile(TESTDATA("tarzeau_ocr_a.ttf")));
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QCOMPARE(nameSpy.count(), 2);
- QCOMPARE(statusSpy.count(), 2);
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
-
- ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf");
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QCOMPARE(nameSpy.count(), 3);
- QCOMPARE(statusSpy.count(), 2);
- QTRY_COMPARE(fontObject->name(), QString("Daniel"));
-}
-
-void tst_qdeclarativefontloader::changeFontSourceViaState()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("qtbug-20268.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(qvariant_cast<QObject *>(canvas.rootObject()->property("fontloader")));
- QVERIFY(fontObject != 0);
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QVERIFY(fontObject->source() != QUrl(""));
- QTRY_COMPARE(fontObject->name(), QString("OCRA"));
-
- canvas.rootObject()->setProperty("usename", true);
-
- // This warning should probably not be printed once QTBUG-20268 is fixed
- QString warning = QString(QUrl::fromLocalFile(TESTDATA("qtbug-20268.qml")).toString()) +
- QLatin1String(":13:5: QML FontLoader: Cannot load font: \"\"");
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
-
- QEXPECT_FAIL("", "QTBUG-20268", Abort);
- QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
- QCOMPARE(canvas.rootObject()->property("name").toString(), QString("Tahoma"));
-}
-
-QTEST_MAIN(tst_qdeclarativefontloader)
-
-#include "tst_qdeclarativefontloader.moc"
diff --git a/tests/auto/declarative/qdeclarativeimageprovider/qdeclarativeimageprovider.pro b/tests/auto/declarative/qdeclarativeimageprovider/qdeclarativeimageprovider.pro
index dda2595956..70b9a406b3 100644
--- a/tests/auto/declarative/qdeclarativeimageprovider/qdeclarativeimageprovider.pro
+++ b/tests/auto/declarative/qdeclarativeimageprovider/qdeclarativeimageprovider.pro
@@ -6,4 +6,4 @@ SOURCES += tst_qdeclarativeimageprovider.cpp
CONFIG += parallel_test
-QT += core-private gui-private declarative-private network testlib
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/declarative/qdeclarativeincubator/tst_qdeclarativeincubator.cpp b/tests/auto/declarative/qdeclarativeincubator/tst_qdeclarativeincubator.cpp
index fe618b87e8..599b5d21b1 100644
--- a/tests/auto/declarative/qdeclarativeincubator/tst_qdeclarativeincubator.cpp
+++ b/tests/auto/declarative/qdeclarativeincubator/tst_qdeclarativeincubator.cpp
@@ -51,7 +51,7 @@
#include <QDeclarativeProperty>
#include <QDeclarativeComponent>
#include <QDeclarativeIncubator>
-#include "../shared/util.h"
+#include "../../shared/util.h"
inline QUrl TEST_FILE(const QString &filename)
{
diff --git a/tests/auto/declarative/qdeclarativeinfo/tst_qdeclarativeinfo.cpp b/tests/auto/declarative/qdeclarativeinfo/tst_qdeclarativeinfo.cpp
index ec04a83102..d4e3df2ffb 100644
--- a/tests/auto/declarative/qdeclarativeinfo/tst_qdeclarativeinfo.cpp
+++ b/tests/auto/declarative/qdeclarativeinfo/tst_qdeclarativeinfo.cpp
@@ -45,7 +45,7 @@
#include <QTimer>
#include <QDeclarativeContext>
#include <qdeclarativeinfo.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativeinfo : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro
index 105e2b44d6..f79d1c99c9 100644
--- a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro
+++ b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro
@@ -6,9 +6,9 @@ SOURCES += tst_qdeclarativelanguage.cpp \
testtypes.cpp
HEADERS += testtypes.h
-INCLUDEPATH += ../shared/
-HEADERS += ../shared/testhttpserver.h
-SOURCES += ../shared/testhttpserver.cpp
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += ../../shared/testhttpserver.cpp
importFiles.files = data
importFiles.path = .
diff --git a/tests/auto/declarative/qdeclarativelistcompositor/qdeclarativelistcompositor.pro b/tests/auto/declarative/qdeclarativelistcompositor/qdeclarativelistcompositor.pro
index e8dd7dd83a..3936f4beff 100644
--- a/tests/auto/declarative/qdeclarativelistcompositor/qdeclarativelistcompositor.pro
+++ b/tests/auto/declarative/qdeclarativelistcompositor/qdeclarativelistcompositor.pro
@@ -6,4 +6,4 @@ SOURCES += tst_qdeclarativelistcompositor.cpp
CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro
index fc8a3178ae..ae3aa9d287 100644
--- a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro
+++ b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro
@@ -10,4 +10,4 @@ DEPLOYMENT += testDataFiles
CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp
index 661b086fd1..1de2a2868e 100644
--- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp
+++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp
@@ -39,8 +39,8 @@
**
****************************************************************************/
#include <qtest.h>
-#include <QtDeclarative/private/qquickitem_p.h>
-#include <QtDeclarative/private/qquicktext_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquicktext_p.h>
#include <QtDeclarative/private/qdeclarativeengine_p.h>
#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
#include <QtDeclarative/private/qdeclarativeexpression_p.h>
@@ -51,7 +51,7 @@
#include <QtCore/qtranslator.h>
#include <QSignalSpy>
-#include "../shared/util.h"
+#include "../../shared/util.h"
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<QVariantHash>)
diff --git a/tests/auto/declarative/qdeclarativelistreference/tst_qdeclarativelistreference.cpp b/tests/auto/declarative/qdeclarativelistreference/tst_qdeclarativelistreference.cpp
index a86e66de45..e09db2c9c7 100644
--- a/tests/auto/declarative/qdeclarativelistreference/tst_qdeclarativelistreference.cpp
+++ b/tests/auto/declarative/qdeclarativelistreference/tst_qdeclarativelistreference.cpp
@@ -49,7 +49,7 @@
#include <QtDeclarative/qdeclarativeprivate.h>
#include <QtDeclarative/qdeclarativeproperty.h>
#include <QDebug>
-#include "../shared/util.h"
+#include "../../shared/util.h"
inline QUrl TEST_FILE(const QString &filename)
{
diff --git a/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp b/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp
index 54139a2671..b2f35fd8b3 100644
--- a/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp
+++ b/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp
@@ -43,10 +43,9 @@
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickitem.h>
#include <QtCore/QDateTime>
#include <qcolor.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativelocale : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp
index d8b7cf4e5b..1530eb9d36 100644
--- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp
+++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp
@@ -44,8 +44,8 @@
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QDebug>
-#include "../shared/testhttpserver.h"
-#include "../shared/util.h"
+#include "../../shared/testhttpserver.h"
+#include "../../shared/util.h"
#define SERVER_ADDR "http://127.0.0.1:14450"
#define SERVER_PORT 14450
diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro
index 94c0f9dde1..bec727f05f 100644
--- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro
+++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro
@@ -1,9 +1,9 @@
CONFIG += testcase
TARGET = tst_qdeclarativemoduleplugin
-HEADERS = ../shared/testhttpserver.h
+HEADERS = ../../shared/testhttpserver.h
SOURCES = tst_qdeclarativemoduleplugin.cpp \
- ../shared/testhttpserver.cpp
+ ../../shared/testhttpserver.cpp
CONFIG -= app_bundle
testDataFiles.files = data
diff --git a/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro b/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro
deleted file mode 100644
index 212117165d..0000000000
--- a/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativepath
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativepath.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private testlib
diff --git a/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp b/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp
deleted file mode 100644
index 91513fc8a5..0000000000
--- a/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/private/qdeclarativepath_p.h>
-
-#include "../shared/util.h"
-
-class tst_QDeclarativePath : public QObject
-{
- Q_OBJECT
-public:
- tst_QDeclarativePath() {}
-
-private slots:
- void arc();
- void catmullromCurve();
- void svg();
-};
-
-void tst_QDeclarativePath::arc()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("arc.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->startX(), 0.);
- QCOMPARE(obj->startY(), 0.);
-
- QDeclarativeListReference list(obj, "pathElements");
- QCOMPARE(list.count(), 1);
-
- QDeclarativePathArc* arc = qobject_cast<QDeclarativePathArc*>(list.at(0));
- QVERIFY(arc != 0);
- QCOMPARE(arc->x(), 100.);
- QCOMPARE(arc->y(), 100.);
- QCOMPARE(arc->radiusX(), 100.);
- QCOMPARE(arc->radiusY(), 100.);
- QCOMPARE(arc->useLargeArc(), false);
- QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
-
- QPainterPath path = obj->path();
- QVERIFY(path != QPainterPath());
-
- QPointF pos = obj->pointAt(0);
- QCOMPARE(pos, QPointF(0,0));
- pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(39,8)); //fuzzy compare
- pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(92,61)); //fuzzy compare
- pos = obj->pointAt(1);
- QCOMPARE(pos, QPointF(100,100));
-}
-
-void tst_QDeclarativePath::catmullromCurve()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("curve.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->startX(), 0.);
- QCOMPARE(obj->startY(), 0.);
-
- QDeclarativeListReference list(obj, "pathElements");
- QCOMPARE(list.count(), 3);
-
- QDeclarativePathCatmullRomCurve* arc = qobject_cast<QDeclarativePathCatmullRomCurve*>(list.at(0));
-// QVERIFY(arc != 0);
-// QCOMPARE(arc->x(), 100.);
-// QCOMPARE(arc->y(), 100.);
-// QCOMPARE(arc->radiusX(), 100.);
-// QCOMPARE(arc->radiusY(), 100.);
-// QCOMPARE(arc->useLargeArc(), false);
-// QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
-
- QPainterPath path = obj->path();
- QVERIFY(path != QPainterPath());
-
- QPointF pos = obj->pointAt(0);
- QCOMPARE(pos, QPointF(0,0));
- pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(63,26)); //fuzzy compare
- pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(51,105)); //fuzzy compare
- pos = obj->pointAt(1);
- QCOMPARE(pos, QPointF(100,150));
-}
-
-void tst_QDeclarativePath::svg()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("svg.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->startX(), 0.);
- QCOMPARE(obj->startY(), 0.);
-
- QDeclarativeListReference list(obj, "pathElements");
- QCOMPARE(list.count(), 1);
-
- QDeclarativePathSvg* svg = qobject_cast<QDeclarativePathSvg*>(list.at(0));
- QVERIFY(svg != 0);
- QCOMPARE(svg->path(), QLatin1String("M200,300 Q400,50 600,300 T1000,300"));
-
- QPainterPath path = obj->path();
- QVERIFY(path != QPainterPath());
-
- QPointF pos = obj->pointAt(0);
- QCOMPARE(pos, QPointF(200,300));
- pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(400,175)); //fuzzy compare
- pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(800,425)); //fuzzy compare
- pos = obj->pointAt(1);
- QCOMPARE(pos, QPointF(1000,300));
-}
-
-
-QTEST_MAIN(tst_QDeclarativePath)
-
-#include "tst_qdeclarativepath.moc"
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro b/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro
deleted file mode 100644
index 79d411c62c..0000000000
--- a/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativepixmapcache
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativepixmapcache.cpp
-
-INCLUDEPATH += ../shared/
-HEADERS += ../shared/testhttpserver.h
-SOURCES += ../shared/testhttpserver.cpp
-
-importFiles.files = data
-importFiles.path = .
-DEPLOYMENT += importFiles
-
-# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
-# LIBS += -lgcov
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp
deleted file mode 100644
index 7a1c9e6bfd..0000000000
--- a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QtTest>
-#include <private/qdeclarativepixmapcache_p.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativeimageprovider.h>
-#include <QNetworkReply>
-#include "../shared/util.h"
-#include "testhttpserver.h"
-
-#ifndef QT_NO_CONCURRENT
-#include <qtconcurrentrun.h>
-#include <qfuture.h>
-#endif
-
-inline QUrl TEST_FILE(const QString &filename)
-{
- return QUrl::fromLocalFile(TESTDATA(filename));
-}
-
-class tst_qdeclarativepixmapcache : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativepixmapcache() :
- server(14452)
- {
- server.serveDirectory(TESTDATA("http"));
- }
-
-private slots:
- void single();
- void single_data();
- void parallel();
- void parallel_data();
- void massive();
- void cancelcrash();
- void shrinkcache();
-#ifndef QT_NO_CONCURRENT
- void networkCrash();
-#endif
- void lockingCrash();
- void dataLeak();
-private:
- QDeclarativeEngine engine;
- TestHTTPServer server;
-};
-
-static int slotters=0;
-
-class Slotter : public QObject
-{
- Q_OBJECT
-public:
- Slotter()
- {
- gotslot = false;
- slotters++;
- }
- bool gotslot;
-
-public slots:
- void got()
- {
- gotslot = true;
- --slotters;
- if (slotters==0)
- QTestEventLoop::instance().exitLoop();
- }
-};
-
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
-static const bool localfile_optimized = true;
-#else
-static const bool localfile_optimized = false;
-#endif
-
-void tst_qdeclarativepixmapcache::single_data()
-{
- // Note, since QDeclarativePixmapCache is shared, tests affect each other!
- // so use different files fore all test functions.
-
- QTest::addColumn<QUrl>("target");
- QTest::addColumn<bool>("incache");
- QTest::addColumn<bool>("exists");
- QTest::addColumn<bool>("neterror");
-
- // File URLs are optimized
- QTest::newRow("local") << TEST_FILE("exists.png") << localfile_optimized << true << false;
- QTest::newRow("local") << TEST_FILE("notexists.png") << localfile_optimized << false << false;
- QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/exists.png") << false << true << false;
- QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/notexists.png") << false << false << true;
-}
-
-void tst_qdeclarativepixmapcache::single()
-{
- QFETCH(QUrl, target);
- QFETCH(bool, incache);
- QFETCH(bool, exists);
- QFETCH(bool, neterror);
-
- QString expectedError;
- if (neterror) {
- expectedError = "Error downloading " + target.toString() + " - server replied: Not found";
- } else if (!exists) {
- expectedError = "Cannot open: " + target.toString();
- }
-
- QDeclarativePixmap pixmap;
- QVERIFY(pixmap.width() <= 0); // Check Qt assumption
-
- pixmap.load(&engine, target);
-
- if (incache) {
- QCOMPARE(pixmap.error(), expectedError);
- if (exists) {
- QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
- QVERIFY(pixmap.width() > 0);
- } else {
- QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
- QVERIFY(pixmap.width() <= 0);
- }
- } else {
- QVERIFY(pixmap.width() <= 0);
-
- Slotter getter;
- pixmap.connectFinished(&getter, SLOT(got()));
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(getter.gotslot);
- if (exists) {
- QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
- QVERIFY(pixmap.width() > 0);
- } else {
- QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
- QVERIFY(pixmap.width() <= 0);
- }
- QCOMPARE(pixmap.error(), expectedError);
- }
-}
-
-void tst_qdeclarativepixmapcache::parallel_data()
-{
- // Note, since QDeclarativePixmapCache is shared, tests affect each other!
- // so use different files fore all test functions.
-
- QTest::addColumn<QUrl>("target1");
- QTest::addColumn<QUrl>("target2");
- QTest::addColumn<int>("incache");
- QTest::addColumn<int>("cancel"); // which one to cancel
-
- QTest::newRow("local")
- << TEST_FILE("exists1.png")
- << TEST_FILE("exists2.png")
- << (localfile_optimized ? 2 : 0)
- << -1;
-
- QTest::newRow("remote")
- << QUrl("http://127.0.0.1:14452/exists2.png")
- << QUrl("http://127.0.0.1:14452/exists3.png")
- << 0
- << -1;
-
- QTest::newRow("remoteagain")
- << QUrl("http://127.0.0.1:14452/exists2.png")
- << QUrl("http://127.0.0.1:14452/exists3.png")
- << 2
- << -1;
-
- QTest::newRow("remotecopy")
- << QUrl("http://127.0.0.1:14452/exists4.png")
- << QUrl("http://127.0.0.1:14452/exists4.png")
- << 0
- << -1;
-
- QTest::newRow("remotecopycancel")
- << QUrl("http://127.0.0.1:14452/exists5.png")
- << QUrl("http://127.0.0.1:14452/exists5.png")
- << 0
- << 0;
-}
-
-void tst_qdeclarativepixmapcache::parallel()
-{
- QFETCH(QUrl, target1);
- QFETCH(QUrl, target2);
- QFETCH(int, incache);
- QFETCH(int, cancel);
-
- QList<QUrl> targets;
- targets << target1 << target2;
-
- QList<QDeclarativePixmap *> pixmaps;
- QList<bool> pending;
- QList<Slotter*> getters;
-
- for (int i=0; i<targets.count(); ++i) {
- QUrl target = targets.at(i);
- QDeclarativePixmap *pixmap = new QDeclarativePixmap;
-
- pixmap->load(&engine, target);
-
- QVERIFY(pixmap->status() != QDeclarativePixmap::Error);
- pixmaps.append(pixmap);
- if (pixmap->isReady()) {
- QVERIFY(pixmap->width() > 0);
- getters.append(0);
- pending.append(false);
- } else {
- QVERIFY(pixmap->width() <= 0);
- getters.append(new Slotter);
- pixmap->connectFinished(getters[i], SLOT(got()));
- pending.append(true);
- }
- }
-
- QCOMPARE(incache+slotters, targets.count());
-
- if (cancel >= 0) {
- pixmaps.at(cancel)->clear(getters[cancel]);
- slotters--;
- }
-
- if (slotters) {
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- }
-
- for (int i=0; i<targets.count(); ++i) {
- QDeclarativePixmap *pixmap = pixmaps[i];
-
- if (i == cancel) {
- QVERIFY(!getters[i]->gotslot);
- } else {
- if (pending[i])
- QVERIFY(getters[i]->gotslot);
-
- QVERIFY(pixmap->isReady());
- QVERIFY(pixmap->width() > 0);
- delete getters[i];
- }
- }
-
- qDeleteAll(pixmaps);
-}
-
-void tst_qdeclarativepixmapcache::massive()
-{
- QDeclarativeEngine engine;
- QUrl url = TEST_FILE("massive.png");
-
- // Confirm that massive images remain in the cache while they are
- // in use by the application.
- {
- qint64 cachekey = 0;
- QDeclarativePixmap p(&engine, url);
- QVERIFY(p.isReady());
- QVERIFY(p.image().size() == QSize(10000, 1000));
- cachekey = p.image().cacheKey();
-
- QDeclarativePixmap p2(&engine, url);
- QVERIFY(p2.isReady());
- QVERIFY(p2.image().size() == QSize(10000, 1000));
-
- QVERIFY(p2.image().cacheKey() == cachekey);
- }
-
- // Confirm that massive images are removed from the cache when
- // they become unused
- {
- qint64 cachekey = 0;
- {
- QDeclarativePixmap p(&engine, url);
- QVERIFY(p.isReady());
- QVERIFY(p.image().size() == QSize(10000, 1000));
- cachekey = p.image().cacheKey();
- }
-
- QDeclarativePixmap p2(&engine, url);
- QVERIFY(p2.isReady());
- QVERIFY(p2.image().size() == QSize(10000, 1000));
-
- QVERIFY(p2.image().cacheKey() != cachekey);
- }
-}
-
-// QTBUG-12729
-void tst_qdeclarativepixmapcache::cancelcrash()
-{
- QUrl url("http://127.0.0.1:14452/cancelcrash_notexist.png");
- for (int ii = 0; ii < 1000; ++ii) {
- QDeclarativePixmap pix(&engine, url);
- }
-}
-
-class MyPixmapProvider : public QDeclarativeImageProvider
-{
-public:
- MyPixmapProvider()
- : QDeclarativeImageProvider(Pixmap) {}
-
- virtual QPixmap requestPixmap(const QString &d, QSize *, const QSize &) {
- Q_UNUSED(d)
- QPixmap pix(800, 600);
- pix.fill(Qt::red);
- return pix;
- }
-};
-
-// QTBUG-13345
-void tst_qdeclarativepixmapcache::shrinkcache()
-{
- QDeclarativeEngine engine;
- engine.addImageProvider(QLatin1String("mypixmaps"), new MyPixmapProvider);
-
- for (int ii = 0; ii < 4000; ++ii) {
- QUrl url("image://mypixmaps/" + QString::number(ii));
- QDeclarativePixmap p(&engine, url);
- }
-}
-
-#ifndef QT_NO_CONCURRENT
-
-void createNetworkServer()
-{
- QEventLoop eventLoop;
- TestHTTPServer server(14453);
- server.serveDirectory(TESTDATA("http"));
- QTimer::singleShot(100, &eventLoop, SLOT(quit()));
- eventLoop.exec();
-}
-
-#ifndef QT_NO_CONCURRENT
-// QT-3957
-void tst_qdeclarativepixmapcache::networkCrash()
-{
- QFuture<void> future = QtConcurrent::run(createNetworkServer);
- QDeclarativeEngine engine;
- for (int ii = 0; ii < 100 ; ++ii) {
- QDeclarativePixmap* pixmap = new QDeclarativePixmap;
- pixmap->load(&engine, QUrl(QString("http://127.0.0.1:14453/exists.png")));
- QTest::qSleep(1);
- pixmap->clear();
- delete pixmap;
- }
- future.cancel();
-}
-#endif
-
-#endif
-
-// QTBUG-22125
-void tst_qdeclarativepixmapcache::lockingCrash()
-{
- TestHTTPServer server(14453);
- server.serveDirectory(TESTDATA("http"), TestHTTPServer::Delay);
-
- {
- QDeclarativePixmap* p = new QDeclarativePixmap;
- {
- QDeclarativeEngine e;
- p->load(&e, QUrl(QString("http://127.0.0.1:14453/exists6.png")));
- }
- p->clear();
- QVERIFY(p->isNull());
- delete p;
- }
-}
-
-#include <QQuickView>
-class DataLeakView : public QQuickView
-{
- Q_OBJECT
-
-public:
- explicit DataLeakView() : QQuickView()
- {
- setSource(TEST_FILE("dataLeak.qml"));
- }
-
- void showFor2Seconds()
- {
- showFullScreen();
- QTimer::singleShot(2000, this, SIGNAL(ready()));
- }
-
-signals:
- void ready();
-};
-
-// QTBUG-22742
-Q_GLOBAL_STATIC(QDeclarativePixmap, dataLeakPixmap)
-void tst_qdeclarativepixmapcache::dataLeak()
-{
- // Should not leak cached QDeclarativePixmapData.
- // Unfortunately, since the QDeclarativePixmapStore
- // is a global static, and it releases the cache
- // entries on dtor (application exit), we must use
- // valgrind to determine whether it leaks or not.
- QDeclarativePixmap *p1 = new QDeclarativePixmap;
- QDeclarativePixmap *p2 = new QDeclarativePixmap;
- {
- QScopedPointer<DataLeakView> test(new DataLeakView);
- test->showFor2Seconds();
- dataLeakPixmap()->load(test->engine(), TEST_FILE("exists.png"));
- p1->load(test->engine(), TEST_FILE("exists.png"));
- p2->load(test->engine(), TEST_FILE("exists2.png"));
- QTest::qWait(2005); // 2 seconds + a few more millis.
- }
-
- // When the (global static) dataLeakPixmap is deleted, it
- // shouldn't attempt to dereference a QDeclarativePixmapData
- // which has been deleted by the QDeclarativePixmapStore
- // destructor.
-}
-
-QTEST_MAIN(tst_qdeclarativepixmapcache)
-
-#include "tst_qdeclarativepixmapcache.moc"
diff --git a/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp b/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp
index 411eeeacc7..b1aad3a34b 100644
--- a/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp
+++ b/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp
@@ -47,7 +47,7 @@
#include <QtWidgets/QLineEdit>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
inline QUrl TEST_FILE(const QString &filename)
{
diff --git a/tests/auto/declarative/qdeclarativepropertymap/qdeclarativepropertymap.pro b/tests/auto/declarative/qdeclarativepropertymap/qdeclarativepropertymap.pro
index a6332161a0..f94405c770 100644
--- a/tests/auto/declarative/qdeclarativepropertymap/qdeclarativepropertymap.pro
+++ b/tests/auto/declarative/qdeclarativepropertymap/qdeclarativepropertymap.pro
@@ -6,4 +6,4 @@ SOURCES += tst_qdeclarativepropertymap.cpp
CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
index cb2db47800..59a7fe7931 100644
--- a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
+++ b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
@@ -43,7 +43,7 @@
#include <QtDeclarative/qdeclarativecontext.h>
#include <QtDeclarative/qdeclarativepropertymap.h>
#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qquicktext_p.h>
+#include <QtQuick/private/qquicktext_p.h>
#include <QSignalSpy>
class tst_QDeclarativePropertyMap : public QObject
diff --git a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro
index 18fb8b2027..9428746dc1 100644
--- a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro
+++ b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro
@@ -9,4 +9,4 @@ DEPLOYMENT += testDataFiles
CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
index 293fcd382f..5b3ea5e169 100644
--- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
+++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
@@ -50,9 +50,9 @@
#include <QDir>
#include <QVector3D>
#include <QCryptographicHash>
-#include <QQuickItem>
+#include <QtQuick/QQuickItem>
#include <QSignalSpy>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativeqt : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro b/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro
deleted file mode 100644
index 05d31be39d..0000000000
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativesmoothedanimation
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativesmoothedanimation.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private testlib
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp b/tests/auto/declarative/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp
deleted file mode 100644
index 735af520fe..0000000000
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qdeclarativesmoothedanimation_p.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include "../shared/util.h"
-
-class tst_qdeclarativesmoothedanimation : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativesmoothedanimation();
-
-private slots:
- void defaultValues();
- void values();
- void disabled();
- void simpleAnimation();
- void valueSource();
- void behavior();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qdeclarativesmoothedanimation::tst_qdeclarativesmoothedanimation()
-{
-}
-
-void tst_qdeclarativesmoothedanimation::defaultValues()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation1.qml")));
- QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 0.);
- QCOMPARE(obj->velocity(), 200.);
- QCOMPARE(obj->duration(), -1);
- QCOMPARE(obj->maximumEasingTime(), -1);
- QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Eased);
-
- delete obj;
-}
-
-void tst_qdeclarativesmoothedanimation::values()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation2.qml")));
- QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 10.);
- QCOMPARE(obj->velocity(), 200.);
- QCOMPARE(obj->duration(), 300);
- QCOMPARE(obj->maximumEasingTime(), -1);
- QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Immediate);
-
- delete obj;
-}
-
-void tst_qdeclarativesmoothedanimation::disabled()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation3.qml")));
- QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 10.);
- QCOMPARE(obj->velocity(), 250.);
- QCOMPARE(obj->maximumEasingTime(), 150);
- QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Sync);
-
- delete obj;
-}
-
-void tst_qdeclarativesmoothedanimation::simpleAnimation()
-{
- QQuickRectangle rect;
- QDeclarativeSmoothedAnimation animation;
- animation.setTarget(&rect);
- animation.setProperty("x");
- animation.setTo(200);
- animation.setDuration(250);
- QVERIFY(animation.target() == &rect);
- QVERIFY(animation.property() == "x");
- QVERIFY(animation.to() == 200);
- animation.start();
- QVERIFY(animation.isRunning());
- QTest::qWait(animation.duration());
- QTRY_COMPARE(rect.x(), qreal(200));
-
- rect.setX(0);
- animation.start();
- animation.pause();
- QVERIFY(animation.isRunning());
- QVERIFY(animation.isPaused());
- animation.setCurrentTime(125);
- QVERIFY(animation.currentTime() == 125);
- QCOMPARE(rect.x(), qreal(100));
-}
-
-void tst_qdeclarativesmoothedanimation::valueSource()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimationValueSource.qml")));
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
- QVERIFY(theRect);
-
- QDeclarativeSmoothedAnimation *easeX = rect->findChild<QDeclarativeSmoothedAnimation*>("easeX");
- QVERIFY(easeX);
- QVERIFY(easeX->isRunning());
-
- QDeclarativeSmoothedAnimation *easeY = rect->findChild<QDeclarativeSmoothedAnimation*>("easeY");
- QVERIFY(easeY);
- QVERIFY(easeY->isRunning());
-
- // XXX get the proper duration
- QTest::qWait(100);
-
- QTRY_VERIFY(!easeX->isRunning());
- QTRY_VERIFY(!easeY->isRunning());
-
- QTRY_COMPARE(theRect->x(), qreal(200));
- QTRY_COMPARE(theRect->y(), qreal(200));
-
- delete rect;
-}
-
-void tst_qdeclarativesmoothedanimation::behavior()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimationBehavior.qml")));
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect);
-
- QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
- QVERIFY(theRect);
-
- QDeclarativeSmoothedAnimation *easeX = rect->findChild<QDeclarativeSmoothedAnimation*>("easeX");
- QVERIFY(easeX);
-
- QDeclarativeSmoothedAnimation *easeY = rect->findChild<QDeclarativeSmoothedAnimation*>("easeY");
- QVERIFY(easeY);
-
- // XXX get the proper duration
- QTest::qWait(400);
-
- QTRY_VERIFY(!easeX->isRunning());
- QTRY_VERIFY(!easeY->isRunning());
-
- QTRY_COMPARE(theRect->x(), qreal(200));
- QTRY_COMPARE(theRect->y(), qreal(200));
-
- delete rect;
-}
-
-QTEST_MAIN(tst_qdeclarativesmoothedanimation)
-
-#include "tst_qdeclarativesmoothedanimation.moc"
diff --git a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro b/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro
deleted file mode 100644
index 7153327829..0000000000
--- a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativespringanimation
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativespringanimation.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private testlib
diff --git a/tests/auto/declarative/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp b/tests/auto/declarative/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp
deleted file mode 100644
index d7edcee386..0000000000
--- a/tests/auto/declarative/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qdeclarativespringanimation_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include "../shared/util.h"
-
-class tst_qdeclarativespringanimation : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativespringanimation();
-
-private slots:
- void defaultValues();
- void values();
- void disabled();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qdeclarativespringanimation::tst_qdeclarativespringanimation()
-{
-}
-
-void tst_qdeclarativespringanimation::defaultValues()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation1.qml")));
- QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 0.);
- QCOMPARE(obj->velocity(), 0.);
- QCOMPARE(obj->spring(), 0.);
- QCOMPARE(obj->damping(), 0.);
- QCOMPARE(obj->epsilon(), 0.01);
- QCOMPARE(obj->modulus(), 0.);
- QCOMPARE(obj->mass(), 1.);
- QCOMPARE(obj->isRunning(), false);
-
- delete obj;
-}
-
-void tst_qdeclarativespringanimation::values()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation2.qml")));
- QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 1.44);
- QCOMPARE(obj->velocity(), 0.9);
- QCOMPARE(obj->spring(), 1.0);
- QCOMPARE(obj->damping(), 0.5);
- QCOMPARE(obj->epsilon(), 0.25);
- QCOMPARE(obj->modulus(), 360.0);
- QCOMPARE(obj->mass(), 2.0);
- QCOMPARE(obj->isRunning(), true);
-
- QTRY_COMPARE(obj->isRunning(), false);
-
- delete obj;
-}
-
-void tst_qdeclarativespringanimation::disabled()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation3.qml")));
- QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
-
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->to(), 1.44);
- QCOMPARE(obj->velocity(), 0.9);
- QCOMPARE(obj->spring(), 1.0);
- QCOMPARE(obj->damping(), 0.5);
- QCOMPARE(obj->epsilon(), 0.25);
- QCOMPARE(obj->modulus(), 360.0);
- QCOMPARE(obj->mass(), 2.0);
- QCOMPARE(obj->isRunning(), false);
-
- delete obj;
-}
-
-QTEST_MAIN(tst_qdeclarativespringanimation)
-
-#include "tst_qdeclarativespringanimation.moc"
diff --git a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro
index 2d0efec9a5..8b8c19c44c 100644
--- a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro
+++ b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro
@@ -10,4 +10,4 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private sql testlib
+QT += core-private gui-private v8-private declarative-private quick-private sql testlib
diff --git a/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp b/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
index f7c520d283..1a6b08cb79 100644
--- a/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
+++ b/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
@@ -41,7 +41,7 @@
#include <qtest.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qquicktext_p.h>
+#include <QtQuick/private/qquicktext_p.h>
#include <private/qdeclarativeengine_p.h>
#include <QtCore/qcryptographichash.h>
/*
@@ -53,7 +53,7 @@
#include <QtSql/qsqldatabase.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativesqldatabase : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro b/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro
deleted file mode 100644
index c0ffda7828..0000000000
--- a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativestates
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativestates.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
deleted file mode 100644
index 2535f89030..0000000000
--- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
+++ /dev/null
@@ -1,1596 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickstateoperations_p.h>
-#include <private/qquickanchors_p_p.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquickimage_p.h>
-#include <private/qdeclarativepropertychanges_p.h>
-#include <private/qdeclarativestategroup_p.h>
-#include <private/qquickitem_p.h>
-#include <private/qdeclarativeproperty_p.h>
-#include "../shared/util.h"
-
-class MyAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int foo READ foo WRITE setFoo)
-public:
- MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
-
- int foo() const { return m_foo; }
- void setFoo(int f) { m_foo = f; }
-
-private:
- int m_foo;
-};
-
-class MyRect : public QQuickRectangle
-{
- Q_OBJECT
- Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
-public:
- MyRect() {}
-
- void doSomething() { emit didSomething(); }
-
- int propertyWithNotify() const { return m_prop; }
- void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
-
- static MyAttached *qmlAttachedProperties(QObject *o) {
- return new MyAttached(o);
- }
-Q_SIGNALS:
- void didSomething();
- void oddlyNamedNotifySignal();
-
-private:
- int m_prop;
-};
-
-QML_DECLARE_TYPE(MyRect)
-QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
-
-class tst_qdeclarativestates : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativestates() {}
-
-private:
- static QByteArray fullDataPath(const QString &path);
-
-private slots:
- void initTestCase();
-
- void basicChanges();
- void attachedPropertyChanges();
- void basicExtension();
- void basicBinding();
- void signalOverride();
- void signalOverrideCrash();
- void signalOverrideCrash2();
- void signalOverrideCrash3();
- void parentChange();
- void parentChangeErrors();
- void anchorChanges();
- void anchorChanges2();
- void anchorChanges3();
- void anchorChanges4();
- void anchorChanges5();
- void anchorChangesRTL();
- void anchorChangesRTL2();
- void anchorChangesRTL3();
- void anchorChangesCrash();
- void anchorRewindBug();
- void anchorRewindBug2();
- void script();
- void restoreEntryValues();
- void explicitChanges();
- void propertyErrors();
- void incorrectRestoreBug();
- void autoStateAtStartupRestoreBug();
- void deletingChange();
- void deletingState();
- void tempState();
- void illegalTempState();
- void nonExistantProperty();
- void reset();
- void illegalObjectCreation();
- void whenOrdering();
- void urlResolution();
- void unnamedWhen();
- void returnToBase();
- void extendsBug();
- void editProperties();
- void QTBUG_14830();
- void avoidFastForward();
- void revertListBug();
-};
-
-void tst_qdeclarativestates::initTestCase()
-{
- qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
-}
-
-QByteArray tst_qdeclarativestates::fullDataPath(const QString &path)
-{
- return QUrl::fromLocalFile(TESTDATA(path)).toString().toUtf8();
-}
-
-void tst_qdeclarativestates::basicChanges()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("bordered");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),2.0);
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),1.0);
- //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
-
- rectPrivate->setState("bordered");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),2.0);
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),1.0);
-
- }
-
- {
- // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
- // signal using 'onPropertyWithNotifyChanged' even though the signal name is
- // actually 'oddlyNamedNotifySignal'
-
- QDeclarativeComponent component(&engine, TESTDATA("basicChanges4.qml"));
- QVERIFY(component.isReady());
-
- MyRect *rect = qobject_cast<MyRect*>(component.create());
- QVERIFY(rect != 0);
-
- QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
- QVERIFY(prop.hasNotifySignal());
- QString notifySignal = QByteArray(prop.notifySignal().signature());
- QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
-
- QCOMPARE(rect->color(), QColor(Qt::red));
-
- rect->setPropertyWithNotify(100);
- QCOMPARE(rect->color(), QColor(Qt::blue));
- }
-}
-
-void tst_qdeclarativestates::attachedPropertyChanges()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent component(&engine, TESTDATA("attachedPropertyChanges.qml"));
- QVERIFY(component.isReady());
-
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != 0);
- QCOMPARE(item->width(), 50.0);
-
- // Ensure attached property has been changed
- QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
- QVERIFY(attObj);
-
- MyAttached *att = qobject_cast<MyAttached*>(attObj);
- QVERIFY(att);
-
- QCOMPARE(att->foo(), 1);
-}
-
-void tst_qdeclarativestates::basicExtension()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicExtension.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("bordered");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),2.0);
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),1.0);
-
- rectPrivate->setState("bordered");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->border()->width(),2.0);
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->border()->width(),1.0);
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("fakeExtension.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
- }
-}
-
-void tst_qdeclarativestates::basicBinding()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- rect->setProperty("sourceColor", QColor("green"));
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- rect->setProperty("sourceColor", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("yellow"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- rect->setProperty("sourceColor", QColor("green"));
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("green"));
- rect->setProperty("sourceColor", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("yellow"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("yellow"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
- rect->setProperty("sourceColor", QColor("green"));
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- rect->setProperty("sourceColor", QColor("red"));
- QCOMPARE(rect->color(),QColor("blue"));
- rect->setProperty("sourceColor2", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("yellow"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- rect->setProperty("sourceColor2", QColor("green"));
- QCOMPARE(rect->color(),QColor("red"));
- rect->setProperty("sourceColor", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("yellow"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- rect->setProperty("sourceColor", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("yellow"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
- rect->setProperty("sourceColor", QColor("purple"));
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("purple"));
-
- rectPrivate->setState("green");
- QCOMPARE(rect->color(),QColor("green"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- }
-}
-
-void tst_qdeclarativestates::signalOverride()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverride.qml"));
- MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
- rect->doSomething();
- QCOMPARE(rect->color(),QColor("blue"));
-
- QQuickItemPrivate::get(rect)->setState("green");
- rect->doSomething();
- QCOMPARE(rect->color(),QColor("green"));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverride2.qml"));
- MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("white"));
- rect->doSomething();
- QCOMPARE(rect->color(),QColor("blue"));
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("extendedRect"));
- QQuickItemPrivate::get(innerRect)->setState("green");
- rect->doSomething();
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(innerRect->color(),QColor("green"));
- QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
- }
-}
-
-void tst_qdeclarativestates::signalOverrideCrash()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash.qml"));
- MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate::get(rect)->setState("overridden");
- rect->doSomething();
-}
-
-void tst_qdeclarativestates::signalOverrideCrash2()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QQuickItemPrivate::get(rect)->setState("state2");
- QQuickItemPrivate::get(rect)->setState("state1");
-
- delete rect;
-}
-
-void tst_qdeclarativestates::signalOverrideCrash3()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate::get(rect)->setState("state1");
- QQuickItemPrivate::get(rect)->setState("");
- QQuickItemPrivate::get(rect)->setState("state2");
- QQuickItemPrivate::get(rect)->setState("");
-
- delete rect;
-}
-
-void tst_qdeclarativestates::parentChange()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange1.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickParentChange *pChange = qobject_cast<QQuickParentChange*>(state->operationAt(0));
- QVERIFY(pChange != 0);
- QQuickItem *nParent = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("NewParent"));
- QVERIFY(nParent != 0);
-
- QCOMPARE(pChange->parent(), nParent);
-
- QQuickItemPrivate::get(rect)->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(0));
- QCOMPARE(innerRect->scale(), qreal(1));
- QCOMPARE(innerRect->x(), qreal(-133));
- QCOMPARE(innerRect->y(), qreal(-300));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- rectPrivate->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(15));
- QCOMPARE(innerRect->scale(), qreal(.5));
- QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-19.9075));
- QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-8.73433));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- rectPrivate->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(-37));
- QCOMPARE(innerRect->scale(), qreal(.25));
- QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
- QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->rotation(), qreal(0));
- QCOMPARE(innerRect->scale(), qreal(1));
- QCOMPARE(innerRect->x(), qreal(5));
- //do a non-qFuzzyCompare fuzzy compare
- QVERIFY(innerRect->y() < qreal(0.00001) && innerRect->y() > qreal(-0.00001));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange6.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QQuickItemPrivate::get(rect)->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(180));
- QCOMPARE(innerRect->scale(), qreal(1));
- QCOMPARE(innerRect->x(), qreal(-105));
- QCOMPARE(innerRect->y(), qreal(-105));
- }
-}
-
-void tst_qdeclarativestates::parentChangeErrors()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
- QQuickItemPrivate::get(rect)->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(0));
- QCOMPARE(innerRect->scale(), qreal(1));
- QCOMPARE(innerRect->x(), qreal(5));
- QCOMPARE(innerRect->y(), qreal(5));
- }
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
- QQuickItemPrivate::get(rect)->setState("reparented");
- QCOMPARE(innerRect->rotation(), qreal(0));
- QCOMPARE(innerRect->scale(), qreal(1));
- QCOMPARE(innerRect->x(), qreal(5));
- QCOMPARE(innerRect->y(), qreal(5));
- }
-}
-
-void tst_qdeclarativestates::anchorChanges()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges1.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- rectPrivate->setState("right");
- QCOMPARE(innerRect->x(), qreal(150));
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), qreal(5));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChanges2()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- rectPrivate->setState("right");
- QCOMPARE(innerRect->x(), qreal(150));
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), qreal(5));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChanges3()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
-
- QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- rectPrivate->setState("reanchored");
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
-
- QCOMPARE(innerRect->x(), qreal(10));
- QCOMPARE(innerRect->y(), qreal(0));
- QCOMPARE(innerRect->width(), qreal(190));
- QCOMPARE(innerRect->height(), qreal(150));
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), qreal(0));
- QCOMPARE(innerRect->y(), qreal(10));
- QCOMPARE(innerRect->width(), qreal(150));
- QCOMPARE(innerRect->height(), qreal(190));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChanges4()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
-
- QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- QQuickItemPrivate::get(rect)->setState("reanchored");
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QQuickItemPrivate::get(leftGuideline)->verticalCenter().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QQuickItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChanges5()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
-
- QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
-
- QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- QQuickItemPrivate::get(rect)->setState("reanchored");
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
- //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
- //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
- //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
-
- delete rect;
-}
-
-void mirrorAnchors(QQuickItem *item) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->setLayoutMirror(true);
-}
-
-qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
- return anchorItem->width()+2*anchorItem->x()-item->width();
-}
-
-void tst_qdeclarativestates::anchorChangesRTL()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges1.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
- mirrorAnchors(innerRect);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- rectPrivate->setState("right");
- QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChangesRTL2()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
- mirrorAnchors(innerRect);
-
- rectPrivate->setState("right");
- QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::anchorChangesRTL3()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
- mirrorAnchors(innerRect);
-
- QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
-
- QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
-
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
-
- rectPrivate->setState("reanchored");
- QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
-
- QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
- QCOMPARE(innerRect->y(), qreal(0));
- // between left side of parent and leftGuideline.x: 10, which has width 0
- QCOMPARE(innerRect->width(), qreal(10));
- QCOMPARE(innerRect->height(), qreal(150));
-
- rectPrivate->setState("");
- QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
- QCOMPARE(innerRect->y(), qreal(10));
- // between right side of parent and left side of rightGuideline.x: 150, which has width 0
- QCOMPARE(innerRect->width(), qreal(50));
- QCOMPARE(innerRect->height(), qreal(190));
-
- delete rect;
-}
-
-//QTBUG-9609
-void tst_qdeclarativestates::anchorChangesCrash()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChangesCrash.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate::get(rect)->setState("reanchored");
-
- delete rect;
-}
-
-// QTBUG-12273
-void tst_qdeclarativestates::anchorRewindBug()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("anchorRewindBug.qml")));
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
- QVERIFY(rect != 0);
-
- QQuickItem * column = rect->findChild<QQuickItem*>("column");
-
- QVERIFY(column != 0);
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
- QCOMPARE(column->height(), 200.0);
- QQuickItemPrivate::get(rect)->setState("reanchored");
-
- // column height and width should stay implicit
- // and column's implicit resizing should still work
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
- QTRY_COMPARE(column->height(), 100.0);
-
- QQuickItemPrivate::get(rect)->setState("");
-
- // column height and width should stay implicit
- // and column's implicit resizing should still work
- QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
- QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
- QTRY_COMPARE(column->height(), 200.0);
-
- delete view;
-}
-
-// QTBUG-11834
-void tst_qdeclarativestates::anchorRewindBug2()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorRewindBug2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
-
- QVERIFY(mover != 0);
- QCOMPARE(mover->y(), qreal(0.0));
- QCOMPARE(mover->width(), qreal(50.0));
-
- QQuickItemPrivate::get(rect)->setState("anchored");
- QCOMPARE(mover->y(), qreal(250.0));
- QCOMPARE(mover->width(), qreal(200.0));
-
- QQuickItemPrivate::get(rect)->setState("");
- QCOMPARE(mover->y(), qreal(0.0));
- QCOMPARE(mover->width(), qreal(50.0));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::script()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent rectComponent(&engine, TESTDATA("script.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
- }
-}
-
-void tst_qdeclarativestates::restoreEntryValues()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("restoreEntryValues.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("blue"));
-}
-
-void tst_qdeclarativestates::explicitChanges()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("explicit.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QDeclarativeListReference list(rect, "states");
- QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
- QVERIFY(state != 0);
-
- qmlExecuteDeferred(state);
- QDeclarativePropertyChanges *changes = qobject_cast<QDeclarativePropertyChanges*>(rect->findChild<QDeclarativePropertyChanges*>("changes"));
- QVERIFY(changes != 0);
- QVERIFY(changes->isExplicit());
-
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rect->setProperty("sourceColor", QColor("green"));
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- rect->setProperty("sourceColor", QColor("yellow"));
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("yellow"));
-}
-
-void tst_qdeclarativestates::propertyErrors()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent rectComponent(&engine, TESTDATA("propertyErrors.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QCOMPARE(rect->color(),QColor("red"));
-
- QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
- QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
- QQuickItemPrivate::get(rect)->setState("blue");
-}
-
-void tst_qdeclarativestates::incorrectRestoreBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QCOMPARE(rect->color(),QColor("red"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- // make sure if we change the base state value, we then restore to it correctly
- rect->setColor(QColor("green"));
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("green"));
-}
-
-void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent component(&engine, TESTDATA("autoStateAtStartupRestoreBug.qml"));
- QObject *obj = component.create();
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->property("test").toInt(), 3);
-
- obj->setProperty("input", 2);
-
- QCOMPARE(obj->property("test").toInt(), 9);
-
- delete obj;
-}
-
-void tst_qdeclarativestates::deletingChange()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("deleting.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
- QCOMPARE(rect->radius(),qreal(5));
-
- rectPrivate->setState("");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->radius(),qreal(0));
-
- QDeclarativePropertyChanges *pc = rect->findChild<QDeclarativePropertyChanges*>("pc1");
- QVERIFY(pc != 0);
- delete pc;
-
- QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
- QVERIFY(state != 0);
- qmlExecuteDeferred(state);
- QCOMPARE(state->operationCount(), 1);
-
- rectPrivate->setState("blue");
- QCOMPARE(rect->color(),QColor("red"));
- QCOMPARE(rect->radius(),qreal(5));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::deletingState()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("deletingState.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
-
- QDeclarativeStateGroup *sg = rect->findChild<QDeclarativeStateGroup*>();
- QVERIFY(sg != 0);
- QVERIFY(sg->findState("blue") != 0);
-
- sg->setState("blue");
- QCOMPARE(rect->color(),QColor("blue"));
-
- sg->setState("");
- QCOMPARE(rect->color(),QColor("red"));
-
- QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
- QVERIFY(state != 0);
- delete state;
-
- QVERIFY(sg->findState("blue") == 0);
-
- //### should we warn that state doesn't exist
- sg->setState("blue");
- QCOMPARE(rect->color(),QColor("red"));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::tempState()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("legalTempState.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QTest::ignoreMessage(QtDebugMsg, "entering placed");
- QTest::ignoreMessage(QtDebugMsg, "entering idle");
- rectPrivate->setState("placed");
- QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
-}
-
-void tst_qdeclarativestates::illegalTempState()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("illegalTempState.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
- rectPrivate->setState("placed");
- QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
-}
-
-void tst_qdeclarativestates::nonExistantProperty()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent rectComponent(&engine, TESTDATA("nonExistantProp.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
- rectPrivate->setState("blue");
- QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
-}
-
-void tst_qdeclarativestates::reset()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("reset.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickImage *image = rect->findChild<QQuickImage*>();
- QVERIFY(image != 0);
- QCOMPARE(image->width(), qreal(40.));
- QCOMPARE(image->height(), qreal(20.));
-
- QQuickItemPrivate::get(rect)->setState("state1");
-
- QCOMPARE(image->width(), 20.0);
- QCOMPARE(image->height(), qreal(20.));
-
- delete rect;
-}
-
-void tst_qdeclarativestates::illegalObjectCreation()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent component(&engine, TESTDATA("illegalObj.qml"));
- QList<QDeclarativeError> errors = component.errors();
- QVERIFY(errors.count() == 1);
- const QDeclarativeError &error = errors.at(0);
- QCOMPARE(error.line(), 9);
- QCOMPARE(error.column(), 23);
- QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
-}
-
-void tst_qdeclarativestates::whenOrdering()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("whenOrdering.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
- rect->setProperty("condition2", true);
- QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
- rect->setProperty("condition1", true);
- QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
- rect->setProperty("condition2", false);
- QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
- rect->setProperty("condition2", true);
- QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
- rect->setProperty("condition1", false);
- rect->setProperty("condition2", false);
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
-}
-
-void tst_qdeclarativestates::urlResolution()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("urlResolution.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
- QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
- QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
- QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
- QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
-
- QQuickItemPrivate::get(myType)->setState("SetImageState");
- QUrl resolved = QUrl::fromLocalFile(TESTDATA("Implementation/images/qt-logo.png"));
- QCOMPARE(image1->source(), resolved);
- QCOMPARE(image2->source(), resolved);
- QCOMPARE(image3->source(), resolved);
-
- delete rect;
-}
-
-void tst_qdeclarativestates::unnamedWhen()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("unnamedWhen.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
- rect->setProperty("triggerState", true);
- QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
- rect->setProperty("triggerState", false);
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
-}
-
-void tst_qdeclarativestates::returnToBase()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("returnToBase.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
- rect->setProperty("triggerState", true);
- QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
- rect->setProperty("triggerState", false);
- QCOMPARE(rectPrivate->state(), QLatin1String(""));
- QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
-}
-
-//QTBUG-12559
-void tst_qdeclarativestates::extendsBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("extendsBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
-
- rectPrivate->setState("b");
- QCOMPARE(greenRect->x(), qreal(100));
- QCOMPARE(greenRect->y(), qreal(100));
-}
-
-void tst_qdeclarativestates::editProperties()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("editProperties.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QDeclarativeStateGroup *stateGroup = rectPrivate->_states();
- QVERIFY(stateGroup != 0);
- qmlExecuteDeferred(stateGroup);
-
- QDeclarativeState *blueState = stateGroup->findState("blue");
- QVERIFY(blueState != 0);
- qmlExecuteDeferred(blueState);
-
- QDeclarativePropertyChanges *propertyChangesBlue = qobject_cast<QDeclarativePropertyChanges*>(blueState->operationAt(0));
- QVERIFY(propertyChangesBlue != 0);
-
- QDeclarativeState *greenState = stateGroup->findState("green");
- QVERIFY(greenState != 0);
- qmlExecuteDeferred(greenState);
-
- QDeclarativePropertyChanges *propertyChangesGreen = qobject_cast<QDeclarativePropertyChanges*>(greenState->operationAt(0));
- QVERIFY(propertyChangesGreen != 0);
-
- QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
- QVERIFY(childRect != 0);
- QCOMPARE(childRect->width(), qreal(402));
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- QCOMPARE(childRect->height(), qreal(200));
-
- rectPrivate->setState("blue");
- QCOMPARE(childRect->width(), qreal(50));
- QCOMPARE(childRect->height(), qreal(40));
- QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- QVERIFY(blueState->bindingInRevertList(childRect, "width"));
-
-
- rectPrivate->setState("green");
- QCOMPARE(childRect->width(), qreal(200));
- QCOMPARE(childRect->height(), qreal(100));
- QVERIFY(greenState->bindingInRevertList(childRect, "width"));
-
-
- rectPrivate->setState("");
-
-
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
- QVERIFY(propertyChangesBlue->containsValue("width"));
- QVERIFY(!propertyChangesBlue->containsProperty("x"));
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
- QVERIFY(!propertyChangesBlue->value("x").isValid());
-
- propertyChangesBlue->changeValue("width", 60);
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
-
-
- propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
- QVERIFY(!propertyChangesBlue->containsValue("width"));
- QVERIFY(propertyChangesBlue->containsExpression("width"));
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
-
- propertyChangesBlue->changeValue("width", 50);
- QVERIFY(propertyChangesBlue->containsValue("width"));
- QVERIFY(!propertyChangesBlue->containsExpression("width"));
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
-
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- rectPrivate->setState("blue");
- QCOMPARE(childRect->width(), qreal(50));
- QCOMPARE(childRect->height(), qreal(40));
-
- propertyChangesBlue->changeValue("width", 60);
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
- QCOMPARE(childRect->width(), qreal(60));
- QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
-
- propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
- QVERIFY(!propertyChangesBlue->containsValue("width"));
- QVERIFY(propertyChangesBlue->containsExpression("width"));
- QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
- QCOMPARE(propertyChangesBlue->actions().length(), 2);
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- QCOMPARE(childRect->width(), qreal(200));
-
- propertyChangesBlue->changeValue("width", 50);
- QCOMPARE(childRect->width(), qreal(50));
-
- rectPrivate->setState("");
- QCOMPARE(childRect->width(), qreal(402));
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
-
- QCOMPARE(propertyChangesGreen->actions().length(), 2);
- rectPrivate->setState("green");
- QCOMPARE(childRect->width(), qreal(200));
- QCOMPARE(childRect->height(), qreal(100));
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- QVERIFY(greenState->bindingInRevertList(childRect, "width"));
- QCOMPARE(propertyChangesGreen->actions().length(), 2);
-
-
- propertyChangesGreen->removeProperty("height");
- QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
- QCOMPARE(childRect->height(), qreal(200));
-
- QVERIFY(greenState->bindingInRevertList(childRect, "width"));
- QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
- propertyChangesGreen->removeProperty("width");
- QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
- QCOMPARE(childRect->width(), qreal(402));
- QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
- QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
-
- propertyChangesBlue->removeProperty("width");
- QCOMPARE(childRect->width(), qreal(402));
-
- rectPrivate->setState("blue");
- QCOMPARE(childRect->width(), qreal(402));
- QCOMPARE(childRect->height(), qreal(40));
-}
-
-void tst_qdeclarativestates::QTBUG_14830()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("QTBUG-14830.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
- QQuickItem *item = rect->findChild<QQuickItem*>("area");
-
- QCOMPARE(item->width(), qreal(171));
-}
-
-void tst_qdeclarativestates::avoidFastForward()
-{
- QDeclarativeEngine engine;
-
- //shouldn't fast forward if there isn't a transition
- QDeclarativeComponent c(&engine, TESTDATA("avoidFastForward.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- rectPrivate->setState("a");
- QCOMPARE(rect->property("updateCount").toInt(), 1);
-}
-
-//QTBUG-22583
-void tst_qdeclarativestates::revertListBug()
-{
- QDeclarativeEngine engine;
-
- QDeclarativeComponent c(&engine, TESTDATA("revertListBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
-
- QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
- QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
- QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
- QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
- QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
-
- QCOMPARE(rect1->parentItem(), origParent1);
- QCOMPARE(rect2->parentItem(), origParent2);
-
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- rectPrivate->setState("reparented");
-
- QCOMPARE(rect1->parentItem(), newParent);
- QCOMPARE(rect2->parentItem(), origParent2);
-
- rectPrivate->setState("");
-
- QCOMPARE(rect1->parentItem(), origParent1);
- QCOMPARE(rect2->parentItem(), origParent2);
-
- QMetaObject::invokeMethod(rect, "switchTargetItem");
-
- rectPrivate->setState("reparented");
-
- QCOMPARE(rect1->parentItem(), origParent1);
- QCOMPARE(rect2->parentItem(), newParent);
-
- rectPrivate->setState("");
-
- QCOMPARE(rect1->parentItem(), origParent1);
- QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
-}
-
-QTEST_MAIN(tst_qdeclarativestates)
-
-#include "tst_qdeclarativestates.moc"
diff --git a/tests/auto/declarative/qdeclarativestyledtext/qdeclarativestyledtext.pro b/tests/auto/declarative/qdeclarativestyledtext/qdeclarativestyledtext.pro
deleted file mode 100644
index 70e6fafe59..0000000000
--- a/tests/auto/declarative/qdeclarativestyledtext/qdeclarativestyledtext.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativestyledtext
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativestyledtext.cpp
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qdeclarativesystempalette/qdeclarativesystempalette.pro b/tests/auto/declarative/qdeclarativesystempalette/qdeclarativesystempalette.pro
deleted file mode 100644
index 4eee37678f..0000000000
--- a/tests/auto/declarative/qdeclarativesystempalette/qdeclarativesystempalette.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativesystempalette
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativesystempalette.cpp
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private widgets testlib
diff --git a/tests/auto/declarative/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp b/tests/auto/declarative/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp
deleted file mode 100644
index 8c9543273c..0000000000
--- a/tests/auto/declarative/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QDebug>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/private/qdeclarativesystempalette_p.h>
-#include <qpalette.h>
-
-class tst_qdeclarativesystempalette : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativesystempalette();
-
-private slots:
- void activePalette();
- void inactivePalette();
- void disabledPalette();
- void paletteChanged();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qdeclarativesystempalette::tst_qdeclarativesystempalette()
-{
-}
-
-void tst_qdeclarativesystempalette::activePalette()
-{
- QString componentStr = "import QtQuick 2.0\nSystemPalette { }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
-
- QVERIFY(object != 0);
-
- QPalette palette;
- palette.setCurrentColorGroup(QPalette::Active);
- QCOMPARE(palette.window().color(), object->window());
- QCOMPARE(palette.windowText().color(), object->windowText());
- QCOMPARE(palette.base().color(), object->base());
- QCOMPARE(palette.text().color(), object->text());
- QCOMPARE(palette.alternateBase().color(), object->alternateBase());
- QCOMPARE(palette.button().color(), object->button());
- QCOMPARE(palette.buttonText().color(), object->buttonText());
- QCOMPARE(palette.light().color(), object->light());
- QCOMPARE(palette.midlight().color(), object->midlight());
- QCOMPARE(palette.dark().color(), object->dark());
- QCOMPARE(palette.mid().color(), object->mid());
- QCOMPARE(palette.shadow().color(), object->shadow());
- QCOMPARE(palette.highlight().color(), object->highlight());
- QCOMPARE(palette.highlightedText().color(), object->highlightedText());
-
- delete object;
-}
-
-void tst_qdeclarativesystempalette::inactivePalette()
-{
- QString componentStr = "import QtQuick 2.0\nSystemPalette { colorGroup: SystemPalette.Inactive }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
-
- QVERIFY(object != 0);
- QVERIFY(object->colorGroup() == QDeclarativeSystemPalette::Inactive);
-
- QPalette palette;
- palette.setCurrentColorGroup(QPalette::Inactive);
- QCOMPARE(palette.window().color(), object->window());
- QCOMPARE(palette.windowText().color(), object->windowText());
- QCOMPARE(palette.base().color(), object->base());
- QCOMPARE(palette.text().color(), object->text());
- QCOMPARE(palette.alternateBase().color(), object->alternateBase());
- QCOMPARE(palette.button().color(), object->button());
- QCOMPARE(palette.buttonText().color(), object->buttonText());
- QCOMPARE(palette.light().color(), object->light());
- QCOMPARE(palette.midlight().color(), object->midlight());
- QCOMPARE(palette.dark().color(), object->dark());
- QCOMPARE(palette.mid().color(), object->mid());
- QCOMPARE(palette.shadow().color(), object->shadow());
- QCOMPARE(palette.highlight().color(), object->highlight());
- QCOMPARE(palette.highlightedText().color(), object->highlightedText());
-
- delete object;
-}
-
-void tst_qdeclarativesystempalette::disabledPalette()
-{
- QString componentStr = "import QtQuick 2.0\nSystemPalette { colorGroup: SystemPalette.Disabled }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
-
- QVERIFY(object != 0);
- QVERIFY(object->colorGroup() == QDeclarativeSystemPalette::Disabled);
-
- QPalette palette;
- palette.setCurrentColorGroup(QPalette::Disabled);
- QCOMPARE(palette.window().color(), object->window());
- QCOMPARE(palette.windowText().color(), object->windowText());
- QCOMPARE(palette.base().color(), object->base());
- QCOMPARE(palette.text().color(), object->text());
- QCOMPARE(palette.alternateBase().color(), object->alternateBase());
- QCOMPARE(palette.button().color(), object->button());
- QCOMPARE(palette.buttonText().color(), object->buttonText());
- QCOMPARE(palette.light().color(), object->light());
- QCOMPARE(palette.midlight().color(), object->midlight());
- QCOMPARE(palette.dark().color(), object->dark());
- QCOMPARE(palette.mid().color(), object->mid());
- QCOMPARE(palette.shadow().color(), object->shadow());
- QCOMPARE(palette.highlight().color(), object->highlight());
- QCOMPARE(palette.highlightedText().color(), object->highlightedText());
-
- delete object;
-}
-
-void tst_qdeclarativesystempalette::paletteChanged()
-{
- QString componentStr = "import QtQuick 2.0\nSystemPalette { }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
-
- QVERIFY(object != 0);
-
- QPalette p;
- p.setCurrentColorGroup(QPalette::Active);
- p.setColor(QPalette::Active, QPalette::Text, QColor("red"));
- p.setColor(QPalette::Active, QPalette::ButtonText, QColor("green"));
- p.setColor(QPalette::Active, QPalette::WindowText, QColor("blue"));
-
- qApp->setPalette(p);
-
- object->setColorGroup(QDeclarativeSystemPalette::Active);
- QTRY_COMPARE(QColor("red"), object->text());
- QTRY_COMPARE(QColor("green"), object->buttonText());
- QTRY_COMPARE(QColor("blue"), object->windowText());
-
- delete object;
-}
-
-QTEST_MAIN(tst_qdeclarativesystempalette)
-
-#include "tst_qdeclarativesystempalette.moc"
diff --git a/tests/auto/declarative/qdeclarativetimer/qdeclarativetimer.pro b/tests/auto/declarative/qdeclarativetimer/qdeclarativetimer.pro
deleted file mode 100644
index 60e59f01f6..0000000000
--- a/tests/auto/declarative/qdeclarativetimer/qdeclarativetimer.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qdeclarativetimer
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qdeclarativetimer.cpp
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private gui testlib
diff --git a/tests/auto/declarative/qdeclarativetimer/tst_qdeclarativetimer.cpp b/tests/auto/declarative/qdeclarativetimer/tst_qdeclarativetimer.cpp
deleted file mode 100644
index 1e795099e8..0000000000
--- a/tests/auto/declarative/qdeclarativetimer/tst_qdeclarativetimer.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QSignalSpy>
-#include <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qdeclarativetimer_p.h>
-#include <QtDeclarative/qquickitem.h>
-#include <QDebug>
-
-class tst_qdeclarativetimer : public QObject
-{
- Q_OBJECT
-public:
- tst_qdeclarativetimer();
-
-private slots:
- void notRepeating();
- void notRepeatingStart();
- void repeat();
- void noTriggerIfNotRunning();
- void triggeredOnStart();
- void triggeredOnStartRepeat();
- void changeDuration();
- void restart();
- void parentProperty();
-};
-
-class TimerHelper : public QObject
-{
- Q_OBJECT
-public:
- TimerHelper() : QObject(), count(0)
- {
- }
-
- int count;
-
-public slots:
- void timeout() {
- ++count;
- }
-};
-
-#define TIMEOUT_TIMEOUT 200
-
-tst_qdeclarativetimer::tst_qdeclarativetimer()
-{
-}
-
-void tst_qdeclarativetimer::notRepeating()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
- QVERIFY(timer->isRunning());
- QVERIFY(!timer->isRepeating());
- QCOMPARE(timer->interval(), 100);
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 1);
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 1);
- QVERIFY(timer->isRunning() == false);
-}
-
-void tst_qdeclarativetimer::notRepeatingStart()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
- QVERIFY(!timer->isRunning());
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 0);
-
- timer->start();
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 1);
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 1);
- QVERIFY(timer->isRunning() == false);
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::repeat()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
- QCOMPARE(helper.count, 0);
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QVERIFY(helper.count > 0);
- int oldCount = helper.count;
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QVERIFY(helper.count > oldCount);
- QVERIFY(timer->isRunning());
-
- oldCount = helper.count;
- timer->stop();
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QVERIFY(helper.count == oldCount);
- QVERIFY(timer->isRunning() == false);
-
- QSignalSpy spy(timer, SIGNAL(repeatChanged()));
-
- timer->setRepeating(false);
- QVERIFY(!timer->isRepeating());
- QCOMPARE(spy.count(),1);
-
- timer->setRepeating(false);
- QCOMPARE(spy.count(),1);
-
- timer->setRepeating(true);
- QCOMPARE(spy.count(),2);
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::triggeredOnStart()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
- QVERIFY(timer->triggeredOnStart());
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
- QTest::qWait(1);
- QCOMPARE(helper.count, 1);
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 2);
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(helper.count, 2);
- QVERIFY(timer->isRunning() == false);
-
- QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged()));
-
- timer->setTriggeredOnStart(false);
- QVERIFY(!timer->triggeredOnStart());
- QCOMPARE(spy.count(),1);
-
- timer->setTriggeredOnStart(false);
- QCOMPARE(spy.count(),1);
-
- timer->setTriggeredOnStart(true);
- QCOMPARE(spy.count(),2);
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::triggeredOnStartRepeat()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
- QTest::qWait(1);
- QCOMPARE(helper.count, 1);
-
- QTest::qWait(TIMEOUT_TIMEOUT);
- QVERIFY(helper.count > 1);
- int oldCount = helper.count;
- QTest::qWait(TIMEOUT_TIMEOUT);
- QVERIFY(helper.count > oldCount);
- QVERIFY(timer->isRunning());
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::noTriggerIfNotRunning()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray(
- "import QtQuick 2.0\n"
- "Item { property bool ok: true\n"
- "Timer { id: t1; interval: 100; repeat: true; running: true; onTriggered: if (!running) ok=false }"
- "Timer { interval: 10; running: true; onTriggered: t1.running=false }"
- "}"
- ), QUrl::fromLocalFile(""));
- QObject *item = component.create();
- QVERIFY(item != 0);
- QTest::qWait(TIMEOUT_TIMEOUT);
- QCOMPARE(item->property("ok").toBool(), true);
-
- delete item;
-}
-
-void tst_qdeclarativetimer::changeDuration()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
- QCOMPARE(helper.count, 0);
-
- QTest::qWait(500);
- QCOMPARE(helper.count, 2);
-
- timer->setInterval(500);
-
- QTest::qWait(600);
- QCOMPARE(helper.count, 3);
- QVERIFY(timer->isRunning());
-
- QSignalSpy spy(timer, SIGNAL(intervalChanged()));
-
- timer->setInterval(200);
- QCOMPARE(timer->interval(), 200);
- QCOMPARE(spy.count(),1);
-
- timer->setInterval(200);
- QCOMPARE(spy.count(),1);
-
- timer->setInterval(300);
- QCOMPARE(spy.count(),2);
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::restart()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
- QVERIFY(timer != 0);
-
- TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
- QCOMPARE(helper.count, 0);
-
- QTest::qWait(600);
- QCOMPARE(helper.count, 1);
-
- QTest::qWait(300);
-
- timer->restart();
-
- QTest::qWait(700);
-
- QCOMPARE(helper.count, 2);
- QVERIFY(timer->isRunning());
-
- delete timer;
-}
-
-void tst_qdeclarativetimer::parentProperty()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != 0);
- QDeclarativeTimer *timer = item->findChild<QDeclarativeTimer*>("timer");
- QVERIFY(timer != 0);
-
- QVERIFY(timer->isRunning());
-
- delete timer;
-}
-
-QTEST_MAIN(tst_qdeclarativetimer)
-
-#include "tst_qdeclarativetimer.moc"
diff --git a/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp b/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp
index be257fdc41..da84167148 100644
--- a/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp
+++ b/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp
@@ -43,7 +43,7 @@
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
#include <QTranslator>
-#include "../shared/util.h"
+#include "../../shared/util.h"
class tst_qdeclarativetranslation : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp
index db0e05bcf2..c6880b96ce 100644
--- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp
+++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp
@@ -44,7 +44,7 @@
#include <QDeclarativeComponent>
#include <QDebug>
#include <private/qdeclarativevaluetype_p.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
#include "testtypes.h"
QT_BEGIN_NAMESPACE
diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
index eb3413ec10..7dccbb35a0 100644
--- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
+++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
@@ -50,7 +50,7 @@
#include <private/qdeclarativeworkerscript_p.h>
#include <private/qdeclarativeengine_p.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
inline QUrl TEST_FILE(const QString &filename)
{
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro b/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro
index 0e6073b503..5715f3c114 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro
@@ -2,11 +2,11 @@ CONFIG += testcase
TARGET = tst_qdeclarativexmlhttprequest
macx:CONFIG -= app_bundle
-INCLUDEPATH += ../shared/
-HEADERS += ../shared/testhttpserver.h
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
SOURCES += tst_qdeclarativexmlhttprequest.cpp \
- ../shared/testhttpserver.cpp
+ ../../shared/testhttpserver.cpp
testDataFiles.files = data
testDataFiles.path = .
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
index 1caec581cc..da5431c50b 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
@@ -45,7 +45,7 @@
#include <QDebug>
#include <QNetworkCookieJar>
#include "testhttpserver.h"
-#include "../shared/util.h"
+#include "../../shared/util.h"
#define SERVER_PORT 14445
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
deleted file mode 100644
index c2cf4a69f6..0000000000
--- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
+++ /dev/null
@@ -1,961 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtGlobal>
-#include <math.h>
-#include <QMetaObject>
-#include <qtest.h>
-#include <QtTest/qsignalspy.h>
-#include <QtDeclarative/qdeclarativenetworkaccessmanagerfactory.h>
-#include <QtNetwork/qnetworkaccessmanager.h>
-#include <QtNetwork/qnetworkrequest.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qtemporaryfile.h>
-#include "../shared/util.h"
-#include <private/qdeclarativeengine_p.h>
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qlistmodelinterface_p.h>
-#include "../../../../src/imports/xmllistmodel/qdeclarativexmllistmodel_p.h"
-
-typedef QPair<int, int> QDeclarativeXmlListRange;
-typedef QList<QVariantList> QDeclarativeXmlModelData;
-
-Q_DECLARE_METATYPE(QList<QDeclarativeXmlListRange>)
-Q_DECLARE_METATYPE(QDeclarativeXmlModelData)
-Q_DECLARE_METATYPE(QDeclarativeXmlListModel::Status)
-
-class tst_qdeclarativexmllistmodel : public QObject
-
-{
- Q_OBJECT
-public:
- tst_qdeclarativexmllistmodel() {}
-
-private slots:
- void initTestCase() {
- qRegisterMetaType<QDeclarativeXmlListModel::Status>();
- }
-
- void buildModel();
- void testTypes();
- void testTypes_data();
- void cdata();
- void attributes();
- void roles();
- void roleErrors();
- void uniqueRoleNames();
- void headers();
- void xml();
- void xml_data();
- void source();
- void source_data();
- void data();
- void get();
- void reload();
- void useKeys();
- void useKeys_data();
- void noKeysValueChanges();
- void keysChanged();
- void threading();
- void threading_data();
- void propertyChanges();
-
- void roleCrash();
-
-private:
- QString errorString(QListModelInterface* model) {
- QString ret;
- QMetaObject::invokeMethod(model, "errorString", Q_RETURN_ARG(QString, ret));
- return ret;
- }
-
- QString makeItemXmlAndData(const QString &data, QDeclarativeXmlModelData *modelData = 0) const
- {
- if (modelData)
- modelData->clear();
- QString xml;
-
- if (!data.isEmpty()) {
- QStringList items = data.split(";");
- foreach(const QString &item, items) {
- if (item.isEmpty())
- continue;
- QVariantList variants;
- xml += QLatin1String("<item>");
- QStringList fields = item.split(",");
- foreach(const QString &field, fields) {
- QStringList values = field.split("=");
- if (values.count() != 2) {
- qWarning() << "makeItemXmlAndData: invalid field:" << field;
- continue;
- }
- xml += QString("<%1>%2</%1>").arg(values[0], values[1]);
- if (!modelData)
- continue;
- bool isNum = false;
- int number = values[1].toInt(&isNum);
- if (isNum)
- variants << number;
- else
- variants << values[1];
- }
- xml += QLatin1String("</item>");
- if (modelData)
- modelData->append(variants);
- }
- }
-
- QString decl = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>";
- return decl + QLatin1String("<data>") + xml + QLatin1String("</data>");
- }
-
- QDeclarativeEngine engine;
-};
-
-class CustomNetworkAccessManagerFactory : public QObject, public QDeclarativeNetworkAccessManagerFactory
-{
- Q_OBJECT
-public:
- QVariantMap lastSentHeaders;
-
-protected:
- QNetworkAccessManager *create(QObject *parent);
-};
-
-class CustomNetworkAccessManager : public QNetworkAccessManager
-{
- Q_OBJECT
-public:
- CustomNetworkAccessManager(CustomNetworkAccessManagerFactory *factory, QObject *parent)
- : QNetworkAccessManager(parent), m_factory(factory) {}
-
-protected:
- QNetworkReply *createRequest(Operation op, const QNetworkRequest &req, QIODevice * outgoingData = 0)
- {
- if (m_factory) {
- QVariantMap map;
- foreach (const QString &header, req.rawHeaderList())
- map[header] = req.rawHeader(header.toUtf8());
- m_factory->lastSentHeaders = map;
- }
- return QNetworkAccessManager::createRequest(op, req, outgoingData);
- }
-
- QPointer<CustomNetworkAccessManagerFactory> m_factory;
-};
-
-QNetworkAccessManager *CustomNetworkAccessManagerFactory::create(QObject *parent)
-{
- return new CustomNetworkAccessManager(this, parent);
-}
-
-
-void tst_qdeclarativexmllistmodel::buildModel()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
- QCOMPARE(model->data(3, Qt::UserRole).toString(), QLatin1String("Spot"));
- QCOMPARE(model->data(3, Qt::UserRole+1).toString(), QLatin1String("Dog"));
- QCOMPARE(model->data(3, Qt::UserRole+2).toInt(), 9);
- QCOMPARE(model->data(3, Qt::UserRole+3).toString(), QLatin1String("Medium"));
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::testTypes()
-{
- QFETCH(QString, xml);
- QFETCH(QString, roleName);
- QFETCH(QVariant, expectedValue);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("testtypes.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- model->setProperty("xml",xml.toUtf8());
- QMetaObject::invokeMethod(model, "reload");
- QTRY_COMPARE(model->count(), 1);
-
- int role = -1;
- foreach (int i, model->roles()) {
- if (model->toString(i) == roleName) {
- role = i;
- break;
- }
- }
- QVERIFY(role >= 0);
-
- if (expectedValue.toString() == "nan")
- QVERIFY(qIsNaN(model->data(0, role).toDouble()));
- else
- QCOMPARE(model->data(0, role), expectedValue);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::testTypes_data()
-{
- QTest::addColumn<QString>("xml");
- QTest::addColumn<QString>("roleName");
- QTest::addColumn<QVariant>("expectedValue");
-
- QTest::newRow("missing string field") << "<data></data>"
- << "stringValue" << QVariant("");
- QTest::newRow("empty string") << "<data><a-string></a-string></data>"
- << "stringValue" << QVariant("");
- QTest::newRow("1-char string") << "<data><a-string>5</a-string></data>"
- << "stringValue" << QVariant("5");
- QTest::newRow("string ok") << "<data><a-string>abc def g</a-string></data>"
- << "stringValue" << QVariant("abc def g");
-
- QTest::newRow("missing number field") << "<data></data>"
- << "numberValue" << QVariant("");
- double nan = qQNaN();
- QTest::newRow("empty number field") << "<data><a-number></a-number></data>"
- << "numberValue" << QVariant(nan);
- QTest::newRow("number field with string") << "<data><a-number>a string</a-number></data>"
- << "numberValue" << QVariant(nan);
- QTest::newRow("-1") << "<data><a-number>-1</a-number></data>"
- << "numberValue" << QVariant("-1");
- QTest::newRow("-1.5") << "<data><a-number>-1.5</a-number></data>"
- << "numberValue" << QVariant("-1.5");
- QTest::newRow("0") << "<data><a-number>0</a-number></data>"
- << "numberValue" << QVariant("0");
- QTest::newRow("+1") << "<data><a-number>1</a-number></data>"
- << "numberValue" << QVariant("1");
- QTest::newRow("+1.5") << "<data><a-number>1.5</a-number></data>"
- << "numberValue" << QVariant("1.5");
-}
-
-void tst_qdeclarativexmllistmodel::cdata()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("recipes.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 5);
-
- QVERIFY(model->data(2, Qt::UserRole+2).toString().startsWith(QLatin1String("<html>")));
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::attributes()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("recipes.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 5);
- QCOMPARE(model->data(2, Qt::UserRole).toString(), QLatin1String("Vegetable Soup"));
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::roles()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
- QList<int> roles = model->roles();
- QCOMPARE(roles.count(), 4);
- QCOMPARE(model->toString(roles.at(0)), QLatin1String("name"));
- QCOMPARE(model->toString(roles.at(1)), QLatin1String("type"));
- QCOMPARE(model->toString(roles.at(2)), QLatin1String("age"));
- QCOMPARE(model->toString(roles.at(3)), QLatin1String("size"));
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::roleErrors()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleErrors.qml")));
- QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("roleErrors.qml")).toString() + ":7:5: QML XmlRole: An XmlRole query must not start with '/'").toUtf8().constData());
- QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("roleErrors.qml")).toString() + ":10:5: QML XmlRole: invalid query: \"age/\"").toUtf8().constData());
-
- //### make sure we receive all expected warning messages.
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
-
- //### should any of these return valid values?
- QCOMPARE(model->data(3, Qt::UserRole), QVariant());
- QCOMPARE(model->data(3, Qt::UserRole+1), QVariant());
- QCOMPARE(model->data(3, Qt::UserRole+2), QVariant());
-
- QEXPECT_FAIL("", "QTBUG-10797", Continue);
- QCOMPARE(model->data(3, Qt::UserRole+3), QVariant());
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::uniqueRoleNames()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("unique.qml")));
- QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("unique.qml")).toString() + ":8:5: QML XmlRole: \"name\" duplicates a previous role name and will be disabled.").toUtf8().constData());
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
- QList<int> roles = model->roles();
- QCOMPARE(roles.count(), 1);
-
- delete model;
-}
-
-
-void tst_qdeclarativexmllistmodel::xml()
-{
- QFETCH(QString, xml);
- QFETCH(int, count);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
-
- QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)));
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QTest::qWait(50);
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
- QCOMPARE(model->count(), 9);
-
- // if xml is empty (i.e. clearing) it won't have any effect if a source is set
- if (xml.isEmpty())
- model->setProperty("source",QUrl());
- model->setProperty("xml",xml);
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0)); // immediately goes to 1.0 if using setXml()
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- if (xml.isEmpty())
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Null);
- else
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->count(), count);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::xml_data()
-{
- QTest::addColumn<QString>("xml");
- QTest::addColumn<int>("count");
-
- QTest::newRow("xml with no items") << "<Pets></Pets>" << 0;
- QTest::newRow("empty xml") << "" << 0;
- QTest::newRow("one item") << "<Pets><Pet><name>Hobbes</name><type>Tiger</type><age>7</age><size>Large</size></Pet></Pets>" << 1;
-}
-
-void tst_qdeclarativexmllistmodel::headers()
-{
- // ensure the QNetworkAccessManagers created for this test are immediately deleted
- QDeclarativeEngine qmlEng;
-
- CustomNetworkAccessManagerFactory factory;
- qmlEng.setNetworkAccessManagerFactory(&factory);
-
- QDeclarativeComponent component(&qmlEng, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Ready);
-
- QVariantMap expectedHeaders;
- expectedHeaders["Accept"] = "application/xml,*/*";
-
- QCOMPARE(factory.lastSentHeaders.count(), expectedHeaders.count());
- foreach (const QString &header, expectedHeaders.keys()) {
- QVERIFY(factory.lastSentHeaders.contains(header));
- QCOMPARE(factory.lastSentHeaders[header].toString(), expectedHeaders[header].toString());
- }
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::source()
-{
- QFETCH(QUrl, source);
- QFETCH(int, count);
- QFETCH(QDeclarativeXmlListModel::Status, status);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)));
-
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
- QCOMPARE(model->count(), 9);
-
- model->setProperty("source",source);
- if (model->property("source").toString().isEmpty())
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Null);
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
- QDeclarativeXmlListModel::Loading);
- QVERIFY(errorString(model).isEmpty());
-
- QEventLoop loop;
- QTimer timer;
- timer.setSingleShot(true);
- connect(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)), &loop, SLOT(quit()));
- connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
- timer.start(20000);
- loop.exec();
-
- if (spy.count() == 0 && status != QDeclarativeXmlListModel::Ready) {
- qWarning("QDeclarativeXmlListModel invalid source test timed out");
- } else {
- QCOMPARE(spy.count(), 1); spy.clear();
- }
-
- QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")), status);
- QCOMPARE(model->count(), count);
-
- if (status == QDeclarativeXmlListModel::Ready)
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
-
- QCOMPARE(errorString(model).isEmpty(), status == QDeclarativeXmlListModel::Ready);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::source_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<int>("count");
- QTest::addColumn<QDeclarativeXmlListModel::Status>("status");
-
- QTest::newRow("valid") << QUrl::fromLocalFile(TESTDATA("model2.xml")) << 2
- << QDeclarativeXmlListModel::Ready;
- QTest::newRow("invalid") << QUrl("http://blah.blah/blah.xml") << 0
- << QDeclarativeXmlListModel::Error;
-
- // empty file
- QTemporaryFile *temp = new QTemporaryFile(this);
- if (temp->open())
- QTest::newRow("empty file") << QUrl::fromLocalFile(temp->fileName()) << 0
- << QDeclarativeXmlListModel::Ready;
- temp->close();
-}
-
-void tst_qdeclarativexmllistmodel::data()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
-
- for (int i=0; i<9; i++) {
- for (int j=0; j<model->roles().count(); j++) {
- QCOMPARE(model->data(i, j), QVariant());
- }
- }
- QTRY_COMPARE(model->count(), 9);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::get()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("get.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
-
- QVERIFY(model != 0);
-
- QVERIFY(QMetaObject::invokeMethod(model, "runPreTest"));
- QCOMPARE(model->property("preTest").toBool(), true);
-
- QTRY_COMPARE(model->count(), 9);
-
- QVERIFY(QMetaObject::invokeMethod(model, "runPostTest"));
- QCOMPARE(model->property("postTest").toBool(), true);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::reload()
-{
- // If no keys are used, the model should be rebuilt from scratch when
- // reload() is called.
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
- QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
- QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
- //reload multiple times to test the xml query aborting
- QMetaObject::invokeMethod(model, "reload");
- QMetaObject::invokeMethod(model, "reload");
- QCoreApplication::processEvents();
- QMetaObject::invokeMethod(model, "reload");
- QMetaObject::invokeMethod(model, "reload");
- QTRY_COMPARE(spyCount.count(), 1);
- QTRY_COMPARE(spyInsert.count(), 1);
- QTRY_COMPARE(spyRemove.count(), 1);
-
- QCOMPARE(spyInsert[0][0].toInt(), 0);
- QCOMPARE(spyInsert[0][1].toInt(), 9);
-
- QCOMPARE(spyRemove[0][0].toInt(), 0);
- QCOMPARE(spyRemove[0][1].toInt(), 9);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::useKeys()
-{
- // If using incremental updates through keys, the model should only
- // insert & remove some of the items, instead of throwing everything
- // away and causing the view to repaint the whole view.
-
- QFETCH(QString, oldXml);
- QFETCH(int, oldCount);
- QFETCH(QString, newXml);
- QFETCH(QDeclarativeXmlModelData, newData);
- QFETCH(QList<QDeclarativeXmlListRange>, insertRanges);
- QFETCH(QList<QDeclarativeXmlListRange>, removeRanges);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
-
- model->setProperty("xml",oldXml);
- QTRY_COMPARE(model->count(), oldCount);
-
- QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
- QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- model->setProperty("xml",newXml);
-
- if (oldCount != newData.count()) {
- QTRY_COMPARE(model->count(), newData.count());
- QCOMPARE(spyCount.count(), 1);
- } else {
- QTRY_VERIFY(spyInsert.count() > 0 || spyRemove.count() > 0);
- QCOMPARE(spyCount.count(), 0);
- }
-
- QList<int> roles = model->roles();
- for (int i=0; i<model->count(); i++) {
- for (int j=0; j<roles.count(); j++)
- QCOMPARE(model->data(i, roles[j]), newData[i][j]);
- }
-
- QCOMPARE(spyInsert.count(), insertRanges.count());
- for (int i=0; i<spyInsert.count(); i++) {
- QCOMPARE(spyInsert[i][0].toInt(), insertRanges[i].first);
- QCOMPARE(spyInsert[i][1].toInt(), insertRanges[i].second);
- }
-
- QCOMPARE(spyRemove.count(), removeRanges.count());
- for (int i=0; i<spyRemove.count(); i++) {
- QCOMPARE(spyRemove[i][0].toInt(), removeRanges[i].first);
- QCOMPARE(spyRemove[i][1].toInt(), removeRanges[i].second);
- }
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::useKeys_data()
-{
- QTest::addColumn<QString>("oldXml");
- QTest::addColumn<int>("oldCount");
- QTest::addColumn<QString>("newXml");
- QTest::addColumn<QDeclarativeXmlModelData>("newData");
- QTest::addColumn<QList<QDeclarativeXmlListRange> >("insertRanges");
- QTest::addColumn<QList<QDeclarativeXmlListRange> >("removeRanges");
-
- QDeclarativeXmlModelData modelData;
-
- QTest::newRow("append 1")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
- << QList<QDeclarativeXmlListRange>();
-
- QTest::newRow("append multiple")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
- << QList<QDeclarativeXmlListRange>();
-
- QTest::newRow("insert in different spots")
- << makeItemXmlAndData("name=B,age=35,sport=Athletics") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2))
- << QList<QDeclarativeXmlListRange>();
-
- QTest::newRow("insert in middle")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=D,age=55,sport=Golf") << 2
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
- << QList<QDeclarativeXmlListRange>();
-
- QTest::newRow("remove first")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
- << makeItemXmlAndData("name=B,age=35,sport=Athletics", &modelData)
- << modelData
- << QList<QDeclarativeXmlListRange>()
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
-
- QTest::newRow("remove last")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
- << makeItemXmlAndData("name=A,age=25,sport=Football", &modelData)
- << modelData
- << QList<QDeclarativeXmlListRange>()
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1));
-
- QTest::newRow("remove from multiple spots")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 5
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << QList<QDeclarativeXmlListRange>()
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1) << qMakePair(3,2));
-
- QTest::newRow("remove all")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
- << makeItemXmlAndData("", &modelData)
- << modelData
- << QList<QDeclarativeXmlListRange>()
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 3));
-
- QTest::newRow("replace item")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=ZZZ,age=25,sport=Football", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1))
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
-
- QTest::newRow("add and remove simultaneously, in different spots")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf") << 4
- << makeItemXmlAndData("name=B,age=35,sport=Athletics;name=E,age=65,sport=Fencing", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2));
-
- QTest::newRow("insert at start, remove at end i.e. rss feed")
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 3
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2))
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2));
-
- QTest::newRow("remove at start, insert at end")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2));
-
- QTest::newRow("all data has changed")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35") << 2
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2))
- << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2));
-}
-
-void tst_qdeclarativexmllistmodel::noKeysValueChanges()
-{
- // The 'key' roles are 'name' and 'age', as defined in roleKeys.qml.
- // If a 'sport' value is changed, the model should not be reloaded,
- // since 'sport' is not marked as a key.
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
-
- QString xml;
-
- xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
- QTRY_COMPARE(model->count(), 2);
-
- model->setProperty("xml","");
-
- QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
- QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- xml = makeItemXmlAndData("name=A,age=25,sport=AussieRules;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
-
- // wait for the new xml data to be set, and verify no signals were emitted
- QTRY_VERIFY(model->data(0, model->roles()[2]).toString() != QLatin1String("Football"));
- QCOMPARE(model->data(0, model->roles()[2]).toString(), QLatin1String("AussieRules"));
-
- QVERIFY(spyInsert.count() == 0);
- QVERIFY(spyRemove.count() == 0);
- QVERIFY(spyCount.count() == 0);
-
- QCOMPARE(model->count(), 2);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::keysChanged()
-{
- // If the key roles change, the next time the data is reloaded, it should
- // delete all its data and build a clean model (i.e. same behaviour as
- // if no keys are set).
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
-
- QString xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
- QTRY_COMPARE(model->count(), 2);
-
- model->setProperty("xml","");
-
- QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
- QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- QVERIFY(QMetaObject::invokeMethod(model, "disableNameKey"));
- model->setProperty("xml",xml);
-
- QTRY_VERIFY(spyInsert.count() > 0 && spyRemove.count() > 0);
-
- QCOMPARE(spyInsert.count(), 1);
- QCOMPARE(spyInsert[0][0].toInt(), 0);
- QCOMPARE(spyInsert[0][1].toInt(), 2);
-
- QCOMPARE(spyRemove.count(), 1);
- QCOMPARE(spyRemove[0][0].toInt(), 0);
- QCOMPARE(spyRemove[0][1].toInt(), 2);
-
- QCOMPARE(spyCount.count(), 0);
-
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::threading()
-{
- QFETCH(int, xmlDataCount);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
-
- QListModelInterface *m1 = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(m1 != 0);
- QListModelInterface *m2 = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(m2 != 0);
- QListModelInterface *m3 = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(m3 != 0);
-
- for (int dataCount=0; dataCount<xmlDataCount; dataCount++) {
-
- QString data1, data2, data3;
- for (int i=0; i<dataCount; i++) {
- data1 += "name=A" + QString::number(i) + ",age=1" + QString::number(i) + ",sport=Football;";
- data2 += "name=B" + QString::number(i) + ",age=2" + QString::number(i) + ",sport=Athletics;";
- data3 += "name=C" + QString::number(i) + ",age=3" + QString::number(i) + ",sport=Curling;";
- }
-
- //Set the xml data multiple times with randomized order and mixed with multiple event loops
- //to test the xml query reloading/aborting, the result should be stable.
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- QCoreApplication::processEvents();
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
-
- QTRY_VERIFY(m1->count() == dataCount && m2->count() == dataCount && m3->count() == dataCount);
-
- for (int i=0; i<dataCount; i++) {
- QCOMPARE(m1->data(i, m1->roles()[0]).toString(), QString("A" + QString::number(i)));
- QCOMPARE(m1->data(i, m1->roles()[1]).toString(), QString("1" + QString::number(i)));
- QCOMPARE(m1->data(i, m1->roles()[2]).toString(), QString("Football"));
-
- QCOMPARE(m2->data(i, m2->roles()[0]).toString(), QString("B" + QString::number(i)));
- QCOMPARE(m2->data(i, m2->roles()[1]).toString(), QString("2" + QString::number(i)));
- QCOMPARE(m2->data(i, m2->roles()[2]).toString(), QString("Athletics"));
-
- QCOMPARE(m3->data(i, m3->roles()[0]).toString(), QString("C" + QString::number(i)));
- QCOMPARE(m3->data(i, m3->roles()[1]).toString(), QString("3" + QString::number(i)));
- QCOMPARE(m3->data(i, m3->roles()[2]).toString(), QString("Curling"));
- }
- }
-
- delete m1;
- delete m2;
- delete m3;
-}
-
-void tst_qdeclarativexmllistmodel::threading_data()
-{
- QTest::addColumn<int>("xmlDataCount");
-
- QTest::newRow("1") << 1;
- QTest::newRow("2") << 2;
- QTest::newRow("10") << 10;
-}
-
-void tst_qdeclarativexmllistmodel::propertyChanges()
-{
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->count(), 9);
-
- QObject *role = model->findChild<QObject*>("role");
- QVERIFY(role);
-
- QSignalSpy nameSpy(role, SIGNAL(nameChanged()));
- QSignalSpy querySpy(role, SIGNAL(queryChanged()));
- QSignalSpy isKeySpy(role, SIGNAL(isKeyChanged()));
-
- role->setProperty("name","size");
- role->setProperty("query","size/string()");
- role->setProperty("isKey",true);
-
- QCOMPARE(role->property("name").toString(), QString("size"));
- QCOMPARE(role->property("query").toString(), QString("size/string()"));
- QVERIFY(role->property("isKey").toBool());
-
- QCOMPARE(nameSpy.count(),1);
- QCOMPARE(querySpy.count(),1);
- QCOMPARE(isKeySpy.count(),1);
-
- role->setProperty("name","size");
- role->setProperty("query","size/string()");
- role->setProperty("isKey",true);
-
- QCOMPARE(nameSpy.count(),1);
- QCOMPARE(querySpy.count(),1);
- QCOMPARE(isKeySpy.count(),1);
-
- QSignalSpy sourceSpy(model, SIGNAL(sourceChanged()));
- QSignalSpy xmlSpy(model, SIGNAL(xmlChanged()));
- QSignalSpy modelQuerySpy(model, SIGNAL(queryChanged()));
- QSignalSpy namespaceDeclarationsSpy(model, SIGNAL(namespaceDeclarationsChanged()));
-
- model->setProperty("source",QUrl(""));
- model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
- model->setProperty("query","/Pets");
- model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
-
- QCOMPARE(model->property("source").toUrl(), QUrl(""));
- QCOMPARE(model->property("xml").toString(), QString("<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>"));
- QCOMPARE(model->property("query").toString(), QString("/Pets"));
- QCOMPARE(model->property("namespaceDeclarations").toString(), QString("declare namespace media=\"http://search.yahoo.com/mrss/\";"));
-
- QTRY_VERIFY(model->count() == 1);
-
- QCOMPARE(sourceSpy.count(),1);
- QCOMPARE(xmlSpy.count(),1);
- QCOMPARE(modelQuerySpy.count(),1);
- QCOMPARE(namespaceDeclarationsSpy.count(),1);
-
- model->setProperty("source",QUrl(""));
- model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
- model->setProperty("query","/Pets");
- model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
-
- QCOMPARE(sourceSpy.count(),1);
- QCOMPARE(xmlSpy.count(),1);
- QCOMPARE(modelQuerySpy.count(),1);
- QCOMPARE(namespaceDeclarationsSpy.count(),1);
-
- QTRY_VERIFY(model->count() == 1);
- delete model;
-}
-
-void tst_qdeclarativexmllistmodel::roleCrash()
-{
- // don't crash
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleCrash.qml")));
- QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
- QVERIFY(model != 0);
- delete model;
-}
-
-QTEST_MAIN(tst_qdeclarativexmllistmodel)
-
-#include "tst_qdeclarativexmllistmodel.moc"
diff --git a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp
index 53b0e3772a..1c4f72191b 100644
--- a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp
@@ -94,7 +94,7 @@ void tst_qmlmin::initTestCase()
excludedDirs << "doc/src/snippets/qtquick1/imports";
// Add invalid files (i.e. files with syntax errors)
- invalidFiles << "tests/auto/declarative/qquickloader/data/InvalidSourceComponent.qml";
+ invalidFiles << "tests/auto/qtquick2/qquickloader/data/InvalidSourceComponent.qml";
invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/dynamicObjectProperties.2.qml";
invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/signal.3.qml";
invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/property.4.qml";
diff --git a/tests/auto/declarative/qquickanchors/qquickanchors.pro b/tests/auto/declarative/qquickanchors/qquickanchors.pro
deleted file mode 100644
index 0d085d367d..0000000000
--- a/tests/auto/declarative/qquickanchors/qquickanchors.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TARGET = tst_qquickanchors
-CONFIG += testcase
-SOURCES += tst_qquickanchors.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private v8-private testlib
diff --git a/tests/auto/declarative/qquickanchors/tst_qquickanchors.cpp b/tests/auto/declarative/qquickanchors/tst_qquickanchors.cpp
deleted file mode 100644
index 00b52ebc50..0000000000
--- a/tests/auto/declarative/qquickanchors/tst_qquickanchors.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QSignalSpy>
-#include <private/qquickitem_p.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/private/qquickrectangle_p.h>
-#include <QtDeclarative/private/qquicktext_p.h>
-#include <QtDeclarative/private/qquickanchors_p_p.h>
-#include <QtDeclarative/private/qquickitem_p.h>
-#include "../shared/util.h"
-
-Q_DECLARE_METATYPE(QQuickAnchors::Anchor)
-Q_DECLARE_METATYPE(QQuickAnchorLine::AnchorLine)
-
-class tst_qquickanchors : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickanchors() {}
-
-private slots:
- void basicAnchors();
- void basicAnchorsRTL();
- void loops();
- void illegalSets();
- void illegalSets_data();
- void reset();
- void reset_data();
- void resetConvenience();
- void nullItem();
- void nullItem_data();
- void crash1();
- void centerIn();
- void centerInRTL();
- void centerInRotation();
- void hvCenter();
- void hvCenterRTL();
- void fill();
- void fillRTL();
- void margins();
- void marginsRTL();
-};
-
-/*
- Find an item with the specified objectName.
-*/
-template<typename T>
-T *findItem(QQuickItem *parent, const QString &objectName)
-{
- if (!parent)
- return 0;
-
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->QQuickItem::children().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
- return static_cast<T*>(item);
- item = findItem<T>(item, objectName);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-void tst_qquickanchors::basicAnchors()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("anchors.qml")));
-
- qApp->processEvents();
-
- //sibling horizontal
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
-
- //parent horizontal
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
-
- //vertical
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
-
- //stretch
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->width(), 96.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->width(), 192.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->width(), 192.0);
-
- //vertical stretch
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->height(), 40.0);
-
- //more parent horizontal
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
-
- //centerIn
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
-
- //margins
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->width(), 86.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->height(), 10.0);
-
- // offsets
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
- QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
-
- //baseline
- QQuickText *text1 = findItem<QQuickText>(view->rootObject(), QLatin1String("text1"));
- QQuickText *text2 = findItem<QQuickText>(view->rootObject(), QLatin1String("text2"));
- QCOMPARE(text1->y(), text2->y());
-
- delete view;
-}
-
-QQuickItem* childItem(QQuickItem *parentItem, const char * itemString) {
- return findItem<QQuickItem>(parentItem, QLatin1String(itemString));
-}
-
-qreal offsetMasterRTL(QQuickItem *rootItem, const char * itemString) {
- QQuickItem* masterItem = findItem<QQuickItem>(rootItem, QLatin1String("masterRect"));
- return masterItem->width()+2*masterItem->x()-findItem<QQuickItem>(rootItem, QLatin1String(itemString))->width();
-}
-
-qreal offsetParentRTL(QQuickItem *rootItem, const char * itemString) {
- return rootItem->width()+2*rootItem->x()-findItem<QQuickItem>(rootItem, QLatin1String(itemString))->width();
-}
-
-void mirrorAnchors(QQuickItem *item) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->setLayoutMirror(true);
-}
-
-void tst_qquickanchors::basicAnchorsRTL()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("anchors.qml")));
-
- qApp->processEvents();
-
- QQuickItem* rootItem = qobject_cast<QQuickItem*>(view->rootObject());
- foreach (QObject *child, rootItem->children()) {
- bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
- QCOMPARE(mirrored, false);
- }
-
- foreach (QObject *child, rootItem->children())
- mirrorAnchors(qobject_cast<QQuickItem*>(child));
-
- foreach (QObject *child, rootItem->children()) {
- bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
- QCOMPARE(mirrored, true);
- }
-
- //sibling horizontal
- QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
- QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
- QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0);
- QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0);
- QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0);
- QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0);
-
- //parent horizontal
- QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0);
- QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0);
- QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0);
- QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0);
- QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0);
- QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0);
-
- //vertical
- QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0);
- QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0);
-
- //stretch
- QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0);
- QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0);
- QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0);
- QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0);
- QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0);
- QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0);
-
- //vertical stretch
- QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0);
- QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0);
-
- //more parent horizontal
- QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0);
- QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0);
- QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0);
-
- //centerIn
- QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0);
- QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0);
-
- //margins
- QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0);
- QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0);
- QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0);
- QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0);
-
- // offsets
- QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0);
- QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0);
- QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0);
-
- //baseline
- QQuickText *text1 = findItem<QQuickText>(rootItem, QLatin1String("text1"));
- QQuickText *text2 = findItem<QQuickText>(rootItem, QLatin1String("text2"));
- QCOMPARE(text1->y(), text2->y());
-
- delete view;
-}
-
-// mostly testing that we don't crash
-void tst_qquickanchors::loops()
-{
- {
- QUrl source(QUrl::fromLocalFile(TESTDATA("loop1.qml")));
-
- QString expect = source.toString() + ":6:5: QML Text: Possible anchor loop detected on horizontal anchor.";
- QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
- QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
-
- QQuickView *view = new QQuickView;
- view->setSource(source);
- qApp->processEvents();
-
- delete view;
- }
-
- {
- QUrl source(QUrl::fromLocalFile(TESTDATA("loop2.qml")));
-
- QString expect = source.toString() + ":8:3: QML Image: Possible anchor loop detected on horizontal anchor.";
- QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
-
- QQuickView *view = new QQuickView;
- view->setSource(source);
- qApp->processEvents();
-
- delete view;
- }
-}
-
-void tst_qquickanchors::illegalSets()
-{
- QFETCH(QString, qml);
- QFETCH(QString, warning);
-
- QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
-
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 1.0\n" + qml.toUtf8()), QUrl::fromLocalFile(""));
- if (!component.isReady())
- qWarning() << "Test errors:" << component.errors();
- QVERIFY(component.isReady());
- QObject *o = component.create();
- delete o;
-}
-
-void tst_qquickanchors::illegalSets_data()
-{
- QTest::addColumn<QString>("qml");
- QTest::addColumn<QString>("warning");
-
- QTest::newRow("H - too many anchors")
- << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
- << "file::2:23: QML Rectangle: Cannot specify left, right, and hcenter anchors.";
-
- foreach (const QString &side, QStringList() << "left" << "right") {
- QTest::newRow("H - anchor to V")
- << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
- << "file::2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
-
- QTest::newRow("H - anchor to non parent/sibling")
- << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
-
- QTest::newRow("H - anchor to self")
- << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
- << "file::2:1: QML Rectangle: Cannot anchor item to self.";
- }
-
-
- QTest::newRow("V - too many anchors")
- << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
- << "file::2:23: QML Rectangle: Cannot specify top, bottom, and vcenter anchors.";
-
- QTest::newRow("V - too many anchors with baseline")
- << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
- << "file::2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.";
-
- foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
-
- QTest::newRow("V - anchor to H")
- << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
- << "file::2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
-
- QTest::newRow("V - anchor to non parent/sibling")
- << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
-
- QTest::newRow("V - anchor to self")
- << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
- << "file::2:1: QML Rectangle: Cannot anchor item to self.";
- }
-
-
- QTest::newRow("centerIn - anchor to non parent/sibling")
- << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
-
-
- QTest::newRow("fill - anchor to non parent/sibling")
- << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
-}
-
-void tst_qquickanchors::reset()
-{
- QFETCH(QString, side);
- QFETCH(QQuickAnchorLine::AnchorLine, anchorLine);
- QFETCH(QQuickAnchors::Anchor, usedAnchor);
-
- QQuickItem *baseItem = new QQuickItem;
-
- QQuickAnchorLine anchor;
- anchor.item = baseItem;
- anchor.anchorLine = anchorLine;
-
- QQuickItem *item = new QQuickItem;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- const QMetaObject *meta = itemPrivate->anchors()->metaObject();
- QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
-
- QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
- QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true);
-
- QVERIFY(p.reset(itemPrivate->anchors()));
- QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false);
-
- delete item;
- delete baseItem;
-}
-
-void tst_qquickanchors::reset_data()
-{
- QTest::addColumn<QString>("side");
- QTest::addColumn<QQuickAnchorLine::AnchorLine>("anchorLine");
- QTest::addColumn<QQuickAnchors::Anchor>("usedAnchor");
-
- QTest::newRow("left") << "left" << QQuickAnchorLine::Left << QQuickAnchors::LeftAnchor;
- QTest::newRow("top") << "top" << QQuickAnchorLine::Top << QQuickAnchors::TopAnchor;
- QTest::newRow("right") << "right" << QQuickAnchorLine::Right << QQuickAnchors::RightAnchor;
- QTest::newRow("bottom") << "bottom" << QQuickAnchorLine::Bottom << QQuickAnchors::BottomAnchor;
-
- QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchorLine::HCenter << QQuickAnchors::HCenterAnchor;
- QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchorLine::VCenter << QQuickAnchors::VCenterAnchor;
- QTest::newRow("baseline") << "baseline" << QQuickAnchorLine::Baseline << QQuickAnchors::BaselineAnchor;
-}
-
-void tst_qquickanchors::resetConvenience()
-{
- QQuickItem *baseItem = new QQuickItem;
- QQuickItem *item = new QQuickItem;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- //fill
- itemPrivate->anchors()->setFill(baseItem);
- QVERIFY(itemPrivate->anchors()->fill() == baseItem);
- itemPrivate->anchors()->resetFill();
- QVERIFY(itemPrivate->anchors()->fill() == 0);
-
- //centerIn
- itemPrivate->anchors()->setCenterIn(baseItem);
- QVERIFY(itemPrivate->anchors()->centerIn() == baseItem);
- itemPrivate->anchors()->resetCenterIn();
- QVERIFY(itemPrivate->anchors()->centerIn() == 0);
-
- delete item;
- delete baseItem;
-}
-
-void tst_qquickanchors::nullItem()
-{
- QFETCH(QString, side);
-
- QQuickAnchorLine anchor;
- QQuickItem *item = new QQuickItem;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- const QMetaObject *meta = itemPrivate->anchors()->metaObject();
- QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
-
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML Item: Cannot anchor to a null item.");
- QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
-
- delete item;
-}
-
-void tst_qquickanchors::nullItem_data()
-{
- QTest::addColumn<QString>("side");
-
- QTest::newRow("left") << "left";
- QTest::newRow("top") << "top";
- QTest::newRow("right") << "right";
- QTest::newRow("bottom") << "bottom";
-
- QTest::newRow("hcenter") << "horizontalCenter";
- QTest::newRow("vcenter") << "verticalCenter";
- QTest::newRow("baseline") << "baseline";
-}
-
-//QTBUG-5428
-void tst_qquickanchors::crash1()
-{
- QUrl source(QUrl::fromLocalFile(TESTDATA("crash1.qml")));
-
- QString expect = source.toString() + ":3:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
-
- QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
-
- QQuickView *view = new QQuickView(source);
- qApp->processEvents();
-
- delete view;
-}
-
-void tst_qquickanchors::fill()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("fill.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QCOMPARE(rect->x(), 0.0 + 10.0);
- QCOMPARE(rect->y(), 0.0 + 30.0);
- QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
- //Alter Offsets (tests QTBUG-6631)
- rectPrivate->anchors()->setLeftMargin(20.0);
- rectPrivate->anchors()->setRightMargin(0.0);
- rectPrivate->anchors()->setBottomMargin(0.0);
- rectPrivate->anchors()->setTopMargin(10.0);
- QCOMPARE(rect->x(), 0.0 + 20.0);
- QCOMPARE(rect->y(), 0.0 + 10.0);
- QCOMPARE(rect->width(), 200.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 10.0);
-
- delete view;
-}
-
-void tst_qquickanchors::fillRTL()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("fill.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- mirrorAnchors(rect);
-
- QCOMPARE(rect->x(), 0.0 + 20.0);
- QCOMPARE(rect->y(), 0.0 + 30.0);
- QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
- //Alter Offsets (tests QTBUG-6631)
- rectPrivate->anchors()->setLeftMargin(20.0);
- rectPrivate->anchors()->setRightMargin(0.0);
- rectPrivate->anchors()->setBottomMargin(0.0);
- rectPrivate->anchors()->setTopMargin(10.0);
- QCOMPARE(rect->x(), 0.0 + 0.0);
- QCOMPARE(rect->y(), 0.0 + 10.0);
- QCOMPARE(rect->width(), 200.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 10.0);
-
- delete view;
-}
-
-void tst_qquickanchors::centerIn()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerin.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- QCOMPARE(rect->x(), 75.0 + 10);
- QCOMPARE(rect->y(), 75.0 + 30);
- //Alter Offsets (tests QTBUG-6631)
- rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
- rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
- QCOMPARE(rect->x(), 75.0 - 20.0);
- QCOMPARE(rect->y(), 75.0 - 10.0);
-
- delete view;
-}
-
-void tst_qquickanchors::centerInRTL()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerin.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- mirrorAnchors(rect);
-
- QCOMPARE(rect->x(), 75.0 - 10);
- QCOMPARE(rect->y(), 75.0 + 30);
- //Alter Offsets (tests QTBUG-6631)
- rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
- rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
- QCOMPARE(rect->x(), 75.0 + 20.0);
- QCOMPARE(rect->y(), 75.0 - 10.0);
-
- delete view;
-}
-
-//QTBUG-12441
-void tst_qquickanchors::centerInRotation()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerinRotation.qml")));
-
- qApp->processEvents();
- QQuickRectangle* outer = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("outer"));
- QQuickRectangle* inner = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("inner"));
-
- QEXPECT_FAIL("", "QTBUG-12441", Abort);
- QCOMPARE(outer->x(), qreal(49.5));
- QCOMPARE(outer->y(), qreal(49.5));
- QCOMPARE(inner->x(), qreal(25.5));
- QCOMPARE(inner->y(), qreal(25.5));
-
- delete view;
-}
-
-void tst_qquickanchors::hvCenter()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("hvCenter.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
-
- // test QTBUG-10999
- QCOMPARE(rect->x(), 10.0);
- QCOMPARE(rect->y(), 19.0);
-
- rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
- rectPrivate->anchors()->setVerticalCenterOffset(5.0);
- QCOMPARE(rect->x(), 10.0 - 5.0);
- QCOMPARE(rect->y(), 19.0 + 5.0);
-
- delete view;
-}
-
-void tst_qquickanchors::hvCenterRTL()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("hvCenter.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- mirrorAnchors(rect);
-
- // test QTBUG-10999
- QCOMPARE(rect->x(), 10.0);
- QCOMPARE(rect->y(), 19.0);
-
- rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
- rectPrivate->anchors()->setVerticalCenterOffset(5.0);
- QCOMPARE(rect->x(), 10.0 + 5.0);
- QCOMPARE(rect->y(), 19.0 + 5.0);
-
- delete view;
-}
-void tst_qquickanchors::margins()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("margins.qml")));
-
- qApp->processEvents();
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QCOMPARE(rect->x(), 5.0);
- QCOMPARE(rect->y(), 6.0);
- QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
- QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
-
- rectPrivate->anchors()->setTopMargin(0.0);
- rectPrivate->anchors()->setMargins(20.0);
-
- QCOMPARE(rect->x(), 5.0);
- QCOMPARE(rect->y(), 20.0);
- QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
-
- delete view;
-}
-
-void tst_qquickanchors::marginsRTL()
-{
- QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("margins.qml")));
-
- QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- mirrorAnchors(rect);
-
- QCOMPARE(rect->x(), 10.0);
- QCOMPARE(rect->y(), 6.0);
- QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
- QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
-
- rectPrivate->anchors()->setTopMargin(0.0);
- rectPrivate->anchors()->setMargins(20.0);
-
- QCOMPARE(rect->x(), 20.0);
- QCOMPARE(rect->y(), 20.0);
- QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
- QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
-
- delete view;
-}
-
-
-QTEST_MAIN(tst_qquickanchors)
-
-#include "tst_qquickanchors.moc"
diff --git a/tests/auto/declarative/qquickanimatedimage/qquickanimatedimage.pro b/tests/auto/declarative/qquickanimatedimage/qquickanimatedimage.pro
deleted file mode 100644
index d6a40e11ce..0000000000
--- a/tests/auto/declarative/qquickanimatedimage/qquickanimatedimage.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickanimatedimage
-HEADERS += ../shared/testhttpserver.h
-SOURCES += tst_qquickanimatedimage.cpp ../shared/testhttpserver.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/declarative/qquickanimatedimage/tst_qquickanimatedimage.cpp
deleted file mode 100644
index 542811efc1..0000000000
--- a/tests/auto/declarative/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ /dev/null
@@ -1,378 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquickimage_p.h>
-#include <private/qquickanimatedimage_p.h>
-#include <QSignalSpy>
-#include <QtDeclarative/qdeclarativecontext.h>
-
-#include "../shared/testhttpserver.h"
-#include "../shared/util.h"
-
-Q_DECLARE_METATYPE(QQuickImageBase::Status)
-
-class tst_qquickanimatedimage : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickanimatedimage() {}
-
-private slots:
- void play();
- void pause();
- void stopped();
- void setFrame();
- void frameCount();
- void mirror_running();
- void mirror_notRunning();
- void mirror_notRunning_data();
- void remote();
- void remote_data();
- void sourceSize();
- void sourceSizeReadOnly();
- void invalidSource();
- void qtbug_16520();
- void progressAndStatusChanges();
-
-};
-
-void tst_qquickanimatedimage::play()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickman.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QVERIFY(anim->isPlaying());
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::pause()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QVERIFY(anim->isPlaying());
- QVERIFY(anim->isPaused());
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::stopped()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QVERIFY(!anim->isPlaying());
- QCOMPARE(anim->currentFrame(), 0);
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::setFrame()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QVERIFY(anim->isPlaying());
- QCOMPARE(anim->currentFrame(), 2);
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::frameCount()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("colors.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QVERIFY(anim->isPlaying());
- QCOMPARE(anim->frameCount(), 3);
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::mirror_running()
-{
- // test where mirror is set to true after animation has started
-
- QQuickView *canvas = new QQuickView;
- canvas->show();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("hearts.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
- QVERIFY(anim);
-
- int width = anim->property("width").toInt();
-
- QCOMPARE(anim->currentFrame(), 0);
- QPixmap frame0 = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- anim->setCurrentFrame(1);
- QPixmap frame1 = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- anim->setCurrentFrame(0);
-
- QSignalSpy spy(anim, SIGNAL(frameChanged()));
- anim->setPlaying(true);
-
- QTRY_VERIFY(spy.count() == 1); spy.clear();
- anim->setProperty("mirror", true);
-
- QCOMPARE(anim->currentFrame(), 1);
- QPixmap frame1_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- QTRY_VERIFY(spy.count() == 1); spy.clear();
- QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
- QPixmap frame0_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
-
- QTransform transform;
- transform.translate(width, 0).scale(-1, 1.0);
- QPixmap frame0_expected = frame0.transformed(transform);
- QPixmap frame1_expected = frame1.transformed(transform);
-
- QCOMPARE(frame0_flipped, frame0_expected);
- QCOMPARE(frame1_flipped, frame1_expected);
-
- delete canvas;
-}
-
-void tst_qquickanimatedimage::mirror_notRunning()
-{
- QFETCH(QUrl, fileUrl);
-
- QQuickView *canvas = new QQuickView;
- canvas->show();
-
- canvas->setSource(fileUrl);
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
- QVERIFY(anim);
-
- int width = anim->property("width").toInt();
- QPixmap screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- QTransform transform;
- transform.translate(width, 0).scale(-1, 1.0);
- QPixmap expected = screenshot.transformed(transform);
-
- int frame = anim->currentFrame();
- bool playing = anim->isPlaying();
- bool paused = anim->isPlaying();
-
- anim->setProperty("mirror", true);
- screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
-
- QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
- QCOMPARE(screenshot, expected);
-
- // mirroring should not change the current frame or playing status
- QCOMPARE(anim->currentFrame(), frame);
- QCOMPARE(anim->isPlaying(), playing);
- QCOMPARE(anim->isPaused(), paused);
-
- delete canvas;
-}
-
-void tst_qquickanimatedimage::mirror_notRunning_data()
-{
- QTest::addColumn<QUrl>("fileUrl");
-
- QTest::newRow("paused") << QUrl::fromLocalFile(TESTDATA("stickmanpause.qml"));
- QTest::newRow("stopped") << QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml"));
-}
-
-void tst_qquickanimatedimage::remote()
-{
- QFETCH(QString, fileName);
- QFETCH(bool, paused);
-
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
- QTRY_VERIFY(component.isReady());
-
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
-
- QTRY_VERIFY(anim->isPlaying());
- if (paused) {
- QTRY_VERIFY(anim->isPaused());
- QCOMPARE(anim->currentFrame(), 2);
- }
- QVERIFY(anim->status() != QQuickAnimatedImage::Error);
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::sourceSize()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanscaled.qml")));
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
- QCOMPARE(anim->width(),240.0);
- QCOMPARE(anim->height(),180.0);
- QCOMPARE(anim->sourceSize(),QSize(160,120));
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::sourceSizeReadOnly()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanerror1.qml")));
- QVERIFY(component.isError());
- QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
-}
-
-void tst_qquickanimatedimage::remote_data()
-{
- QTest::addColumn<QString>("fileName");
- QTest::addColumn<bool>("paused");
-
- QTest::newRow("playing") << "stickman.qml" << false;
- QTest::newRow("paused") << "stickmanpause.qml" << true;
-}
-
-void tst_qquickanimatedimage::invalidSource()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
- QVERIFY(component.isReady());
-
- QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
-
- QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
- QVERIFY(anim);
-
- QVERIFY(!anim->isPlaying());
- QVERIFY(!anim->isPaused());
- QCOMPARE(anim->currentFrame(), 0);
- QCOMPARE(anim->frameCount(), 0);
- QTRY_VERIFY(anim->status() == 3);
-}
-
-void tst_qquickanimatedimage::qtbug_16520()
-{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("qtbug-16520.qml")));
- QTRY_VERIFY(component.isReady());
-
- QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
- QVERIFY(root);
- QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
-
- anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
-
- QTRY_VERIFY(anim->opacity() == 0);
- QTRY_VERIFY(anim->opacity() == 1);
-
- delete anim;
-}
-
-void tst_qquickanimatedimage::progressAndStatusChanges()
-{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- QDeclarativeEngine engine;
- QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("stickman.gif")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
-
- qRegisterMetaType<QQuickImageBase::Status>();
- QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
- QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
- QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
-
- // Loading local file
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.gif")));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
- QTRY_COMPARE(sourceSpy.count(), 1);
- QTRY_COMPARE(progressSpy.count(), 0);
- QTRY_COMPARE(statusSpy.count(), 0);
-
- // Loading remote file
- ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
- QTRY_COMPARE(sourceSpy.count(), 2);
- QTRY_VERIFY(progressSpy.count() > 1);
- QTRY_COMPARE(statusSpy.count(), 2);
-
- ctxt->setContextProperty("srcImage", "");
- QTRY_VERIFY(obj->status() == QQuickImage::Null);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_COMPARE(sourceSpy.count(), 3);
- QTRY_VERIFY(progressSpy.count() > 2);
- QTRY_COMPARE(statusSpy.count(), 3);
-}
-
-QTEST_MAIN(tst_qquickanimatedimage)
-
-#include "tst_qquickanimatedimage.moc"
diff --git a/tests/auto/declarative/qquickborderimage/qquickborderimage.pro b/tests/auto/declarative/qquickborderimage/qquickborderimage.pro
deleted file mode 100644
index b1ccf4a939..0000000000
--- a/tests/auto/declarative/qquickborderimage/qquickborderimage.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickborderimage
-macx:CONFIG -= app_bundle
-
-HEADERS += ../shared/testhttpserver.h
-SOURCES += tst_qquickborderimage.cpp ../shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network widgets testlib
diff --git a/tests/auto/declarative/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/declarative/qquickborderimage/tst_qquickborderimage.cpp
deleted file mode 100644
index 4fb6ed7057..0000000000
--- a/tests/auto/declarative/qquickborderimage/tst_qquickborderimage.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QTextDocument>
-#include <QTcpServer>
-#include <QTcpSocket>
-#include <QDir>
-#include <QGraphicsScene>
-#include <QPainter>
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qquickborderimage_p.h>
-#include <private/qquickimagebase_p.h>
-#include <private/qquickscalegrid_p_p.h>
-#include <private/qquickloader_p.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-
-#include "../shared/testhttpserver.h"
-#include "../shared/util.h"
-
-#define SERVER_PORT 14446
-#define SERVER_ADDR "http://127.0.0.1:14446"
-
-class tst_qquickborderimage : public QObject
-
-{
- Q_OBJECT
-public:
- tst_qquickborderimage();
-
-private slots:
- void noSource();
- void imageSource();
- void imageSource_data();
- void clearSource();
- void resized();
- void smooth();
- void mirror();
- void tileModes();
- void sciSource();
- void sciSource_data();
- void invalidSciFile();
- void pendingRemoteRequest();
- void pendingRemoteRequest_data();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qquickborderimage::tst_qquickborderimage()
-{
-}
-
-void tst_qquickborderimage::noSource()
-{
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->source(), QUrl());
- QCOMPARE(obj->width(), 0.);
- QCOMPARE(obj->height(), 0.);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
-
- delete obj;
-}
-
-void tst_qquickborderimage::imageSource_data()
-{
- QTest::addColumn<QString>("source");
- QTest::addColumn<bool>("remote");
- QTest::addColumn<QString>("error");
-
- QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << false << "";
- QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << false
- << "file::2:1: QML BorderImage: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString();
- QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << "";
- QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true
- << "file::2:1: QML BorderImage: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
-}
-
-void tst_qquickborderimage::imageSource()
-{
- QFETCH(QString, source);
- QFETCH(bool, remote);
- QFETCH(QString, error);
-
- TestHTTPServer *server = 0;
- if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(TESTDATA(""));
- }
-
- if (!error.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
-
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
-
- if (remote)
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
-
- QCOMPARE(obj->source(), remote ? source : QUrl(source));
-
- if (error.isEmpty()) {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
- QCOMPARE(obj->width(), 120.);
- QCOMPARE(obj->height(), 120.);
- QCOMPARE(obj->sourceSize().width(), 120);
- QCOMPARE(obj->sourceSize().height(), 120);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
- } else {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
- }
-
- delete obj;
- delete server;
-}
-
-void tst_qquickborderimage::clearSource()
-{
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: srcImage }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickBorderImage::Ready);
- QCOMPARE(obj->width(), 120.);
- QCOMPARE(obj->height(), 120.);
-
- ctxt->setContextProperty("srcImage", "");
- QVERIFY(obj->source().isEmpty());
- QVERIFY(obj->status() == QQuickBorderImage::Null);
- QCOMPARE(obj->width(), 0.);
- QCOMPARE(obj->height(), 0.);
-}
-
-void tst_qquickborderimage::resized()
-{
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + QUrl::fromLocalFile(TESTDATA("colors.png")).toString() + "\"; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->sourceSize().width(), 120);
- QCOMPARE(obj->sourceSize().height(), 120);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
-
- delete obj;
-}
-
-void tst_qquickborderimage::smooth()
-{
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->smooth(), true);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
-
- delete obj;
-}
-
-void tst_qquickborderimage::mirror()
-{
- QQuickView *canvas = new QQuickView;
- canvas->show();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml")));
- QQuickBorderImage *image = qobject_cast<QQuickBorderImage*>(canvas->rootObject());
- QVERIFY(image != 0);
- canvas->show();
-
- QImage screenshot = canvas->grabFrameBuffer();
-
- QImage srcPixmap(screenshot);
- QTransform transform;
- transform.translate(image->width(), 0).scale(-1, 1.0);
- srcPixmap = srcPixmap.transformed(transform);
-
- image->setProperty("mirror", true);
- screenshot = canvas->grabFrameBuffer();
- QCOMPARE(screenshot, srcPixmap);
-
- delete canvas;
-}
-
-void tst_qquickborderimage::tileModes()
-{
- {
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; width: 100; height: 300; horizontalTileMode: BorderImage.Repeat; verticalTileMode: BorderImage.Repeat }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 100.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Repeat);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Repeat);
-
- delete obj;
- }
- {
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 150; horizontalTileMode: BorderImage.Round; verticalTileMode: BorderImage.Round }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 150.);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Round);
-
- delete obj;
- }
-}
-
-void tst_qquickborderimage::sciSource()
-{
- QFETCH(QString, source);
- QFETCH(bool, valid);
-
- bool remote = source.startsWith("http");
- TestHTTPServer *server = 0;
- if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(TESTDATA(""));
- }
-
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\"; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
-
- if (remote)
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
-
- QCOMPARE(obj->source(), remote ? source : QUrl(source));
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
-
- if (valid) {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
- QCOMPARE(obj->border()->left(), 10);
- QCOMPARE(obj->border()->top(), 20);
- QCOMPARE(obj->border()->right(), 30);
- QCOMPARE(obj->border()->bottom(), 40);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Repeat);
- } else {
- QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
- }
-
- delete obj;
- delete server;
-}
-
-void tst_qquickborderimage::sciSource_data()
-{
- QTest::addColumn<QString>("source");
- QTest::addColumn<bool>("valid");
-
- QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors-round.sci")).toString() << true;
- QTest::newRow("local quoted filename") << QUrl::fromLocalFile(TESTDATA("colors-round-quotes.sci")).toString() << true;
- QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.sci")).toString() << false;
- QTest::newRow("remote") << SERVER_ADDR "/colors-round.sci" << true;
- QTest::newRow("remote filename quoted") << SERVER_ADDR "/colors-round-quotes.sci" << true;
- QTest::newRow("remote image") << SERVER_ADDR "/colors-round-remote.sci" << true;
- QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.sci" << false;
-}
-
-void tst_qquickborderimage::invalidSciFile()
-{
- QTest::ignoreMessage(QtWarningMsg, "QQuickGridScaledImage: Invalid tile rule specified. Using Stretch."); // for "Roun"
- QTest::ignoreMessage(QtWarningMsg, "QQuickGridScaledImage: Invalid tile rule specified. Using Stretch."); // for "Repea"
-
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + QUrl::fromLocalFile(TESTDATA("invalid.sci")).toString() +"\"; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->status(), QQuickImageBase::Error);
- QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
- QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
-
- delete obj;
-}
-
-void tst_qquickborderimage::pendingRemoteRequest()
-{
- QFETCH(QString, source);
-
- QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->status(), QQuickBorderImage::Loading);
-
- // verify no crash
- // This will cause a delayed "QThread: Destroyed while thread is still running" warning
- delete obj;
- QTest::qWait(50);
-}
-
-void tst_qquickborderimage::pendingRemoteRequest_data()
-{
- QTest::addColumn<QString>("source");
-
- QTest::newRow("png file") << "http://localhost/none.png";
- QTest::newRow("sci file") << "http://localhost/none.sci";
-}
-
-QTEST_MAIN(tst_qquickborderimage)
-
-#include "tst_qquickborderimage.moc"
diff --git a/tests/auto/declarative/qquickcanvas/qquickcanvas.pro b/tests/auto/declarative/qquickcanvas/qquickcanvas.pro
deleted file mode 100644
index b45a3597d4..0000000000
--- a/tests/auto/declarative/qquickcanvas/qquickcanvas.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickcanvas
-SOURCES += tst_qquickcanvas.cpp
-
-macx:CONFIG -= app_bundle
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickcanvas/tst_qquickcanvas.cpp b/tests/auto/declarative/qquickcanvas/tst_qquickcanvas.cpp
deleted file mode 100644
index 829d666b7e..0000000000
--- a/tests/auto/declarative/qquickcanvas/tst_qquickcanvas.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QDebug>
-#include <QTouchEvent>
-#include <QtDeclarative/QQuickItem>
-#include <QtDeclarative/QQuickCanvas>
-#include <QtDeclarative/QDeclarativeEngine>
-#include <QtDeclarative/QDeclarativeComponent>
-#include <QtDeclarative/private/qquickrectangle_p.h>
-#include <QtGui/QWindowSystemInterface>
-#include "../shared/util.h"
-
-struct TouchEventData {
- QEvent::Type type;
- QWidget *widget;
- QWindow *window;
- Qt::TouchPointStates states;
- QList<QTouchEvent::TouchPoint> touchPoints;
-};
-
-static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p, const QPointF &lastPoint = QPointF())
-{
- QPointF last = lastPoint.isNull() ? p : lastPoint;
-
- QTouchEvent::TouchPoint tp;
-
- tp.setPos(p);
- tp.setLastPos(last);
- tp.setScenePos(item->mapToScene(p));
- tp.setLastScenePos(item->mapToScene(last));
- tp.setScreenPos(item->canvas()->mapToGlobal(tp.scenePos().toPoint()));
- tp.setLastScreenPos(item->canvas()->mapToGlobal(tp.lastScenePos().toPoint()));
- return tp;
-}
-
-static TouchEventData makeTouchData(QEvent::Type type, QWidget *w, Qt::TouchPointStates states, const QList<QTouchEvent::TouchPoint> &touchPoints)
-{
- TouchEventData d = { type, w, 0, states, touchPoints };
- return d;
-}
-
-static TouchEventData makeTouchData(QEvent::Type type, QWidget *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
-{
- QList<QTouchEvent::TouchPoint> points;
- points << touchPoint;
- return makeTouchData(type, w, states, points);
-}
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QList<QTouchEvent::TouchPoint>& touchPoints)
-{
- TouchEventData d = { type, 0, w, states, touchPoints };
- return d;
-}
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
-{
- QList<QTouchEvent::TouchPoint> points;
- points << touchPoint;
- return makeTouchData(type, w, states, points);
-}
-
-#define COMPARE_TOUCH_POINTS(tp1, tp2) \
-{ \
- QCOMPARE(tp1.pos(), tp2.pos()); \
- QCOMPARE(tp1.lastPos(), tp2.lastPos()); \
- QCOMPARE(tp1.scenePos(), tp2.scenePos()); \
- QCOMPARE(tp1.lastScenePos(), tp2.lastScenePos()); \
- QCOMPARE(tp1.screenPos(), tp2.screenPos()); \
- QCOMPARE(tp1.lastScreenPos(), tp2.lastScreenPos()); \
-}
-
-#define COMPARE_TOUCH_DATA(d1, d2) \
-{ \
- QCOMPARE((int)d1.type, (int)d2.type); \
- QCOMPARE(d1.widget, d2.widget); \
- QCOMPARE((int)d1.states, (int)d2.states); \
- QCOMPARE(d1.touchPoints.count(), d2.touchPoints.count()); \
- for (int i=0; i<d1.touchPoints.count(); i++) { \
- COMPARE_TOUCH_POINTS(d1.touchPoints[i], d2.touchPoints[i]); \
- } \
-}
-
-class TestTouchItem : public QQuickRectangle
-{
- Q_OBJECT
-public:
- TestTouchItem(QQuickItem *parent = 0)
- : QQuickRectangle(parent), acceptEvents(true), mousePressId(0)
- {
- border()->setWidth(1);
- setAcceptedMouseButtons(Qt::LeftButton);
- setFiltersChildMouseEvents(true);
- }
-
- void reset() {
- acceptEvents = true;
- setEnabled(true);
- setOpacity(1.0);
-
- lastEvent = makeTouchData(QEvent::None, canvas(), 0, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
- }
-
- bool acceptEvents;
- TouchEventData lastEvent;
- int mousePressId;
-
-protected:
- virtual void touchEvent(QTouchEvent *event) {
- if (!acceptEvents) {
- event->ignore();
- return;
- }
- lastEvent = makeTouchData(event->type(), event->widget(), event->touchPointStates(), event->touchPoints());
- event->accept();
- }
-
- virtual void mousePressEvent(QMouseEvent *) {
- mousePressId = ++mousePressNum;
- }
-
- bool childMouseEventFilter(QQuickItem *, QEvent *event) {
- if (event->type() == QEvent::MouseButtonPress)
- mousePressId = ++mousePressNum;
- return false;
- }
-
- static int mousePressNum;
-};
-
-int TestTouchItem::mousePressNum = 0;
-
-class ConstantUpdateItem : public QQuickItem
-{
-Q_OBJECT
-public:
- ConstantUpdateItem(QQuickItem *parent = 0) : QQuickItem(parent), iterations(0) {setFlag(ItemHasContents);}
-
- int iterations;
-protected:
- QSGNode* updatePaintNode(QSGNode *, UpdatePaintNodeData *){
- iterations++;
- update();
- return 0;
- }
-};
-
-class tst_qquickcanvas : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickcanvas();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void constantUpdates();
-
- void touchEvent_basic();
- void touchEvent_propagation();
- void touchEvent_propagation_data();
-
- void clearCanvas();
- void mouseFiltering();
-
- void qmlCreation();
- void clearColor();
-};
-
-tst_qquickcanvas::tst_qquickcanvas()
-{
-}
-
-void tst_qquickcanvas::initTestCase()
-{
-}
-
-void tst_qquickcanvas::cleanupTestCase()
-{
-}
-
-//If the item calls update inside updatePaintNode, it should schedule another update
-void tst_qquickcanvas::constantUpdates()
-{
- QQuickCanvas canvas;
- ConstantUpdateItem item(canvas.rootItem());
- canvas.show();
- QTRY_VERIFY(item.iterations > 60);
-}
-
-void tst_qquickcanvas::touchEvent_basic()
-{
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(250, 250);
- canvas->move(100, 100);
- canvas->show();
-
- TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
- bottomItem->setObjectName("Bottom Item");
- bottomItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *middleItem = new TestTouchItem(bottomItem);
- middleItem->setObjectName("Middle Item");
- middleItem->setPos(QPointF(50, 50));
- middleItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *topItem = new TestTouchItem(middleItem);
- topItem->setObjectName("Top Item");
- topItem->setPos(QPointF(50, 50));
- topItem->setSize(QSizeF(150, 150));
-
- QPointF pos(10, 10);
-
- // press single point
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas);
- QTest::qWait(50);
-
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
-
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
- TouchEventData d = makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem,pos));
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
- topItem->reset();
-
- // press multiple points
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas)
- .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
- topItem->reset();
- bottomItem->reset();
-
- // touch point on top item moves to bottom item, but top item should still receive the event
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).move(0, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, canvas, Qt::TouchPointMoved,
- makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
- topItem->reset();
-
- // touch point on bottom item moves to top item, but bottom item should still receive the event
- QTest::touchEvent(canvas).press(0, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).move(0, topItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, canvas, Qt::TouchPointMoved,
- makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
- bottomItem->reset();
-
- // a single stationary press on an item shouldn't cause an event
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).stationary(0)
- .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
- topItem->reset();
- bottomItem->reset();
-
- // move touch point from top item to bottom, and release
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).release(0, bottomItem->mapToScene(pos).toPoint(),canvas);
- QTest::qWait(50);
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, canvas, Qt::TouchPointReleased,
- makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
- topItem->reset();
-
- // release while another point is pressed
- QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas)
- .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).move(0, bottomItem->mapToScene(pos).toPoint(), canvas);
- QTest::qWait(50);
- QTest::touchEvent(canvas).release(0, bottomItem->mapToScene(pos).toPoint(), canvas)
- .stationary(1);
- QTest::qWait(50);
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, canvas, Qt::TouchPointReleased,
- makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos))));
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
- topItem->reset();
- bottomItem->reset();
-
- delete topItem;
- delete middleItem;
- delete bottomItem;
- delete canvas;
-}
-
-void tst_qquickcanvas::touchEvent_propagation()
-{
- QFETCH(bool, acceptEvents);
- QFETCH(bool, enableItem);
- QFETCH(qreal, itemOpacity);
-
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(250, 250);
- canvas->move(100, 100);
- canvas->show();
-
- TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
- bottomItem->setObjectName("Bottom Item");
- bottomItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *middleItem = new TestTouchItem(bottomItem);
- middleItem->setObjectName("Middle Item");
- middleItem->setPos(QPointF(50, 50));
- middleItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *topItem = new TestTouchItem(middleItem);
- topItem->setObjectName("Top Item");
- topItem->setPos(QPointF(50, 50));
- topItem->setSize(QSizeF(150, 150));
-
- QPointF pos(10, 10);
- QPoint pointInBottomItem = bottomItem->mapToScene(pos).toPoint(); // (10, 10)
- QPoint pointInMiddleItem = middleItem->mapToScene(pos).toPoint(); // (60, 60) overlaps with bottomItem
- QPoint pointInTopItem = topItem->mapToScene(pos).toPoint(); // (110, 110) overlaps with bottom & top items
-
- // disable topItem
- topItem->acceptEvents = acceptEvents;
- topItem->setEnabled(enableItem);
- topItem->setOpacity(itemOpacity);
-
- // single touch to top item, should be received by middle item
- QTest::touchEvent(canvas).press(0, pointInTopItem, canvas);
- QTest::qWait(50);
- QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(middleItem->lastEvent.touchPoints.count(), 1);
- QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
- COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
- makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))));
-
- // touch top and middle items, middle item should get both events
- QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
- .press(1, pointInMiddleItem, canvas);
- QTest::qWait(50);
- QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(middleItem->lastEvent.touchPoints.count(), 2);
- QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
- COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
- (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))
- << makeTouchPoint(middleItem, pos) )));
- middleItem->reset();
-
- // disable middleItem as well
- middleItem->acceptEvents = acceptEvents;
- middleItem->setEnabled(enableItem);
- middleItem->setOpacity(itemOpacity);
-
- // touch top and middle items, bottom item should get all events
- QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
- .press(1, pointInMiddleItem, canvas);
- QTest::qWait(50);
- QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 2);
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
- (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))
- << makeTouchPoint(bottomItem, bottomItem->mapFromItem(middleItem, pos)) )));
- bottomItem->reset();
-
- // disable bottom item as well
- bottomItem->acceptEvents = acceptEvents;
- bottomItem->setEnabled(enableItem);
- bottomItem->setOpacity(itemOpacity);
-
- // no events should be received
- QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
- .press(1, pointInMiddleItem, canvas)
- .press(2, pointInBottomItem, canvas);
- QTest::qWait(50);
- QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
-
- topItem->reset();
- middleItem->reset();
- bottomItem->reset();
-
- // disable middle item, touch on top item
- middleItem->acceptEvents = acceptEvents;
- middleItem->setEnabled(enableItem);
- middleItem->setOpacity(itemOpacity);
- QTest::touchEvent(canvas).press(0, pointInTopItem, canvas);
- QTest::qWait(50);
- if (!enableItem || itemOpacity == 0) {
- // middle item is disabled or has 0 opacity, bottom item receives the event
- QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
- COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
- makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))));
- } else {
- // middle item ignores event, sends it to the top item (top-most child)
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
- QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
- COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
- makeTouchPoint(topItem, pos)));
- }
-
- delete topItem;
- delete middleItem;
- delete bottomItem;
- delete canvas;
-}
-
-void tst_qquickcanvas::touchEvent_propagation_data()
-{
- QTest::addColumn<bool>("acceptEvents");
- QTest::addColumn<bool>("enableItem");
- QTest::addColumn<qreal>("itemOpacity");
-
- QTest::newRow("disable events") << false << true << 1.0;
- QTest::newRow("disable item") << true << false << 1.0;
- QTest::newRow("opacity of 0") << true << true << 0.0;
-}
-
-void tst_qquickcanvas::clearCanvas()
-{
- QQuickCanvas *canvas = new QQuickCanvas;
- QQuickItem *item = new QQuickItem;
- item->setParentItem(canvas->rootItem());
-
- QVERIFY(item->canvas() == canvas);
-
- delete canvas;
-
- QVERIFY(item->canvas() == 0);
-
- delete item;
-}
-
-void tst_qquickcanvas::mouseFiltering()
-{
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(250, 250);
- canvas->move(100, 100);
- canvas->show();
-
- TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
- bottomItem->setObjectName("Bottom Item");
- bottomItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *middleItem = new TestTouchItem(bottomItem);
- middleItem->setObjectName("Middle Item");
- middleItem->setPos(QPointF(50, 50));
- middleItem->setSize(QSizeF(150, 150));
-
- TestTouchItem *topItem = new TestTouchItem(middleItem);
- topItem->setObjectName("Top Item");
- topItem->setPos(QPointF(50, 50));
- topItem->setSize(QSizeF(150, 150));
-
- QPoint pos(100, 100);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, pos);
- QTest::qWait(50);
-
- // Mouse filtering propagates down the stack, so the
- // correct order is
- // 1. middleItem filters event
- // 2. bottomItem filters event
- // 3. topItem receives event
- QCOMPARE(middleItem->mousePressId, 1);
- QCOMPARE(bottomItem->mousePressId, 2);
- QCOMPARE(topItem->mousePressId, 3);
-}
-
-void tst_qquickcanvas::qmlCreation()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
- component.loadUrl(TESTDATA("window.qml"));
- QObject* created = component.create();
- QVERIFY(created);
-
- QQuickCanvas* canvas = qobject_cast<QQuickCanvas*>(created);
- QVERIFY(canvas);
- QCOMPARE(canvas->clearColor(), QColor(Qt::green));
-
- QQuickItem* item = canvas->findChild<QQuickItem*>("item");
- QVERIFY(item);
- QCOMPARE(item->canvas(), canvas);
-}
-
-void tst_qquickcanvas::clearColor()
-{
- //### Can we examine rendering to make sure it is really blue?
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(250, 250);
- canvas->move(100, 100);
- canvas->setClearColor(Qt::blue);
- canvas->show();
- QTest::qWaitForWindowShown(canvas);
- QCOMPARE(canvas->clearColor(), QColor(Qt::blue));
- delete canvas;
-}
-
-QTEST_MAIN(tst_qquickcanvas)
-
-#include "tst_qquickcanvas.moc"
diff --git a/tests/auto/declarative/qquickdrag/qquickdrag.pro b/tests/auto/declarative/qquickdrag/qquickdrag.pro
deleted file mode 100644
index 416ecdbe8e..0000000000
--- a/tests/auto/declarative/qquickdrag/qquickdrag.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-TARGET = tst_qquickdrag
-CONFIG += testcase
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickdrag.cpp
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickdrag/tst_qquickdrag.cpp b/tests/auto/declarative/qquickdrag/tst_qquickdrag.cpp
deleted file mode 100644
index 6bc0866a6e..0000000000
--- a/tests/auto/declarative/qquickdrag/tst_qquickdrag.cpp
+++ /dev/null
@@ -1,827 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qquickitem.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-
-template <typename T> static T evaluate(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- QVariant result = expr.evaluate();
- if (expr.hasError())
- qWarning() << expr.error().toString();
- return result.value<T>();
-}
-
-template <> void evaluate<void>(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- expr.evaluate();
- if (expr.hasError())
- qWarning() << expr.error().toString();
-}
-
-Q_DECLARE_METATYPE(Qt::DropActions)
-
-class TestDropTarget : public QQuickItem
-{
- Q_OBJECT
-public:
- TestDropTarget(QQuickItem *parent = 0)
- : QQuickItem(parent)
- , enterEvents(0)
- , moveEvents(0)
- , leaveEvents(0)
- , dropEvents(0)
- , acceptAction(Qt::MoveAction)
- , defaultAction(Qt::IgnoreAction)
- , proposedAction(Qt::IgnoreAction)
- , accept(true)
- {
- setFlags(ItemAcceptsDrops);
- }
-
- void reset()
- {
- enterEvents = 0;
- moveEvents = 0;
- leaveEvents = 0;
- dropEvents = 0;
- defaultAction = Qt::IgnoreAction;
- proposedAction = Qt::IgnoreAction;
- supportedActions = Qt::IgnoreAction;
- }
-
- void dragEnterEvent(QDragEnterEvent *event)
- {
- ++enterEvents;
- position = event->pos();
- defaultAction = event->dropAction();
- proposedAction = event->proposedAction();
- supportedActions = event->possibleActions();
- event->setAccepted(accept);
- }
-
- void dragMoveEvent(QDragMoveEvent *event)
- {
- ++moveEvents;
- position = event->pos();
- defaultAction = event->dropAction();
- proposedAction = event->proposedAction();
- supportedActions = event->possibleActions();
- event->setAccepted(accept);
- }
-
- void dragLeaveEvent(QDragLeaveEvent *event)
- {
- ++leaveEvents;
- event->setAccepted(accept);
- }
-
- void dropEvent(QDropEvent *event)
- {
- ++dropEvents;
- position = event->pos();
- defaultAction = event->dropAction();
- proposedAction = event->proposedAction();
- supportedActions = event->possibleActions();
- event->setDropAction(acceptAction);
- event->setAccepted(accept);
- }
-
- int enterEvents;
- int moveEvents;
- int leaveEvents;
- int dropEvents;
- Qt::DropAction acceptAction;
- Qt::DropAction defaultAction;
- Qt::DropAction proposedAction;
- Qt::DropActions supportedActions;
- QPointF position;
- bool accept;
-};
-
-class tst_QQuickDrag: public QObject
-{
- Q_OBJECT
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void active();
- void drop();
- void move();
- void hotSpot();
- void supportedActions();
- void proposedAction();
- void keys();
- void source();
-
-private:
- QDeclarativeEngine engine;
-};
-
-void tst_QQuickDrag::initTestCase()
-{
-
-}
-
-void tst_QQuickDrag::cleanupTestCase()
-{
-
-}
-
-void tst_QQuickDrag::active()
-{
- QQuickCanvas canvas;
- TestDropTarget dropTarget(canvas.rootItem());
- dropTarget.setSize(QSizeF(100, 100));
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property bool dragActive: Drag.active\n"
- "property Item dragTarget: Drag.target\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&dropTarget);
-
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
-
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = false");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.cancel()");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
-
- // Start while a drag is active, cancels the previous drag and starts a new one.
- dropTarget.reset();
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 1);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.cancel()");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
-
- // Enter events aren't sent to items without the QQuickItem::ItemAcceptsDrops flag.
- dropTarget.setFlags(QQuickItem::Flags());
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = false");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.setFlags(QQuickItem::Flags());
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = false");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
-
- // Follow up events aren't sent to items if the enter event isn't accepted.
- dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
- dropTarget.accept = false;
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = false");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.accept = true;
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
- QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
-
- dropTarget.accept = false;
-
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = false");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
-
- // Events are sent to hidden or disabled items.
- dropTarget.accept = true;
- dropTarget.setVisible(false);
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- evaluate<void>(item, "Drag.active = false");
- dropTarget.setVisible(true);
-
- dropTarget.setOpacity(0.0);
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-
- evaluate<void>(item, "Drag.active = false");
- dropTarget.setOpacity(1.0);
-
- dropTarget.setEnabled(false);
- dropTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
-}
-
-void tst_QQuickDrag::drop()
-{
- QQuickCanvas canvas;
- TestDropTarget outerTarget(canvas.rootItem());
- outerTarget.setSize(QSizeF(100, 100));
- outerTarget.acceptAction = Qt::CopyAction;
- TestDropTarget innerTarget(&outerTarget);
- innerTarget.setSize(QSizeF(100, 100));
- innerTarget.acceptAction = Qt::MoveAction;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property bool dragActive: Drag.active\n"
- "property Item dragTarget: Drag.target\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&outerTarget);
-
- innerTarget.reset(); outerTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
-
- innerTarget.reset(); outerTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- // Inner target declines the drop so it is propagated to the outer target.
- innerTarget.accept = false;
-
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
-
-
- // Inner target doesn't accept enter so drop goes directly to outer.
- innerTarget.accept = true;
- innerTarget.setFlags(QQuickItem::Flags());
-
- innerTarget.reset(); outerTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- // Neither target accepts drop so Qt::IgnoreAction is returned.
- innerTarget.reset(); outerTarget.reset();
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- outerTarget.accept = false;
-
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-
- // drop doesn't send an event and returns Qt.IgnoreAction if not active.
- innerTarget.accept = true;
- outerTarget.accept = true;
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
-}
-
-void tst_QQuickDrag::move()
-{
- QQuickCanvas canvas;
- TestDropTarget outerTarget(canvas.rootItem());
- outerTarget.setSize(QSizeF(100, 100));
- TestDropTarget leftTarget(&outerTarget);
- leftTarget.setPos(QPointF(0, 35));
- leftTarget.setSize(QSizeF(30, 30));
- TestDropTarget rightTarget(&outerTarget);
- rightTarget.setPos(QPointF(70, 35));
- rightTarget.setSize(QSizeF(30, 30));
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property bool dragActive: Drag.active\n"
- "property Item dragTarget: Drag.target\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&outerTarget);
-
- evaluate<void>(item, "Drag.active = true");
- QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
- QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(50)); QCOMPARE(outerTarget.position.y(), qreal(50));
-
- // Move within the outer target.
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(60, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
-
- // Move into the right target.
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(75, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(75)); QCOMPARE(outerTarget.position.y(), qreal(50));
- QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
-
- // Move into the left target.
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(25, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 1); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 1); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
- QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(15));
-
- // Move within the left target.
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(25, 40));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 1);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(40));
- QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(5));
-
- // Move out of all targets.
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(110, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
-
- // Stop the right target accepting drag events and move into it.
- rightTarget.accept = false;
-
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(80, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(80)); QCOMPARE(outerTarget.position.y(), qreal(50));
-
- // Stop the outer target accepting drag events after it has accepted an enter event.
- outerTarget.accept = false;
-
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(60, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
-
- // Clear the QQuickItem::ItemAcceptsDrops flag from the outer target after it accepted an enter event.
- outerTarget.setFlags(QQuickItem::Flags());
-
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(40, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(40)); QCOMPARE(outerTarget.position.y(), qreal(50));
-
- // Clear the QQuickItem::ItemAcceptsDrops flag from the left target before it accepts an enter event.
- leftTarget.setFlags(QQuickItem::Flags());
-
- outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
- item->setPos(QPointF(25, 50));
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
- QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
- QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
-}
-
-
-void tst_QQuickDrag::hotSpot()
-{
- QQuickCanvas canvas;
- TestDropTarget dropTarget(canvas.rootItem());
- dropTarget.setSize(QSizeF(100, 100));
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property real hotSpotX: Drag.hotSpot.x\n"
- "property real hotSpotY: Drag.hotSpot.y\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&dropTarget);
-
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(0));
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(0));
- QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(0));
- QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(0));
-
- evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
- QCOMPARE(dropTarget.position.x(), qreal(50));
- QCOMPARE(dropTarget.position.y(), qreal(50));
-
- evaluate<void>(item, "{ Drag.hotSpot.x = 5, Drag.hotSpot.y = 5 }");
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(5));
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(5));
- QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(5));
- QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(5));
-
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(dropTarget.position.x(), qreal(55));
- QCOMPARE(dropTarget.position.y(), qreal(55));
-
- item->setPos(QPointF(30, 20));
- QCOMPARE(dropTarget.position.x(), qreal(35));
- QCOMPARE(dropTarget.position.y(), qreal(25));
-
- evaluate<void>(item, "{ Drag.hotSpot.x = 10; Drag.hotSpot.y = 10 }");
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(10));
- QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(10));
- QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(10));
- QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(10));
- // Changing the hotSpot won't generate a move event so the position is unchanged. Should it?
- QCOMPARE(dropTarget.position.x(), qreal(35));
- QCOMPARE(dropTarget.position.y(), qreal(25));
-
- item->setPos(QPointF(10, 20));
- QCOMPARE(dropTarget.position.x(), qreal(20));
- QCOMPARE(dropTarget.position.y(), qreal(30));
-}
-
-void tst_QQuickDrag::supportedActions()
-{
- QQuickCanvas canvas;
- TestDropTarget dropTarget(canvas.rootItem());
- dropTarget.setSize(QSizeF(100, 100));
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property int supportedActions: Drag.supportedActions\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&dropTarget);
-
- QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
- QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
- evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
- QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);
-
- evaluate<void>(item, "Drag.supportedActions = Qt.CopyAction | Qt.MoveAction");
- QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
-
- // Once a drag is started the proposed actions are locked in for future events.
- evaluate<void>(item, "Drag.supportedActions = Qt.MoveAction");
- QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
- item->setPos(QPointF(60, 60));
- QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
-
- // Calling start with proposed actions will override the current actions for the next sequence.
- evaluate<void>(item, "Drag.start(Qt.CopyAction)");
- QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
- QCOMPARE(dropTarget.supportedActions, Qt::CopyAction);
-
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
- QCOMPARE(dropTarget.supportedActions, Qt::MoveAction);
-}
-
-void tst_QQuickDrag::proposedAction()
-{
- QQuickCanvas canvas;
- TestDropTarget dropTarget(canvas.rootItem());
- dropTarget.setSize(QSizeF(100, 100));
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property int proposedAction: Drag.proposedAction\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
- item->setParentItem(&dropTarget);
-
-
- QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
- evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
- QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
- QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
-
- evaluate<void>(item, "Drag.proposedAction = Qt.CopyAction");
- QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.CopyAction"), true);
- QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.CopyAction"), true);
- evaluate<void>(item, "Drag.start()");
- QCOMPARE(dropTarget.defaultAction, Qt::CopyAction);
- QCOMPARE(dropTarget.proposedAction, Qt::CopyAction);
-
- // The proposed action can change during a drag.
- evaluate<void>(item, "Drag.proposedAction = Qt.MoveAction");
- QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
- QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
- item->setPos(QPointF(60, 60));
- QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
- QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
-
- evaluate<void>(item, "Drag.proposedAction = Qt.LinkAction");
- QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.LinkAction"), true);
- QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.LinkAction"), true);
- evaluate<void>(item, "Drag.drop()");
- QCOMPARE(dropTarget.defaultAction, Qt::LinkAction);
- QCOMPARE(dropTarget.proposedAction, Qt::LinkAction);
-}
-
-void tst_QQuickDrag::keys()
-{
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property variant keys: Drag.keys\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
-
-// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList());
-// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList());
- QCOMPARE(item->property("keys").toStringList(), QStringList());
-
- evaluate<void>(item, "Drag.keys = [\"red\", \"blue\"]");
-// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList() << "red" << "blue");
-// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList() << "red" << "blue");
- QCOMPARE(item->property("keys").toStringList(), QStringList() << "red" << "blue");
-}
-
-void tst_QQuickDrag::source()
-{
-
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "Item {\n"
- "property Item source: Drag.source\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "Item { id: proxySource; objectName: \"proxySource\" }\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(item);
-
- QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
- QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
-
- QQuickItem *proxySource = item->findChild<QQuickItem *>("proxySource");
- QVERIFY(proxySource);
-
- evaluate<void>(item, "Drag.source = proxySource");
- QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(proxySource));
- QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(proxySource));
-
- evaluate<void>(item, "Drag.source = undefined");
- QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
- QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
-}
-
-QTEST_MAIN(tst_QQuickDrag)
-
-#include "tst_qquickdrag.moc"
diff --git a/tests/auto/declarative/qquickdroparea/qquickdroparea.pro b/tests/auto/declarative/qquickdroparea/qquickdroparea.pro
deleted file mode 100644
index eff08a2e94..0000000000
--- a/tests/auto/declarative/qquickdroparea/qquickdroparea.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-TARGET = tst_qquickdroparea
-CONFIG += testcase
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickdroparea.cpp
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/declarative/qquickdroparea/tst_qquickdroparea.cpp
deleted file mode 100644
index 0147536abf..0000000000
--- a/tests/auto/declarative/qquickdroparea/tst_qquickdroparea.cpp
+++ /dev/null
@@ -1,1117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qquickitem.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-
-#include <QtGui/qwindowsysteminterface_qpa.h>
-
-template <typename T> static T evaluate(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- QVariant result = expr.evaluate();
- if (expr.hasError())
- qWarning() << expr.error().toString();
- return result.value<T>();
-}
-
-template <> void evaluate<void>(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- expr.evaluate();
- if (expr.hasError())
- qWarning() << expr.error().toString();
-}
-
-class tst_QQuickDropArea: public QObject
-{
- Q_OBJECT
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void containsDrag_internal();
- void containsDrag_external();
- void keys_internal();
- void keys_external();
- void source_internal();
-// void source_external();
- void position_internal();
- void position_external();
- void drop_internal();
-// void drop_external();
- void simultaneousDrags();
-
-private:
- QDeclarativeEngine engine;
-};
-
-void tst_QQuickDropArea::initTestCase()
-{
-
-}
-
-void tst_QQuickDropArea::cleanupTestCase()
-{
-
-}
-
-void tst_QQuickDropArea::containsDrag_internal()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property bool hasDrag: containsDrag\n"
- "property int enterEvents: 0\n"
- "property int exitEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents}\n"
- "onExited: {++exitEvents}\n"
- "Item {\n"
- "objectName: \"dragItem\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
- QVERIFY(dragItem);
-
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
-
- dragItem->setPos(QPointF(150, 50));
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- dragItem->setPos(QPointF(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- dragItem->setPos(QPointF(150, 50));
-
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
-
- evaluate<void>(dragItem, "Drag.active = false");
-}
-
-void tst_QQuickDropArea::containsDrag_external()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property bool hasDrag: containsDrag\n"
- "property int enterEvents: 0\n"
- "property int exitEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents}\n"
- "onExited: {++exitEvents}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QMimeData data;
- QQuickCanvas alternateCanvas;
-
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
-
- evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
-
- QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(150, 50));
-}
-
-void tst_QQuickDropArea::keys_internal()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property variant dragKeys\n"
- "property variant dropKeys: keys\n"
- "property int enterEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
- "Item {\n"
- "objectName: \"dragItem\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "Drag.keys: [\"red\", \"blue\"]\n"
- "}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
- QVERIFY(dragItem);
-
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = \"blue\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "blue");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "blue");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = \"red\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = \"green\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "green");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "green");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = [\"red\", \"green\"]");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red" << "green");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red" << "green");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dragItem, "Drag.keys = []");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = []");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dropArea, "keys = []");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
-
- evaluate<void>(dragItem, "Drag.active = false");
- evaluate<void>(dragItem, "Drag.keys = [\"red\", \"blue\"]");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
-}
-
-void tst_QQuickDropArea::keys_external()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property variant dragKeys\n"
- "property variant dropKeys: keys\n"
- "property int enterEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- dropArea->setParentItem(canvas.rootItem());
-
- QMimeData data;
- QQuickCanvas alternateCanvas;
-
- data.setData("text/x-red", "red");
- data.setData("text/x-blue", "blue");
-
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- evaluate<void>(dropArea, "keys = \"text/x-blue\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-blue");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-blue");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- evaluate<void>(dropArea, "keys = \"text/x-red\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- evaluate<void>(dropArea, "keys = \"text/x-green\"");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-green");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-green");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- evaluate<void>(dropArea, "keys = [\"text/x-red\", \"text/x-green\"]");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- data.removeFormat("text/x-red");
- data.removeFormat("text/x-blue");
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- evaluate<void>(dropArea, "keys = []");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- data.setData("text/x-red", "red");
- data.setData("text/x-blue", "blue");
- QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
- QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
- evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
-
- QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(50, 50));
-}
-
-void tst_QQuickDropArea::source_internal()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property Item source: drag.source\n"
- "property Item eventSource\n"
- "width: 100; height: 100\n"
- "onEntered: {eventSource = drag.source}\n"
- "Item {\n"
- "objectName: \"dragItem\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}\n"
- "Item { id: dragSource; objectName: \"dragSource\" }\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
- QVERIFY(dragItem);
-
- QQuickItem *dragSource = dropArea->findChild<QQuickItem *>("dragSource");
- QVERIFY(dragSource);
-
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragItem));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragItem));
- QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragItem));
-
- evaluate<void>(dragItem, "Drag.active = false");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
-
-
- evaluate<void>(dropArea, "{ eventSource = null }");
- evaluate<void>(dragItem, "Drag.source = dragSource");
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragSource));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragSource));
- QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragSource));
-
- evaluate<void>(dragItem, "Drag.active = false");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
-}
-
-// Setting a source can't be emulated using the QWindowSystemInterface API.
-
-//void tst_QQuickDropArea::source_external()
-//{
-//}
-
-void tst_QQuickDropArea::position_internal()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property real dragX: drag.x\n"
- "property real dragY: drag.y\n"
- "property real eventX\n"
- "property real eventY\n"
- "property int enterEvents: 0\n"
- "property int moveEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
- "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
- "Item {\n"
- "objectName: \"dragItem\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
- QVERIFY(dragItem);
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 0);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
-
- evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- dragItem->setPos(QPointF(40, 50));
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
-
- evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- dragItem->setPos(QPointF(75, 25));
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
-
- evaluate<void>(dragItem, "Drag.active = false");
-}
-
-void tst_QQuickDropArea::position_external()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property real dragX: drag.x\n"
- "property real dragY: drag.y\n"
- "property real eventX\n"
- "property real eventY\n"
- "property int enterEvents: 0\n"
- "property int moveEvents: 0\n"
- "width: 100; height: 100\n"
- "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
- "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QMimeData data;
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
-
- evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(40, 50));
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
-
- evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(75, 25));
- QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
- QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
- QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
- QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
- QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
-
- QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(75, 25));
-}
-
-void tst_QQuickDropArea::drop_internal()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property bool accept: false\n"
- "property bool setAccepted: false\n"
- "property bool acceptDropAction: false\n"
- "property bool setDropAction: false\n"
- "property int dropAction: Qt.IgnoreAction\n"
- "property int proposedAction: Qt.IgnoreAction\n"
- "property int supportedActions: Qt.IgnoreAction\n"
- "property int dropEvents: 0\n"
- "width: 100; height: 100\n"
- "onDropped: {\n"
- "++dropEvents\n"
- "supportedActions = drop.supportedActions\n"
- "proposedAction = drop.action\n"
- "if (setDropAction)\n"
- "drop.action = dropAction\n"
- "if (acceptDropAction)\n"
- "drop.accept(dropAction)\n"
- "else if (setAccepted)\n"
- "drop.accepted = accept\n"
- "else if (accept)\n"
- "drop.accept()\n"
- "}\n"
- "Item {\n"
- "objectName: \"dragItem\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "}\n"
- "}", QUrl());
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea);
- dropArea->setParentItem(canvas.rootItem());
-
- QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
- QVERIFY(dragItem);
-
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ accept = true; setDropAction = true; dropAction = Qt.LinkAction }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = true; }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ accept = false; setAccepted = true; }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = false; setDropAction = false; acceptDropAction = true; }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ acceptDropAction = false; dropAction = Qt.IgnoreAction; accept = true }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = true }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = false }");
- evaluate<void>(dragItem, "Drag.supportedActions = Qt.LinkAction");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = true }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = false }");
- evaluate<void>(dragItem, "Drag.proposedAction = Qt.LinkAction");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
-
- evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
- evaluate<void>(dropArea, "{ setAccepted = true }");
- evaluate<void>(dragItem, "Drag.active = true");
- QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
- QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
-}
-
-// Setting the supportedActions can't be emulated using the QWindowSystemInterface API.
-
-//void tst_QQuickDropArea::drop_external()
-//{
-//}
-
-void tst_QQuickDropArea::simultaneousDrags()
-{
- QQuickCanvas canvas;
- QDeclarativeComponent component(&engine);
- component.setData(
- "import QtQuick 2.0\n"
- "DropArea {\n"
- "property int enterEvents: 0\n"
- "property int exitEvents: 0\n"
- "width: 100; height: 100\n"
- "keys: [\"red\", \"text/x-red\"]\n"
- "onEntered: {++enterEvents}\n"
- "onExited: {++exitEvents}\n"
- "DropArea {\n"
- "objectName: \"dropArea2\"\n"
- "property int enterEvents: 0\n"
- "property int exitEvents: 0\n"
- "width: 100; height: 100\n"
- "keys: [\"blue\", \"text/x-blue\"]\n"
- "onEntered: {++enterEvents}\n"
- "onExited: {++exitEvents}\n"
- "}\n"
- "Item {\n"
- "objectName: \"dragItem1\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "Drag.keys: [\"red\", \"blue\"]"
- "}\n"
- "Item {\n"
- "objectName: \"dragItem2\"\n"
- "x: 50; y: 50\n"
- "width: 10; height: 10\n"
- "Drag.keys: [\"red\", \"blue\"]"
- "}\n"
- "}", QUrl());
-
- QScopedPointer<QObject> object(component.create());
- QQuickItem *dropArea1 = qobject_cast<QQuickItem *>(object.data());
- QVERIFY(dropArea1);
- dropArea1->setParentItem(canvas.rootItem());
-
- QQuickItem *dropArea2 = dropArea1->findChild<QQuickItem *>("dropArea2");
- QVERIFY(dropArea2);
-
- QQuickItem *dragItem1 = dropArea1->findChild<QQuickItem *>("dragItem1");
- QVERIFY(dragItem1);
-
- QQuickItem *dragItem2 = dropArea1->findChild<QQuickItem *>("dragItem2");
- QVERIFY(dragItem2);
-
- QMimeData data;
- data.setData("text/x-red", "red");
- data.setData("text/x-blue", "blue");
-
- QQuickCanvas alternateCanvas;
-
- // Mixed internal drags.
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- // internal then external.
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- // external then internal.
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- // Different acceptance
- evaluate<void>(dragItem1, "Drag.keys = \"red\"");
- evaluate<void>(dragItem2, "Drag.keys = \"blue\"");
- data.removeFormat("text/x-red");
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- // internal then external
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
-
- evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
- evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
- QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
-
- QWindowSystemInterface::handleDrop(&alternateCanvas, &data, QPoint(50, 50));
-}
-
-QTEST_MAIN(tst_QQuickDropArea)
-
-#include "tst_qquickdroparea.moc"
diff --git a/tests/auto/declarative/qquickflickable/qquickflickable.pro b/tests/auto/declarative/qquickflickable/qquickflickable.pro
deleted file mode 100644
index ba951cc051..0000000000
--- a/tests/auto/declarative/qquickflickable/qquickflickable.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickflickable
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickflickable.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickflickable/tst_qquickflickable.cpp b/tests/auto/declarative/qquickflickable/tst_qquickflickable.cpp
deleted file mode 100644
index a02db06616..0000000000
--- a/tests/auto/declarative/qquickflickable/tst_qquickflickable.cpp
+++ /dev/null
@@ -1,662 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickflickable_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include <math.h>
-#include "../shared/util.h"
-#include <QtOpenGL/QGLShaderProgram>
-
-class tst_qquickflickable : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickflickable();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void create();
- void horizontalViewportSize();
- void verticalViewportSize();
- void properties();
- void boundsBehavior();
- void maximumFlickVelocity();
- void flickDeceleration();
- void pressDelay();
- void nestedPressDelay();
- void flickableDirection();
- void resizeContent();
- void returnToBounds();
- void wheel();
- void movingAndDragging();
- void disabled();
- void flickVelocity();
- void margins();
-
-private:
- QDeclarativeEngine engine;
-
- void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &objectName);
-};
-
-tst_qquickflickable::tst_qquickflickable()
-{
-}
-
-void tst_qquickflickable::initTestCase()
-{
-
-}
-
-void tst_qquickflickable::cleanupTestCase()
-{
-
-}
-
-void tst_qquickflickable::create()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable01.qml")));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->isAtXBeginning(), true);
- QCOMPARE(obj->isAtXEnd(), false);
- QCOMPARE(obj->isAtYBeginning(), true);
- QCOMPARE(obj->isAtYEnd(), false);
- QCOMPARE(obj->contentX(), 0.);
- QCOMPARE(obj->contentY(), 0.);
-
- QCOMPARE(obj->horizontalVelocity(), 0.);
- QCOMPARE(obj->verticalVelocity(), 0.);
-
- QCOMPARE(obj->isInteractive(), true);
- QCOMPARE(obj->boundsBehavior(), QQuickFlickable::DragAndOvershootBounds);
- QCOMPARE(obj->pressDelay(), 0);
- QCOMPARE(obj->maximumFlickVelocity(), 2500.);
-
- delete obj;
-}
-
-void tst_qquickflickable::horizontalViewportSize()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable02.qml")));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->contentWidth(), 800.);
- QCOMPARE(obj->contentHeight(), 300.);
- QCOMPARE(obj->isAtXBeginning(), true);
- QCOMPARE(obj->isAtXEnd(), false);
- QCOMPARE(obj->isAtYBeginning(), true);
- QCOMPARE(obj->isAtYEnd(), false);
-
- delete obj;
-}
-
-void tst_qquickflickable::verticalViewportSize()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->contentWidth(), 200.);
- QCOMPARE(obj->contentHeight(), 1200.);
- QCOMPARE(obj->isAtXBeginning(), true);
- QCOMPARE(obj->isAtXEnd(), false);
- QCOMPARE(obj->isAtYBeginning(), true);
- QCOMPARE(obj->isAtYEnd(), false);
-
- delete obj;
-}
-
-void tst_qquickflickable::properties()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable04.qml")));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->isInteractive(), false);
- QCOMPARE(obj->boundsBehavior(), QQuickFlickable::StopAtBounds);
- QCOMPARE(obj->pressDelay(), 200);
- QCOMPARE(obj->maximumFlickVelocity(), 2000.);
-
- QVERIFY(obj->property("ok").toBool() == false);
- QMetaObject::invokeMethod(obj, "check");
- QVERIFY(obj->property("ok").toBool() == true);
-
- delete obj;
-}
-
-void tst_qquickflickable::boundsBehavior()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Flickable { boundsBehavior: Flickable.StopAtBounds }", QUrl::fromLocalFile(""));
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
- QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
-
- QVERIFY(flickable);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
-
- flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragAndOvershootBounds);
- QCOMPARE(spy.count(),1);
- flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
- QCOMPARE(spy.count(),1);
-
- flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragOverBounds);
- QCOMPARE(spy.count(),2);
- flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
- QCOMPARE(spy.count(),2);
-
- flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
- QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
- QCOMPARE(spy.count(),3);
- flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
- QCOMPARE(spy.count(),3);
-}
-
-void tst_qquickflickable::maximumFlickVelocity()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Flickable { maximumFlickVelocity: 1.0; }", QUrl::fromLocalFile(""));
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
- QSignalSpy spy(flickable, SIGNAL(maximumFlickVelocityChanged()));
-
- QVERIFY(flickable);
- QCOMPARE(flickable->maximumFlickVelocity(), 1.0);
-
- flickable->setMaximumFlickVelocity(2.0);
- QCOMPARE(flickable->maximumFlickVelocity(), 2.0);
- QCOMPARE(spy.count(),1);
- flickable->setMaximumFlickVelocity(2.0);
- QCOMPARE(spy.count(),1);
-}
-
-void tst_qquickflickable::flickDeceleration()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Flickable { flickDeceleration: 1.0; }", QUrl::fromLocalFile(""));
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
- QSignalSpy spy(flickable, SIGNAL(flickDecelerationChanged()));
-
- QVERIFY(flickable);
- QCOMPARE(flickable->flickDeceleration(), 1.0);
-
- flickable->setFlickDeceleration(2.0);
- QCOMPARE(flickable->flickDeceleration(), 2.0);
- QCOMPARE(spy.count(),1);
- flickable->setFlickDeceleration(2.0);
- QCOMPARE(spy.count(),1);
-}
-
-void tst_qquickflickable::pressDelay()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Flickable { pressDelay: 100; }", QUrl::fromLocalFile(""));
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
- QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
-
- QVERIFY(flickable);
- QCOMPARE(flickable->pressDelay(), 100);
-
- flickable->setPressDelay(200);
- QCOMPARE(flickable->pressDelay(), 200);
- QCOMPARE(spy.count(),1);
- flickable->setPressDelay(200);
- QCOMPARE(spy.count(),1);
-}
-
-// QTBUG-17361
-void tst_qquickflickable::nestedPressDelay()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("nestedPressDelay.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(canvas->rootObject());
- QVERIFY(outer != 0);
-
- QQuickFlickable *inner = canvas->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
- QVERIFY(inner != 0);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(150, 150));
- // the MouseArea is not pressed immediately
- QVERIFY(outer->property("pressed").toBool() == false);
-
- // The outer pressDelay will prevail (50ms, vs. 10sec)
- // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
- QTRY_VERIFY(outer->property("pressed").toBool() == true);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(150, 150));
-
- delete canvas;
-}
-
-void tst_qquickflickable::flickableDirection()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Flickable { flickableDirection: Flickable.VerticalFlick; }", QUrl::fromLocalFile(""));
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
- QSignalSpy spy(flickable, SIGNAL(flickableDirectionChanged()));
-
- QVERIFY(flickable);
- QCOMPARE(flickable->flickableDirection(), QQuickFlickable::VerticalFlick);
-
- flickable->setFlickableDirection(QQuickFlickable::HorizontalAndVerticalFlick);
- QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalAndVerticalFlick);
- QCOMPARE(spy.count(),1);
-
- flickable->setFlickableDirection(QQuickFlickable::AutoFlickDirection);
- QCOMPARE(flickable->flickableDirection(), QQuickFlickable::AutoFlickDirection);
- QCOMPARE(spy.count(),2);
-
- flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
- QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
- QCOMPARE(spy.count(),3);
-
- flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
- QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
- QCOMPARE(spy.count(),3);
-}
-
-// QtQuick 1.1
-void tst_qquickflickable::resizeContent()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("resize.qml")));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
- QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->contentX(), 0.);
- QCOMPARE(obj->contentY(), 0.);
- QCOMPARE(obj->contentWidth(), 300.);
- QCOMPARE(obj->contentHeight(), 300.);
-
- QMetaObject::invokeMethod(root, "resizeContent");
-
- QCOMPARE(obj->contentX(), 100.);
- QCOMPARE(obj->contentY(), 100.);
- QCOMPARE(obj->contentWidth(), 600.);
- QCOMPARE(obj->contentHeight(), 600.);
-
- delete root;
-}
-
-// QtQuick 1.1
-void tst_qquickflickable::returnToBounds()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("resize.qml")));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
- QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->contentX(), 0.);
- QCOMPARE(obj->contentY(), 0.);
- QCOMPARE(obj->contentWidth(), 300.);
- QCOMPARE(obj->contentHeight(), 300.);
-
- obj->setContentX(100);
- obj->setContentY(400);
- QTRY_COMPARE(obj->contentX(), 100.);
- QTRY_COMPARE(obj->contentY(), 400.);
-
- QMetaObject::invokeMethod(root, "returnToBounds");
-
- QTRY_COMPARE(obj->contentX(), 0.);
- QTRY_COMPARE(obj->contentY(), 0.);
-
- delete root;
-}
-
-void tst_qquickflickable::wheel()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("wheel.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flick");
- QVERIFY(flick != 0);
-
- {
- QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
- event.setAccepted(false);
- QApplication::sendEvent(canvas, &event);
- }
-
- QTRY_VERIFY(flick->contentY() > 0);
- QVERIFY(flick->contentX() == 0);
-
- flick->setContentY(0);
- QVERIFY(flick->contentY() == 0);
-
- {
- QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Horizontal);
- event.setAccepted(false);
- QApplication::sendEvent(canvas, &event);
- }
-
- QTRY_VERIFY(flick->contentX() > 0);
- QVERIFY(flick->contentY() == 0);
-
- delete canvas;
-}
-
-void tst_qquickflickable::movingAndDragging()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
- QVERIFY(flickable != 0);
-
- QSignalSpy vDragSpy(flickable, SIGNAL(draggingVerticallyChanged()));
- QSignalSpy hDragSpy(flickable, SIGNAL(draggingHorizontallyChanged()));
- QSignalSpy dragSpy(flickable, SIGNAL(draggingChanged()));
- QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
- QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
- QSignalSpy moveSpy(flickable, SIGNAL(movingChanged()));
- QSignalSpy dragStartSpy(flickable, SIGNAL(dragStarted()));
- QSignalSpy dragEndSpy(flickable, SIGNAL(dragEnded()));
-
- //Vertical
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
-
- QTest::mouseMove(canvas, QPoint(50, 80));
- QTest::mouseMove(canvas, QPoint(50, 70));
- QTest::mouseMove(canvas, QPoint(50, 60));
-
- QMouseEvent moveEvent(QEvent::MouseMove, QPoint(50, 80), Qt::LeftButton, Qt::LeftButton, 0);
-
- QVERIFY(!flickable->isDraggingHorizontally());
- QVERIFY(flickable->isDraggingVertically());
- QVERIFY(flickable->isDragging());
- QCOMPARE(vDragSpy.count(), 1);
- QCOMPARE(dragSpy.count(), 1);
- QCOMPARE(hDragSpy.count(), 0);
- QCOMPARE(dragStartSpy.count(), 1);
- QCOMPARE(dragEndSpy.count(), 0);
-
- QVERIFY(!flickable->isMovingHorizontally());
- QVERIFY(flickable->isMovingVertically());
- QVERIFY(flickable->isMoving());
- QCOMPARE(vMoveSpy.count(), 1);
- QCOMPARE(moveSpy.count(), 1);
- QCOMPARE(hMoveSpy.count(), 0);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
-
- QTRY_VERIFY(!flickable->isDraggingVertically());
- QVERIFY(!flickable->isDragging());
- QCOMPARE(vDragSpy.count(), 2);
- QCOMPARE(dragSpy.count(), 2);
- QCOMPARE(hDragSpy.count(), 0);
- QCOMPARE(dragStartSpy.count(), 1);
- QCOMPARE(dragEndSpy.count(), 1);
-
- // wait for any motion to end
- QTRY_VERIFY(flickable->isMoving() == false);
-
- //Horizontal
- vDragSpy.clear();
- hDragSpy.clear();
- dragSpy.clear();
- vMoveSpy.clear();
- hMoveSpy.clear();
- moveSpy.clear();
- dragStartSpy.clear();
- dragEndSpy.clear();
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(90, 50));
-
- QTest::mouseMove(canvas, QPoint(80, 50));
- QTest::mouseMove(canvas, QPoint(70, 50));
- QTest::mouseMove(canvas, QPoint(60, 50));
-
- QVERIFY(flickable->isDraggingHorizontally());
- QVERIFY(flickable->isDragging());
- QCOMPARE(vDragSpy.count(), 0);
- QCOMPARE(dragSpy.count(), 1);
- QCOMPARE(hDragSpy.count(), 1);
- QCOMPARE(dragStartSpy.count(), 1);
- QCOMPARE(dragEndSpy.count(), 0);
-
- QVERIFY(!flickable->isMovingVertically());
- QVERIFY(flickable->isMovingHorizontally());
- QVERIFY(flickable->isMoving());
- QCOMPARE(vMoveSpy.count(), 0);
- QCOMPARE(moveSpy.count(), 1);
- QCOMPARE(hMoveSpy.count(), 1);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(60, 50));
-
- QTRY_VERIFY(!flickable->isDraggingHorizontally());
- QVERIFY(!flickable->isDragging());
- QCOMPARE(vDragSpy.count(), 0);
- QCOMPARE(dragSpy.count(), 2);
- QCOMPARE(hDragSpy.count(), 2);
- QCOMPARE(dragStartSpy.count(), 1);
- QCOMPARE(dragEndSpy.count(), 1);
-
- // Don't test moving because a flick could occur
-
- delete canvas;
-}
-
-void tst_qquickflickable::disabled()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("disabled.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flickable");
- QVERIFY(flick != 0);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
-
- QTest::mouseMove(canvas, QPoint(50, 80));
- QTest::mouseMove(canvas, QPoint(50, 70));
- QTest::mouseMove(canvas, QPoint(50, 60));
-
- QVERIFY(flick->isMoving() == false);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
-
- // verify that mouse clicks on other elements still work (QTBUG-20584)
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 10));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10));
-
- QTRY_VERIFY(canvas->rootObject()->property("clicked").toBool() == true);
-}
-
-void tst_qquickflickable::flickVelocity()
-{
-#ifdef Q_OS_MAC
- QSKIP("Producing flicks on Mac CI impossible due to timing problems");
-#endif
-
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
- QVERIFY(flickable != 0);
-
- // flick up
- flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
- QVERIFY(flickable->verticalVelocity() > 0.0);
- QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
-
- // flick down
- flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
- QVERIFY(flickable->verticalVelocity() < 0.0);
- QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
-
- delete canvas;
-}
-
-void tst_qquickflickable::margins()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("margins.qml")));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
- QVERIFY(obj != 0);
-
- // starting state
- QCOMPARE(obj->contentX(), -40.);
- QCOMPARE(obj->contentY(), -20.);
- QCOMPARE(obj->contentWidth(), 1600.);
- QCOMPARE(obj->contentHeight(), 600.);
- QCOMPARE(obj->xOrigin(), 0.);
- QCOMPARE(obj->yOrigin(), 0.);
-
- // Reduce left margin
- obj->setLeftMargin(30);
- QTRY_COMPARE(obj->contentX(), -30.);
-
- // Reduce top margin
- obj->setTopMargin(20);
- QTRY_COMPARE(obj->contentY(), -20.);
-
- // position to the far right, including margin
- obj->setContentX(1600 + 50 - obj->width());
- obj->returnToBounds();
- QTest::qWait(200);
- QCOMPARE(obj->contentX(), 1600. + 50. - obj->width());
-
- // position beyond the far right, including margin
- obj->setContentX(1600 + 50 - obj->width() + 1.);
- obj->returnToBounds();
- QTRY_COMPARE(obj->contentX(), 1600. + 50. - obj->width());
-
- // Reduce right margin
- obj->setRightMargin(40);
- QTRY_COMPARE(obj->contentX(), 1600. + 40. - obj->width());
- QCOMPARE(obj->contentWidth(), 1600.);
-
- // position to the far bottom, including margin
- obj->setContentY(600 + 30 - obj->height());
- obj->returnToBounds();
- QTest::qWait(200);
- QCOMPARE(obj->contentY(), 600. + 30. - obj->height());
-
- // position beyond the far bottom, including margin
- obj->setContentY(600 + 30 - obj->height() + 1.);
- obj->returnToBounds();
- QTRY_COMPARE(obj->contentY(), 600. + 30. - obj->height());
-
- // Reduce bottom margin
- obj->setBottomMargin(20);
- QTRY_COMPARE(obj->contentY(), 600. + 20. - obj->height());
- QCOMPARE(obj->contentHeight(), 600.);
-
- delete root;
-}
-
-void tst_qquickflickable::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
-{
- const int pointCount = 5;
- QPoint diff = to - from;
-
- // send press, five equally spaced moves, and release.
- QTest::mousePress(canvas, Qt::LeftButton, 0, from);
-
- for (int i = 0; i < pointCount; ++i) {
- QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- QTest::qWait(duration/pointCount);
- QCoreApplication::processEvents();
- }
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
-}
-
-template<typename T>
-T *tst_qquickflickable::findItem(QQuickItem *parent, const QString &objectName)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- return static_cast<T*>(item);
- }
- item = findItem<T>(item, objectName);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-QTEST_MAIN(tst_qquickflickable)
-
-#include "tst_qquickflickable.moc"
diff --git a/tests/auto/declarative/qquickflipable/qquickflipable.pro b/tests/auto/declarative/qquickflipable/qquickflipable.pro
deleted file mode 100644
index a36c468c1c..0000000000
--- a/tests/auto/declarative/qquickflipable/qquickflipable.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickflipable
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickflipable.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickflipable/tst_qquickflipable.cpp b/tests/auto/declarative/qquickflipable/tst_qquickflipable.cpp
deleted file mode 100644
index 7243836031..0000000000
--- a/tests/auto/declarative/qquickflipable/tst_qquickflipable.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickflipable_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include <QFontMetrics>
-#include <private/qquickrectangle_p.h>
-#include <math.h>
-#include <QtOpenGL/QGLShaderProgram>
-#include "../shared/util.h"
-
-class tst_qquickflipable : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickflipable();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void create();
- void checkFrontAndBack();
- void setFrontAndBack();
-
- // below here task issues
- void QTBUG_9161_crash();
- void QTBUG_8474_qgv_abort();
-
-private:
- QDeclarativeEngine engine;
-};
-
-tst_qquickflipable::tst_qquickflipable()
-{
-}
-void tst_qquickflipable::initTestCase()
-{
-}
-
-void tst_qquickflipable::cleanupTestCase()
-{
-
-}
-
-void tst_qquickflipable::create()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
- QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
-
- QVERIFY(obj != 0);
- delete obj;
-}
-
-void tst_qquickflipable::checkFrontAndBack()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
- QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
-
- QVERIFY(obj != 0);
- QVERIFY(obj->front() != 0);
- QVERIFY(obj->back() != 0);
- delete obj;
-}
-
-void tst_qquickflipable::setFrontAndBack()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
- QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
-
- QVERIFY(obj != 0);
- QVERIFY(obj->front() != 0);
- QVERIFY(obj->back() != 0);
-
- QString message = c.url().toString() + ":3:1: QML Flipable: front is a write-once property";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
- obj->setFront(new QQuickRectangle());
-
- message = c.url().toString() + ":3:1: QML Flipable: back is a write-once property";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
- obj->setBack(new QQuickRectangle());
- delete obj;
-}
-
-void tst_qquickflipable::QTBUG_9161_crash()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("crash.qml")));
- QQuickItem *root = canvas->rootObject();
- QVERIFY(root != 0);
- canvas->show();
- delete canvas;
-}
-
-void tst_qquickflipable::QTBUG_8474_qgv_abort()
-{
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("flipable-abort.qml")));
- QQuickItem *root = canvas->rootObject();
- QVERIFY(root != 0);
- canvas->show();
- delete canvas;
-}
-
-QTEST_MAIN(tst_qquickflipable)
-
-#include "tst_qquickflipable.moc"
diff --git a/tests/auto/declarative/qquickfocusscope/qquickfocusscope.pro b/tests/auto/declarative/qquickfocusscope/qquickfocusscope.pro
deleted file mode 100644
index 79649ebb8a..0000000000
--- a/tests/auto/declarative/qquickfocusscope/qquickfocusscope.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickfocusscope
-SOURCES += tst_qquickfocusscope.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickfocusscope/tst_qquickfocusscope.cpp b/tests/auto/declarative/qquickfocusscope/tst_qquickfocusscope.cpp
deleted file mode 100644
index d0149ed1d6..0000000000
--- a/tests/auto/declarative/qquickfocusscope/tst_qquickfocusscope.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QSignalSpy>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquicktextedit_p.h>
-#include <private/qquicktext_p.h>
-#include <QtDeclarative/private/qquickfocusscope_p.h>
-#include "../shared/util.h"
-
-class tst_qquickfocusscope : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickfocusscope() {}
-
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &id);
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void basic();
- void nested();
- void noFocus();
- void textEdit();
- void forceFocus();
- void noParentFocus();
- void signalEmission();
- void qtBug13380();
- void forceActiveFocus();
- void canvasFocus();
-};
-void tst_qquickfocusscope::initTestCase()
-{
-}
-
-void tst_qquickfocusscope::cleanupTestCase()
-{
-
-}
-
-/*
- Find an item with the specified id.
-*/
-template<typename T>
-T *tst_qquickfocusscope::findItem(QQuickItem *parent, const QString &objectName)
-{
- const QMetaObject &mo = T::staticMetaObject;
- QList<QQuickItem *> children = parent->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *item = children.at(i);
- if (item) {
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- return static_cast<T*>(item);
- }
- item = findItem<T>(item, objectName);
- if (item)
- return static_cast<T*>(item);
- }
- }
- return 0;
-}
-
-void tst_qquickfocusscope::basic()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("test.qml")));
-
- QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
- QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
- QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
- QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVERIFY(view->isTopLevel());
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Right);
- QTest::qWait(50);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Down);
- QTest::qWait(50);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
-
- delete view;
-}
-
-void tst_qquickfocusscope::nested()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("test2.qml")));
-
- QQuickFocusScope *item1 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item1"));
- QQuickFocusScope *item2 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item2"));
- QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
- QQuickFocusScope *item4 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item4"));
- QQuickFocusScope *item5 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item5"));
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
- QVERIFY(item5 != 0);
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == true);
- QVERIFY(item4->hasActiveFocus() == true);
- QVERIFY(item5->hasActiveFocus() == true);
- delete view;
-}
-
-void tst_qquickfocusscope::noFocus()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("test4.qml")));
-
- QQuickRectangle *item0 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item0"));
- QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
- QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
- QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
-
- view->show();
- view->requestActivateWindow();
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Down);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- delete view;
-}
-
-void tst_qquickfocusscope::textEdit()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("test5.qml")));
-
- QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
- QQuickTextEdit *item1 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item1"));
- QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
- QQuickTextEdit *item3 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
-
- QTRY_VERIFY(view == qGuiApp->focusWindow());
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Right);
- QTest::keyClick(view, Qt::Key_Right);
- QTest::keyClick(view, Qt::Key_Right);
- QTest::keyClick(view, Qt::Key_Right);
- QTest::keyClick(view, Qt::Key_Right);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == true);
- QVERIFY(item3->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_Down);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
-
- delete view;
-}
-
-void tst_qquickfocusscope::forceFocus()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("forcefocus.qml")));
-
- QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
- QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
- QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
- QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
- QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
- QQuickRectangle *item5 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item5"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
- QVERIFY(item5 != 0);
-
- view->show();
- view->requestActivateWindow();
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_4);
- QVERIFY(item0->hasActiveFocus() == true);
- QVERIFY(item1->hasActiveFocus() == true);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == false);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == false);
-
- QTest::keyClick(view, Qt::Key_5);
- QVERIFY(item0->hasActiveFocus() == false);
- QVERIFY(item1->hasActiveFocus() == false);
- QVERIFY(item2->hasActiveFocus() == false);
- QVERIFY(item3->hasActiveFocus() == true);
- QVERIFY(item4->hasActiveFocus() == false);
- QVERIFY(item5->hasActiveFocus() == true);
-
- delete view;
-}
-
-void tst_qquickfocusscope::noParentFocus()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("chain.qml")));
- QVERIFY(view->rootObject());
-
- view->show();
- view->requestActivateWindow();
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVERIFY(view->rootObject()->property("focus1") == false);
- QVERIFY(view->rootObject()->property("focus2") == false);
- QVERIFY(view->rootObject()->property("focus3") == true);
- QVERIFY(view->rootObject()->property("focus4") == true);
- QVERIFY(view->rootObject()->property("focus5") == true);
-
- delete view;
-}
-
-void tst_qquickfocusscope::signalEmission()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("signalEmission.qml")));
-
- QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
- QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
- QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
- QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QVariant blue(QColor("blue"));
- QVariant red(QColor("red"));
-
- item1->setFocus(true);
- QCOMPARE(item1->property("color"), red);
- QCOMPARE(item2->property("color"), blue);
- QCOMPARE(item3->property("color"), blue);
- QCOMPARE(item4->property("color"), blue);
-
- item2->setFocus(true);
- QCOMPARE(item1->property("color"), blue);
- QCOMPARE(item2->property("color"), red);
- QCOMPARE(item3->property("color"), blue);
- QCOMPARE(item4->property("color"), blue);
-
- item3->setFocus(true);
- QCOMPARE(item1->property("color"), blue);
- QCOMPARE(item2->property("color"), red);
- QCOMPARE(item3->property("color"), red);
- QCOMPARE(item4->property("color"), blue);
-
- item4->setFocus(true);
- QCOMPARE(item1->property("color"), blue);
- QCOMPARE(item2->property("color"), red);
- QCOMPARE(item3->property("color"), blue);
- QCOMPARE(item4->property("color"), red);
-
- item4->setFocus(false);
- QCOMPARE(item1->property("color"), blue);
- QCOMPARE(item2->property("color"), red);
- QCOMPARE(item3->property("color"), blue);
- QCOMPARE(item4->property("color"), blue);
-
- delete view;
-}
-
-void tst_qquickfocusscope::qtBug13380()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("qtBug13380.qml")));
-
- view->show();
- QVERIFY(view->rootObject());
- view->requestActivateWindow();
- qApp->processEvents();
-
- QTest::qWaitForWindowShown(view);
-
- QTRY_VERIFY(view == qGuiApp->focusWindow());
- QVERIFY(view->rootObject()->property("noFocus").toBool());
-
- view->rootObject()->setProperty("showRect", true);
- QVERIFY(view->rootObject()->property("noFocus").toBool());
-
- delete view;
-}
-
-void tst_qquickfocusscope::forceActiveFocus()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("forceActiveFocus.qml")));
-
- view->show();
- view->requestActivateWindow();
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- QQuickItem *rootObject = view->rootObject();
- QVERIFY(rootObject);
-
- QQuickItem *scope = findItem<QQuickItem>(rootObject, QLatin1String("scope"));
- QQuickItem *itemA1 = findItem<QQuickItem>(rootObject, QLatin1String("item-a1"));
- QQuickItem *scopeA = findItem<QQuickItem>(rootObject, QLatin1String("scope-a"));
- QQuickItem *itemA2 = findItem<QQuickItem>(rootObject, QLatin1String("item-a2"));
- QQuickItem *itemB1 = findItem<QQuickItem>(rootObject, QLatin1String("item-b1"));
- QQuickItem *scopeB = findItem<QQuickItem>(rootObject, QLatin1String("scope-b"));
- QQuickItem *itemB2 = findItem<QQuickItem>(rootObject, QLatin1String("item-b2"));
-
- QVERIFY(scope);
- QVERIFY(itemA1);
- QVERIFY(scopeA);
- QVERIFY(itemA2);
- QVERIFY(itemB1);
- QVERIFY(scopeB);
- QVERIFY(itemB2);
-
- QSignalSpy rootSpy(rootObject, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy scopeSpy(scope, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy scopeASpy(scopeA, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy scopeBSpy(scopeB, SIGNAL(activeFocusChanged(bool)));
-
- // First, walk the focus from item-a1 down to item-a2 and back again
- itemA1->forceActiveFocus();
- QVERIFY(itemA1->hasActiveFocus());
- QVERIFY(!rootObject->hasActiveFocus());
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- scopeA->forceActiveFocus();
- QVERIFY(!itemA1->hasActiveFocus());
- QVERIFY(scopeA->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 1);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- itemA2->forceActiveFocus();
- QVERIFY(!itemA1->hasActiveFocus());
- QVERIFY(itemA2->hasActiveFocus());
- QVERIFY(scopeA->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 1);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- scopeA->forceActiveFocus();
- QVERIFY(!itemA1->hasActiveFocus());
- QVERIFY(itemA2->hasActiveFocus());
- QVERIFY(scopeA->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 1);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- itemA1->forceActiveFocus();
- QVERIFY(itemA1->hasActiveFocus());
- QVERIFY(!scopeA->hasActiveFocus());
- QVERIFY(!itemA2->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 2);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- // Then jump back and forth between branch 'a' and 'b'
- itemB1->forceActiveFocus();
- QVERIFY(itemB1->hasActiveFocus());
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- scopeA->forceActiveFocus();
- QVERIFY(!itemA1->hasActiveFocus());
- QVERIFY(!itemB1->hasActiveFocus());
- QVERIFY(scopeA->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 3);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- scopeB->forceActiveFocus();
- QVERIFY(!scopeA->hasActiveFocus());
- QVERIFY(!itemB1->hasActiveFocus());
- QVERIFY(scopeB->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 4);
- QCOMPARE(scopeBSpy.count(), 1);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- itemA2->forceActiveFocus();
- QVERIFY(!scopeB->hasActiveFocus());
- QVERIFY(itemA2->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 5);
- QCOMPARE(scopeBSpy.count(), 2);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- itemB2->forceActiveFocus();
- QVERIFY(!itemA2->hasActiveFocus());
- QVERIFY(itemB2->hasActiveFocus());
- QCOMPARE(scopeASpy.count(), 6);
- QCOMPARE(scopeBSpy.count(), 3);
- QCOMPARE(rootSpy.count(), 0);
- QCOMPARE(scopeSpy.count(), 1);
-
- delete view;
-}
-
-void tst_qquickfocusscope::canvasFocus()
-{
- QQuickView *view = new QQuickView;
- view->setSource(QUrl::fromLocalFile(TESTDATA("canvasFocus.qml")));
-
- QQuickView alternateView;
-
- QQuickItem *rootObject = view->rootObject();
- QVERIFY(rootObject);
-
- QQuickItem *rootItem = view->rootItem();
- QQuickItem *scope1 = findItem<QQuickItem>(rootObject, QLatin1String("scope1"));
- QQuickItem *item1 = findItem<QQuickItem>(rootObject, QLatin1String("item1"));
- QQuickItem *scope2 = findItem<QQuickItem>(rootObject, QLatin1String("scope2"));
- QQuickItem *item2 = findItem<QQuickItem>(rootObject, QLatin1String("item2"));
-
- QVERIFY(scope1);
- QVERIFY(item1);
- QVERIFY(scope2);
- QVERIFY(item2);
-
- QSignalSpy rootFocusSpy(rootItem, SIGNAL(focusChanged(bool)));
- QSignalSpy scope1FocusSpy(scope1, SIGNAL(focusChanged(bool)));
- QSignalSpy item1FocusSpy(item1, SIGNAL(focusChanged(bool)));
- QSignalSpy scope2FocusSpy(scope2, SIGNAL(focusChanged(bool)));
- QSignalSpy item2FocusSpy(item2, SIGNAL(focusChanged(bool)));
- QSignalSpy rootActiveFocusSpy(rootItem, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy scope1ActiveFocusSpy(scope1, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy item1ActiveFocusSpy(item1, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy scope2ActiveFocusSpy(scope2, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy item2ActiveFocusSpy(item2, SIGNAL(activeFocusChanged(bool)));
-
- QEXPECT_FAIL("", "QTBUG-22415", Abort);
- QCOMPARE(rootItem->hasFocus(), false);
- QCOMPARE(rootItem->hasActiveFocus(), false);
- QCOMPARE(scope1->hasFocus(), true);
- QCOMPARE(scope1->hasActiveFocus(), false);
- QCOMPARE(item1->hasFocus(), true);
- QCOMPARE(item1->hasActiveFocus(), false);
- QCOMPARE(scope2->hasFocus(), false);
- QCOMPARE(scope2->hasActiveFocus(), false);
- QCOMPARE(item2->hasFocus(), false);
- QCOMPARE(item2->hasActiveFocus(), false);
-
- view->show();
- view->requestActivateWindow();
-
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(view == qGuiApp->focusWindow());
-
- // Now the canvas has focus, active focus given to item1
- QCOMPARE(rootItem->hasFocus(), true);
- QCOMPARE(rootItem->hasActiveFocus(), true);
- QCOMPARE(scope1->hasFocus(), true);
- QCOMPARE(scope1->hasActiveFocus(), true);
- QCOMPARE(item1->hasFocus(), true);
- QCOMPARE(item1->hasActiveFocus(), true);
- QCOMPARE(scope2->hasFocus(), false);
- QCOMPARE(scope2->hasActiveFocus(), false);
- QCOMPARE(item2->hasFocus(), false);
- QCOMPARE(item2->hasActiveFocus(), false);
-
- QCOMPARE(rootFocusSpy.count(), 1);
- QCOMPARE(rootActiveFocusSpy.count(), 1);
- QCOMPARE(scope1FocusSpy.count(), 0);
- QCOMPARE(scope1ActiveFocusSpy.count(), 1);
- QCOMPARE(item1FocusSpy.count(), 0);
- QCOMPARE(item1ActiveFocusSpy.count(), 1);
-
-
- // view->hide(); // seemingly doesn't remove focus, so have an another view steal it.
- alternateView.show();
- alternateView.requestActivateWindow();
- QTest::qWaitForWindowShown(&alternateView);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &alternateView);
-
- QCOMPARE(rootItem->hasFocus(), false);
- QCOMPARE(rootItem->hasActiveFocus(), false);
- QCOMPARE(scope1->hasFocus(), true);
- QCOMPARE(scope1->hasActiveFocus(), false);
- QCOMPARE(item1->hasFocus(), true);
- QCOMPARE(item1->hasActiveFocus(), false);
-
- QCOMPARE(rootFocusSpy.count(), 2);
- QCOMPARE(rootActiveFocusSpy.count(), 2);
- QCOMPARE(scope1FocusSpy.count(), 0);
- QCOMPARE(scope1ActiveFocusSpy.count(), 2);
- QCOMPARE(item1FocusSpy.count(), 0);
- QCOMPARE(item1ActiveFocusSpy.count(), 2);
-
-
- // canvas does not have focus, so item2 will not get active focus
- item2->forceActiveFocus();
-
- QCOMPARE(rootItem->hasFocus(), false);
- QCOMPARE(rootItem->hasActiveFocus(), false);
- QCOMPARE(scope1->hasFocus(), false);
- QCOMPARE(scope1->hasActiveFocus(), false);
- QCOMPARE(item1->hasFocus(), true);
- QCOMPARE(item1->hasActiveFocus(), false);
- QCOMPARE(scope2->hasFocus(), true);
- QCOMPARE(scope2->hasActiveFocus(), false);
- QCOMPARE(item2->hasFocus(), true);
- QCOMPARE(item2->hasActiveFocus(), false);
-
- QCOMPARE(rootFocusSpy.count(), 2);
- QCOMPARE(rootActiveFocusSpy.count(), 2);
- QCOMPARE(scope1FocusSpy.count(), 1);
- QCOMPARE(scope1ActiveFocusSpy.count(), 2);
- QCOMPARE(item1FocusSpy.count(), 0);
- QCOMPARE(item1ActiveFocusSpy.count(), 2);
- QCOMPARE(scope2FocusSpy.count(), 1);
- QCOMPARE(scope2ActiveFocusSpy.count(), 0);
- QCOMPARE(item2FocusSpy.count(), 1);
- QCOMPARE(item2ActiveFocusSpy.count(), 0);
-
- // give the canvas focus, and item2 will get active focus
- view->show();
- view->requestActivateWindow();
- QTest::qWaitForWindowShown(view);
- QTRY_VERIFY(QGuiApplication::focusWindow() == view);
-
- QCOMPARE(rootItem->hasFocus(), true);
- QCOMPARE(rootItem->hasActiveFocus(), true);
- QCOMPARE(scope2->hasFocus(), true);
- QCOMPARE(scope2->hasActiveFocus(), true);
- QCOMPARE(item2->hasFocus(), true);
- QCOMPARE(item2->hasActiveFocus(), true);
- QCOMPARE(rootFocusSpy.count(), 3);
- QCOMPARE(rootActiveFocusSpy.count(), 3);
- QCOMPARE(scope2FocusSpy.count(), 1);
- QCOMPARE(scope2ActiveFocusSpy.count(), 1);
- QCOMPARE(item2FocusSpy.count(), 1);
- QCOMPARE(item2ActiveFocusSpy.count(), 1);
-
- delete view;
-}
-
-QTEST_MAIN(tst_qquickfocusscope)
-
-#include "tst_qquickfocusscope.moc"
diff --git a/tests/auto/declarative/qquickgridview/qquickgridview.pro b/tests/auto/declarative/qquickgridview/qquickgridview.pro
deleted file mode 100644
index c88b63a68e..0000000000
--- a/tests/auto/declarative/qquickgridview/qquickgridview.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickgridview
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickgridview.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-CONFIG += insignificant_test #QTBUG-22807
-QT += core-private gui-private v8-private declarative-private opengl-private testlib widgets
diff --git a/tests/auto/declarative/qquickgridview/tst_qquickgridview.cpp b/tests/auto/declarative/qquickgridview/tst_qquickgridview.cpp
deleted file mode 100644
index 503379ae42..0000000000
--- a/tests/auto/declarative/qquickgridview/tst_qquickgridview.cpp
+++ /dev/null
@@ -1,3705 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtWidgets/qstringlistmodel.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-#include <QtDeclarative/private/qquickitem_p.h>
-#include <QtDeclarative/private/qlistmodelinterface_p.h>
-#include <QtDeclarative/private/qquickgridview_p.h>
-#include <QtDeclarative/private/qquicktext_p.h>
-#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
-#include "../shared/util.h"
-#include <QtGui/qguiapplication.h>
-
-Q_DECLARE_METATYPE(Qt::LayoutDirection)
-Q_DECLARE_METATYPE(QQuickGridView::Flow)
-
-class tst_QQuickGridView : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickGridView();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void items();
- void changed();
- void inserted();
- void inserted_more();
- void inserted_more_data();
- void insertBeforeVisible();
- void insertBeforeVisible_data();
- void removed();
- void addOrRemoveBeforeVisible();
- void addOrRemoveBeforeVisible_data();
- void clear();
- void moved();
- void moved_data();
- void multipleChanges();
- void multipleChanges_data();
- void swapWithFirstItem();
- void changeFlow();
- void currentIndex();
- void noCurrentIndex();
- void defaultValues();
- void properties();
- void propertyChanges();
- void componentChanges();
- void modelChanges();
- void positionViewAtIndex();
- void positionViewAtIndex_rightToLeft();
- void mirroring();
- void snapping();
- void resetModel();
- void enforceRange();
- void enforceRange_rightToLeft();
- void QTBUG_8456();
- void manualHighlight();
- void footer();
- void footer_data();
- void header();
- void header_data();
- void resizeViewAndRepaint();
- void indexAt();
- void onAdd();
- void onAdd_data();
- void onRemove();
- void onRemove_data();
- void columnCount();
- void margins();
- void creationContext();
- void snapToRow_data();
- void snapToRow();
- void unaligned();
- void cacheBuffer();
- void asynchronous();
-
-private:
- QQuickView *createView();
- void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &id, int index=-1);
- template<typename T>
- QList<T*> findItems(QQuickItem *parent, const QString &objectName);
- void dumpTree(QQuickItem *parent, int depth = 0);
-};
-
-template<typename T>
-void tst_qquickgridview_move(int from, int to, int n, T *items)
-{
- if (n == 1) {
- items->move(from, to);
- } else {
- T replaced;
- int i=0;
- typename T::ConstIterator it=items->begin(); it += from+n;
- for (; i<to-from; ++i,++it)
- replaced.append(*it);
- i=0;
- it=items->begin(); it += from;
- for (; i<n; ++i,++it)
- replaced.append(*it);
- typename T::ConstIterator f=replaced.begin();
- typename T::Iterator t=items->begin(); t += from;
- for (; f != replaced.end(); ++f, ++t)
- *t = *f;
- }
-}
-
-void tst_QQuickGridView::initTestCase()
-{
-}
-
-void tst_QQuickGridView::cleanupTestCase()
-{
-
-}
-
-
-class TestModel : public QAbstractListModel
-{
-public:
- enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
-
- TestModel(QObject *parent=0) : QAbstractListModel(parent) {
- QHash<int, QByteArray> roles;
- roles[Name] = "name";
- roles[Number] = "number";
- setRoleNames(roles);
- }
-
- int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
- QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
- QVariant rv;
- if (role == Name)
- rv = list.at(index.row()).first;
- else if (role == Number)
- rv = list.at(index.row()).second;
-
- return rv;
- }
-
- int count() const { return rowCount(); }
- QString name(int index) const { return list.at(index).first; }
- QString number(int index) const { return list.at(index).second; }
-
- void addItem(const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), list.count(), list.count());
- list.append(QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void addItems(const QList<QPair<QString, QString> > &items) {
- emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
- for (int i=0; i<items.count(); i++)
- list.append(QPair<QString,QString>(items[i].first, items[i].second));
- emit endInsertRows();
- }
-
- void insertItem(int index, const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), index, index);
- list.insert(index, QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void insertItems(int index, const QList<QPair<QString, QString> > &items) {
- emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
- for (int i=0; i<items.count(); i++)
- list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
- emit endInsertRows();
- }
-
- void removeItem(int index) {
- emit beginRemoveRows(QModelIndex(), index, index);
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void removeItems(int index, int count) {
- emit beginRemoveRows(QModelIndex(), index, index+count-1);
- while (count--)
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void moveItem(int from, int to) {
- emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
- list.move(from, to);
- emit endMoveRows();
- }
-
- void moveItems(int from, int to, int count) {
- emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
- tst_qquickgridview_move(from, to, count, &list);
- emit endMoveRows();
- }
-
- void modifyItem(int idx, const QString &name, const QString &number) {
- list[idx] = QPair<QString,QString>(name, number);
- emit dataChanged(index(idx,0), index(idx,0));
- }
-
- void clear() {
- int count = list.count();
- emit beginRemoveRows(QModelIndex(), 0, count-1);
- list.clear();
- emit endRemoveRows();
- }
-
-
-private:
- QList<QPair<QString,QString> > list;
-};
-
-tst_QQuickGridView::tst_QQuickGridView()
-{
-}
-
-void tst_QQuickGridView::items()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Billy", "22345");
- model.addItem("Sam", "2945");
- model.addItem("Ben", "04321");
- model.addItem("Jim", "0780");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(gridview->count(), model.count());
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- for (int i = 0; i < model.count(); ++i) {
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- // set an empty model and confirm that items are destroyed
- TestModel model2;
- ctxt->setContextProperty("testModel", &model2);
-
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_VERIFY(itemCount == 0);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::changed()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Billy", "22345");
- model.addItem("Sam", "2945");
- model.addItem("Ben", "04321");
- model.addItem("Jim", "0780");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickFlickable *gridview = findItem<QQuickFlickable>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.modifyItem(1, "Will", "9876");
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- delete canvas;
-}
-
-void tst_QQuickGridView::inserted()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.insertItem(1, "Will", "9876");
-
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- // Checks that onAdd is called
- int added = canvas->rootObject()->property("added").toInt();
- QTRY_COMPARE(added, 1);
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count(); ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_COMPARE(item->x(), (i%3)*80.0);
- QTRY_COMPARE(item->y(), (i/3)*60.0);
- }
-
- model.insertItem(0, "Foo", "1111"); // zero index, and current item
-
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- QTRY_COMPARE(gridview->currentIndex(), 1);
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count(); ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- for (int i = model.count(); i < 30; ++i)
- model.insertItem(i, "Hello", QString::number(i));
-
- gridview->setContentY(120);
-
- // Insert item outside visible area
- model.insertItem(1, "Hello", "1324");
-
- QTRY_VERIFY(gridview->contentY() == 120);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::inserted_more()
-{
- QFETCH(qreal, contentY);
- QFETCH(int, insertIndex);
- QFETCH(int, insertCount);
- QFETCH(qreal, itemsOffsetAfterMove);
-
- QQuickText *name;
- QQuickText *number;
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- gridview->setContentY(contentY);
-
- QList<QPair<QString, QString> > newData;
- for (int i=0; i<insertCount; i++)
- newData << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.insertItems(insertIndex, newData);
- QTRY_COMPARE(gridview->property("count").toInt(), model.count());
-
- // check visibleItems.first() is in correct position
- QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item0);
- QCOMPARE(item0->y(), itemsOffsetAfterMove);
-
- QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
- int firstVisibleIndex = -1;
- for (int i=0; i<items.count(); i++) {
- if (items[i]->y() >= contentY) {
- QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
- firstVisibleIndex = e.evaluate().toInt();
- break;
- }
- }
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
-
- QCOMPARE(item->x(), (i%3)*80.0);
- QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
-
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QCOMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QCOMPARE(number->text(), model.number(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::inserted_more_data()
-{
- QTest::addColumn<qreal>("contentY");
- QTest::addColumn<int>("insertIndex");
- QTest::addColumn<int>("insertCount");
- QTest::addColumn<qreal>("itemsOffsetAfterMove");
-
- QTest::newRow("add 1, before visible items")
- << 120.0 // show 6-23
- << 5 << 1
- << 0.0; // insert 1 above first visible, grid is rearranged; first visible moves forward within its row
- // new 1st visible item is at 0
-
- QTest::newRow("add 2, before visible items")
- << 120.0 // show 6-23
- << 5 << 2
- << 0.0; // insert 2 above first visible, grid is rearranged; first visible moves forward within its row
-
- QTest::newRow("add 3, before visible items")
- << 120.0 // show 6-23
- << 5 << 3
- << -60.0; // insert 3 (1 row) above first visible in negative pos, first visible does not move
-
- QTest::newRow("add 5, before visible items")
- << 120.0 // show 6-23
- << 5 << 5
- << -60.0; // insert 1 row + 2 items above first visible, 1 row added at negative pos,
- // grid is rearranged and first visible moves forward within its row
-
- QTest::newRow("add 6, before visible items")
- << 120.0 // show 6-23
- << 5 << 6
- << -60.0 * 2; // insert 2 rows above first visible in negative pos, first visible does not move
-
-
-
- QTest::newRow("add 1, at start of visible, content at start")
- << 0.0
- << 0 << 1
- << 0.0;
-
- QTest::newRow("add multiple, at start of visible, content at start")
- << 0.0
- << 0 << 3
- << 0.0;
-
- QTest::newRow("add 1, at start of visible, content not at start")
- << 120.0 // show 6-23
- << 6 << 1
- << 0.0;
-
- QTest::newRow("add multiple, at start of visible, content not at start")
- << 120.0 // show 6-23
- << 6 << 3
- << 0.0;
-
-
- QTest::newRow("add 1, at end of visible, content at start")
- << 0.0
- << 17 << 1
- << 0.0;
-
- QTest::newRow("add 1, at end of visible, content at start")
- << 0.0
- << 17 << 3
- << 0.0;
-
- QTest::newRow("add 1, at end of visible, content not at start")
- << 120.0 // show 6-23
- << 23 << 1
- << 0.0;
-
- QTest::newRow("add multiple, at end of visible, content not at start")
- << 120.0 // show 6-23
- << 23 << 3
- << 0.0;
-
-
- QTest::newRow("add 1, after visible, content at start")
- << 0.0
- << 20 << 1
- << 0.0;
-
- QTest::newRow("add 1, after visible, content at start")
- << 0.0
- << 20 << 3
- << 0.0;
-
- QTest::newRow("add 1, after visible, content not at start")
- << 120.0 // show 6-23
- << 24 << 1
- << 0.0;
-
- QTest::newRow("add multiple, after visible, content not at start")
- << 120.0 // show 6-23
- << 24 << 3
- << 0.0;
-}
-
-void tst_QQuickGridView::insertBeforeVisible()
-{
- QFETCH(int, insertIndex);
- QFETCH(int, insertCount);
- QFETCH(int, cacheBuffer);
-
- QQuickText *name;
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- gridview->setCacheBuffer(cacheBuffer);
-
- // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
- int firstVisibleIndex = 20; // move to an index where the top item is not visible
- gridview->setContentY(firstVisibleIndex * 20.0);
- gridview->setCurrentIndex(firstVisibleIndex);
- qApp->processEvents();
- QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
- QVERIFY(item);
- QCOMPARE(item->y(), gridview->contentY());
-
- QList<QPair<QString, QString> > newData;
- for (int i=0; i<insertCount; i++)
- newData << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.insertItems(insertIndex, newData);
- QTRY_COMPARE(gridview->property("count").toInt(), model.count());
-
- // now, moving to the top of the view should position the inserted items correctly
- int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
- gridview->setCurrentIndex(0);
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- QCOMPARE(item->x(), (i%3)*80.0);
- QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::insertBeforeVisible_data()
-{
- QTest::addColumn<int>("insertIndex");
- QTest::addColumn<int>("insertCount");
- QTest::addColumn<int>("cacheBuffer");
-
- QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
- QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
- QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
-
- QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
- QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
- QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
-
- QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 6 << 0;
- QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 6 << 100;
- QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 6 << 500;
-
- QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 6 << 0;
- QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 6 << 100;
- QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 6 << 500;
-}
-
-void tst_QQuickGridView::removed()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.removeItem(1);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
-
- // Checks that onRemove is called
- QString removed = canvas->rootObject()->property("removed").toString();
- QTRY_COMPARE(removed, QString("Item1"));
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- // Remove first item (which is the current item);
- model.removeItem(0);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- // Remove items not visible
- model.removeItem(25);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- // Remove items before visible
- gridview->setContentY(120);
- gridview->setCurrentIndex(10);
-
- // Setting currentIndex above shouldn't cause view to scroll
- QTRY_COMPARE(gridview->contentY(), 120.0);
-
- model.removeItem(1);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- // Confirm items positioned correctly
- for (int i = 6; i < 18; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- // Remove currentIndex
- QQuickItem *oldCurrent = gridview->currentItem();
- model.removeItem(9);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QTRY_COMPARE(gridview->currentIndex(), 9);
- QTRY_VERIFY(gridview->currentItem() != oldCurrent);
-
- gridview->setContentY(0);
- // let transitions settle.
- QTest::qWait(300);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
-
- // remove item outside current view.
- gridview->setCurrentIndex(32);
- gridview->setContentY(240);
-
- model.removeItem(30);
- QTRY_VERIFY(gridview->currentIndex() == 31);
-
- // remove current item beyond visible items.
- gridview->setCurrentIndex(20);
- gridview->setContentY(0);
- model.removeItem(20);
-
- QTRY_COMPARE(gridview->currentIndex(), 20);
- QTRY_VERIFY(gridview->currentItem() != 0);
-
- // remove item before current, but visible
- gridview->setCurrentIndex(8);
- gridview->setContentY(240);
- oldCurrent = gridview->currentItem();
- model.removeItem(6);
-
- QTRY_COMPARE(gridview->currentIndex(), 7);
- QTRY_VERIFY(gridview->currentItem() == oldCurrent);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::addOrRemoveBeforeVisible()
-{
- // QTBUG-21588: ensure re-layout is done on grid after adding or removing
- // items from before the visible area
-
- QFETCH(bool, doAdd);
- QFETCH(qreal, newTopContentY);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_COMPARE(name->text(), QString("Item0"));
-
- gridview->setCurrentIndex(0);
- qApp->processEvents();
-
- // scroll down until item 0 is no longer drawn
- // (bug not triggered if we just move using content y, since that doesn't
- // refill and change the visible items)
- gridview->setCurrentIndex(24);
- qApp->processEvents();
-
- QTRY_COMPARE(gridview->currentIndex(), 24);
- QTRY_COMPARE(gridview->contentY(), 220.0);
-
- QTest::qWait(100); // wait for refill to complete
- QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0)); // 0 shouldn't be visible
-
- if (doAdd) {
- model.insertItem(0, "New Item", "New Item number");
- QTRY_COMPARE(gridview->count(), 31);
- } else {
- model.removeItem(0);
- QTRY_COMPARE(gridview->count(), 29);
- }
-
- // scroll back up and item 0 should be gone
- gridview->setCurrentIndex(0);
- qApp->processEvents();
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->contentY(), newTopContentY);
-
- name = findItem<QQuickText>(contentItem, "textName", 0);
- if (doAdd)
- QCOMPARE(name->text(), QString("New Item"));
- else
- QCOMPARE(name->text(), QString("Item1"));
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
-{
- QTest::addColumn<bool>("doAdd");
- QTest::addColumn<qreal>("newTopContentY");
-
- QTest::newRow("add") << true << -60.0;
- QTest::newRow("remove") << false << 0.0;
-}
-
-void tst_QQuickGridView::clear()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QVERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
-
- model.clear();
-
- QVERIFY(gridview->count() == 0);
- QVERIFY(gridview->currentItem() == 0);
- QVERIFY(gridview->contentY() == 0);
- QVERIFY(gridview->currentIndex() == -1);
-
- // confirm sanity when adding an item to cleared list
- model.addItem("New", "1");
- QTRY_COMPARE(gridview->count(), 1);
- QVERIFY(gridview->currentItem() != 0);
- QVERIFY(gridview->currentIndex() == 0);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::moved()
-{
- QFETCH(qreal, contentY);
- QFETCH(int, from);
- QFETCH(int, to);
- QFETCH(int, count);
- QFETCH(qreal, itemsOffsetAfterMove);
-
- QQuickText *name;
- QQuickText *number;
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickItem *currentItem = gridview->currentItem();
- QTRY_VERIFY(currentItem != 0);
-
- gridview->setContentY(contentY);
- model.moveItems(from, to, count);
-
- // wait for items to move
- QTest::qWait(300);
-
- // Confirm items positioned correctly and indexes correct
- int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
- if (i >= firstVisibleIndex + 18) // index has moved out of view
- continue;
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
-
- QTRY_COMPARE(item->x(), (i%3)*80.0);
- QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
-
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
-
- // current index should have been updated
- if (item == currentItem)
- QTRY_COMPARE(gridview->currentIndex(), i);
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::moved_data()
-{
- QTest::addColumn<qreal>("contentY");
- QTest::addColumn<int>("from");
- QTest::addColumn<int>("to");
- QTest::addColumn<int>("count");
- QTest::addColumn<qreal>("itemsOffsetAfterMove");
-
- // model starts with 30 items, each 80x60, in area 240x320
- // 18 items should be visible at a time
-
- QTest::newRow("move 1 forwards, within visible items")
- << 0.0
- << 1 << 8 << 1
- << 0.0;
-
- QTest::newRow("move 1 forwards, from non-visible -> visible")
- << 120.0 // show 6-23
- << 1 << 23 << 1
- << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
-
- QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
- << 120.0 // // show 6-23
- << 0 << 6 << 1
- << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
-
- QTest::newRow("move 1 forwards, from visible -> non-visible")
- << 0.0
- << 1 << 20 << 1
- << 0.0;
-
- QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
- << 0.0
- << 0 << 20 << 1
- << 0.0;
-
-
- QTest::newRow("move 1 backwards, within visible items")
- << 0.0
- << 10 << 5 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, within visible items (to first index)")
- << 0.0
- << 10 << 0 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from non-visible -> visible")
- << 0.0
- << 28 << 8 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
- << 0.0
- << 29 << 14 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from visible -> non-visible")
- << 120.0 // show 6-23
- << 7 << 1 << 1
- << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
-
- QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
- << 120.0 // show 6-23
- << 7 << 0 << 1
- << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
-
-
- QTest::newRow("move multiple forwards, within visible items")
- << 0.0
- << 0 << 5 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, within visible items (move first item)")
- << 0.0
- << 10 << 0 << 3
- << 0.0;
-
- QTest::newRow("move multiple forwards, before visible items")
- << 120.0 // show 6-23
- << 3 << 4 << 3 // 3, 4, 5 move to after 6
- << 60.0; // row of 3,4,5 has moved down
-
- QTest::newRow("move multiple forwards, from non-visible -> visible")
- << 120.0 // show 6-23
- << 1 << 6 << 3
- << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
-
- QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
- << 120.0 // show 6-23
- << 0 << 6 << 3
- << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
-
- QTest::newRow("move multiple forwards, from visible -> non-visible")
- << 0.0
- << 1 << 16 << 3
- << 0.0;
-
- QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
- << 0.0
- << 0 << 16 << 3
- << 0.0;
-
-
- QTest::newRow("move multiple backwards, within visible items")
- << 0.0
- << 4 << 1 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from non-visible -> visible")
- << 0.0
- << 20 << 4 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
- << 0.0
- << 27 << 10 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from visible -> non-visible")
- << 120.0 // show 6-23
- << 16 << 1 << 3
- << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
-
- QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
- << 120.0 // show 6-23
- << 16 << 0 << 3
- << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
-}
-
-struct ListChange {
- enum { Inserted, Removed, Moved, SetCurrent } type;
- int index;
- int count;
- int to; // Move
-
- static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
- static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
- static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
- static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
-};
-Q_DECLARE_METATYPE(QList<ListChange>)
-
-void tst_QQuickGridView::multipleChanges()
-{
- QFETCH(int, startCount);
- QFETCH(QList<ListChange>, changes);
- QFETCH(int, newCount);
- QFETCH(int, newCurrentIndex);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < startCount; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- for (int i=0; i<changes.count(); i++) {
- switch (changes[i].type) {
- case ListChange::Inserted:
- {
- QList<QPair<QString, QString> > items;
- for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
- items << qMakePair(QString("new item " + j), QString::number(j));
- model.insertItems(changes[i].index, items);
- break;
- }
- case ListChange::Removed:
- model.removeItems(changes[i].index, changes[i].count);
- break;
- case ListChange::Moved:
- model.moveItems(changes[i].index, changes[i].to, changes[i].count);
- break;
- case ListChange::SetCurrent:
- gridview->setCurrentIndex(changes[i].index);
- break;
- }
- }
-
- QTRY_COMPARE(gridview->count(), newCount);
- QCOMPARE(gridview->count(), model.count());
- QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
-
- QQuickText *name;
- QQuickText *number;
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i=0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::multipleChanges_data()
-{
- QTest::addColumn<int>("startCount");
- QTest::addColumn<QList<ListChange> >("changes");
- QTest::addColumn<int>("newCount");
- QTest::addColumn<int>("newCurrentIndex");
-
- QList<ListChange> changes;
-
- for (int i=1; i<30; i++)
- changes << ListChange::remove(0);
- QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
-
- changes << ListChange::remove(0);
- QTest::newRow("remove all") << 30 << changes << 0 << -1;
-
- changes.clear();
- changes << ListChange::setCurrent(29);
- for (int i=29; i>0; i--)
- changes << ListChange::remove(i);
- QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
-
- QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
- << ListChange::remove(0, 1)
- << ListChange::insert(0, 1)
- ) << 10 << 1;
-
- QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::remove(2, 1)
- << ListChange::insert(2, 1)
- ) << 10 << 3;
-
- QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::remove(1, 3)
- << ListChange::insert(2, 2)
- ) << 9 << 1;
-
- QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::remove(1, 3)
- << ListChange::move(1, 5, 1)
- ) << 7 << 5;
-
- QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::remove(4, 3)
- << ListChange::move(4, 1, 1)
- ) << 7 << 1;
-
-
- QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 2)
- << ListChange::insert(0, 4)
- << ListChange::insert(0, 6)
- ) << 12 << 10;
-
- QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 2)
- << ListChange::insert(0, 4)
- << ListChange::insert(0, 6)
- << ListChange::setCurrent(3)
- << ListChange::insert(3, 2)
- ) << 14 << 5;
-
- QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 30)
- << ListChange::remove(0, 30)
- ) << 0 << -1;
-
- QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
- << ListChange::insert(1)
- << ListChange::setCurrent(1)
- << ListChange::remove(1)
- ) << 30 << 1;
-
- QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 10)
- << ListChange::remove(5, 10)
- ) << 10 << 5;
-
- QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 3)
- << ListChange::move(0, 10, 3)
- ) << 13 << 0;
-
- QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 3)
- << ListChange::move(0, 8, 5)
- ) << 13 << 11;
-
- QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(9)
- << ListChange::insert(10, 3)
- << ListChange::move(8, 0, 5)
- ) << 13 << 1;
-
-
- QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::move(1, 2, 2)
- << ListChange::move(2, 1, 2)
- ) << 10 << 1;
-
- QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::move(1, 2, 3)
- << ListChange::move(3, 0, 5)
- ) << 10 << 0;
-
- QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 0, 1)
- << ListChange::remove(0)
- ) << 9 << 0;
-
- QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 0, 1)
- << ListChange::insert(0)
- ) << 11 << 1;
-
- QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::move(5, 1, 3)
- << ListChange::remove(1, 3)
- ) << 7 << 1;
-
- QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 1, 3)
- << ListChange::insert(1, 5)
- ) << 15 << 6;
-
- QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(3)
- << ListChange::move(0, 1, 2)
- << ListChange::insert(3, 5)
- ) << 15 << 8;
-
-
- QTest::newRow("clear current") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 5)
- << ListChange::setCurrent(-1)
- << ListChange::remove(0, 5)
- << ListChange::insert(0, 5)
- ) << 5 << -1;
-}
-
-
-void tst_QQuickGridView::swapWithFirstItem()
-{
- // QTBUG_9697
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- // ensure content position is stable
- gridview->setContentY(0);
- model.moveItem(10, 0);
- QTRY_VERIFY(gridview->contentY() == 0);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::currentIndex()
-{
- TestModel model;
- for (int i = 0; i < 60; i++)
- model.addItem("Item" + QString::number(i), QString::number(i));
-
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
- canvas->show();
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- QString filename(TESTDATA("gridview-initCurrent.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QVERIFY(gridview != 0);
- QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
-
- // current item should be third item
- QCOMPARE(gridview->currentIndex(), 35);
- QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
- QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
- QCOMPARE(gridview->contentY(), 400.0);
-
- gridview->moveCurrentIndexRight();
- QCOMPARE(gridview->currentIndex(), 36);
- gridview->moveCurrentIndexDown();
- QCOMPARE(gridview->currentIndex(), 39);
- gridview->moveCurrentIndexUp();
- QCOMPARE(gridview->currentIndex(), 36);
- gridview->moveCurrentIndexLeft();
- QCOMPARE(gridview->currentIndex(), 35);
-
- // wait until motion stops
- QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
-
- // no wrap
- gridview->setCurrentIndex(0);
- QCOMPARE(gridview->currentIndex(), 0);
- // confirm that the velocity is updated
- QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
-
- gridview->moveCurrentIndexUp();
- QCOMPARE(gridview->currentIndex(), 0);
-
- gridview->moveCurrentIndexLeft();
- QCOMPARE(gridview->currentIndex(), 0);
-
- gridview->setCurrentIndex(model.count()-1);
- QCOMPARE(gridview->currentIndex(), model.count()-1);
-
- gridview->moveCurrentIndexRight();
- QCOMPARE(gridview->currentIndex(), model.count()-1);
-
- gridview->moveCurrentIndexDown();
- QCOMPARE(gridview->currentIndex(), model.count()-1);
-
- // with wrap
- gridview->setWrapEnabled(true);
-
- gridview->setCurrentIndex(0);
- QCOMPARE(gridview->currentIndex(), 0);
-
- gridview->moveCurrentIndexLeft();
- QCOMPARE(gridview->currentIndex(), model.count()-1);
-
- qApp->processEvents();
- QTRY_COMPARE(gridview->contentY(), 880.0);
-
- gridview->moveCurrentIndexRight();
- QCOMPARE(gridview->currentIndex(), 0);
-
- QTRY_COMPARE(gridview->contentY(), 0.0);
-
-
- // footer should become visible if it is out of view, and then current index moves to the first row
- canvas->rootObject()->setProperty("showFooter", true);
- QTRY_VERIFY(gridview->footerItem());
- gridview->setCurrentIndex(model.count()-3);
- QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
- gridview->setCurrentIndex(model.count()-2);
- QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
- canvas->rootObject()->setProperty("showFooter", false);
-
- // header should become visible if it is out of view, and then current index moves to the last row
- canvas->rootObject()->setProperty("showHeader", true);
- QTRY_VERIFY(gridview->headerItem());
- gridview->setCurrentIndex(3);
- QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
- gridview->setCurrentIndex(1);
- QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
- canvas->rootObject()->setProperty("showHeader", false);
-
-
- // Test keys
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
-
- gridview->setCurrentIndex(0);
-
- QTest::keyClick(canvas, Qt::Key_Down);
- QCOMPARE(gridview->currentIndex(), 3);
-
- QTest::keyClick(canvas, Qt::Key_Up);
- QCOMPARE(gridview->currentIndex(), 0);
-
- // hold down Key_Down
- for (int i=0; i<(model.count() / 3) - 1; i++) {
- QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
- QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
- }
- QTest::keyRelease(canvas, Qt::Key_Down);
- QTRY_COMPARE(gridview->currentIndex(), 57);
- QTRY_COMPARE(gridview->contentY(), 880.0);
-
- // hold down Key_Up
- for (int i=(model.count() / 3) - 1; i > 0; i--) {
- QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
- QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
- }
- QTest::keyRelease(canvas, Qt::Key_Up);
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->contentY(), 0.0);
-
-
- gridview->setFlow(QQuickGridView::TopToBottom);
-
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QVERIFY(qGuiApp->focusWindow() == canvas);
- qApp->processEvents();
-
- QTest::keyClick(canvas, Qt::Key_Right);
- QCOMPARE(gridview->currentIndex(), 5);
-
- QTest::keyClick(canvas, Qt::Key_Left);
- QCOMPARE(gridview->currentIndex(), 0);
-
- QTest::keyClick(canvas, Qt::Key_Down);
- QCOMPARE(gridview->currentIndex(), 1);
-
- QTest::keyClick(canvas, Qt::Key_Up);
- QCOMPARE(gridview->currentIndex(), 0);
-
- // hold down Key_Right
- for (int i=0; i<(model.count() / 5) - 1; i++) {
- QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
- QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
- }
-
- QTest::keyRelease(canvas, Qt::Key_Right);
- QTRY_COMPARE(gridview->currentIndex(), 55);
- QTRY_COMPARE(gridview->contentX(), 720.0);
-
- // hold down Key_Left
- for (int i=(model.count() / 5) - 1; i > 0; i--) {
- QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
- QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
- }
- QTest::keyRelease(canvas, Qt::Key_Left);
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->contentX(), 0.0);
-
-
- // turn off auto highlight
- gridview->setHighlightFollowsCurrentItem(false);
- QVERIFY(gridview->highlightFollowsCurrentItem() == false);
- QVERIFY(gridview->highlightItem());
- qreal hlPosX = gridview->highlightItem()->x();
- qreal hlPosY = gridview->highlightItem()->y();
-
- gridview->setCurrentIndex(5);
- QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
- QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
-
- // insert item before currentIndex
- gridview->setCurrentIndex(28);
- model.insertItem(0, "Foo", "1111");
- QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
-
- // check removing highlight by setting currentIndex to -1;
- gridview->setCurrentIndex(-1);
-
- QCOMPARE(gridview->currentIndex(), -1);
- QVERIFY(!gridview->highlightItem());
- QVERIFY(!gridview->currentItem());
-
- gridview->setHighlightFollowsCurrentItem(true);
-
- gridview->setFlow(QQuickGridView::LeftToRight);
- gridview->setLayoutDirection(Qt::RightToLeft);
-
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
- qApp->processEvents();
-
- gridview->setCurrentIndex(35);
-
- QTest::keyClick(canvas, Qt::Key_Right);
- QCOMPARE(gridview->currentIndex(), 34);
-
- QTest::keyClick(canvas, Qt::Key_Down);
- QCOMPARE(gridview->currentIndex(), 37);
-
- QTest::keyClick(canvas, Qt::Key_Up);
- QCOMPARE(gridview->currentIndex(), 34);
-
- QTest::keyClick(canvas, Qt::Key_Left);
- QCOMPARE(gridview->currentIndex(), 35);
-
-
- // turn off auto highlight
- gridview->setHighlightFollowsCurrentItem(false);
- QVERIFY(gridview->highlightFollowsCurrentItem() == false);
- QVERIFY(gridview->highlightItem());
- hlPosX = gridview->highlightItem()->x();
- hlPosY = gridview->highlightItem()->y();
-
- gridview->setCurrentIndex(5);
- QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
- QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
-
- // insert item before currentIndex
- gridview->setCurrentIndex(28);
- model.insertItem(0, "Foo", "1111");
- QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
-
- // check removing highlight by setting currentIndex to -1;
- gridview->setCurrentIndex(-1);
-
- QCOMPARE(gridview->currentIndex(), -1);
- QVERIFY(!gridview->highlightItem());
- QVERIFY(!gridview->currentItem());
-
- delete canvas;
-}
-
-void tst_QQuickGridView::noCurrentIndex()
-{
- TestModel model;
- for (int i = 0; i < 60; i++)
- model.addItem("Item" + QString::number(i), QString::number(i));
-
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- QString filename(TESTDATA("gridview-noCurrent.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QVERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
-
- // current index should be -1
- QCOMPARE(gridview->currentIndex(), -1);
- QVERIFY(!gridview->currentItem());
- QVERIFY(!gridview->highlightItem());
- QCOMPARE(gridview->contentY(), 0.0);
-
- gridview->setCurrentIndex(5);
- QCOMPARE(gridview->currentIndex(), 5);
- QVERIFY(gridview->currentItem());
- QVERIFY(gridview->highlightItem());
-
- delete canvas;
-}
-
-void tst_QQuickGridView::changeFlow()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i));
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal((i%3)*80));
- QTRY_COMPARE(item->y(), qreal((i/3)*60));
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- ctxt->setContextProperty("testTopToBottom", QVariant(true));
-
- // Confirm items positioned correctly and indexes correct
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal((i/5)*80));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- ctxt->setContextProperty("testRightToLeft", QVariant(true));
-
- // Confirm items positioned correctly and indexes correct
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
- gridview->setContentX(100);
- QTRY_COMPARE(gridview->contentX(), 100.);
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
- QTRY_COMPARE(gridview->contentX(), 0.);
-
- // Confirm items positioned correctly and indexes correct
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
- QTRY_COMPARE(item->y(), qreal((i/3)*60));
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::defaultValues()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview3.qml")));
- QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
-
- QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->model() == QVariant());
- QTRY_VERIFY(obj->delegate() == 0);
- QTRY_COMPARE(obj->currentIndex(), -1);
- QTRY_VERIFY(obj->currentItem() == 0);
- QTRY_COMPARE(obj->count(), 0);
- QTRY_VERIFY(obj->highlight() == 0);
- QTRY_VERIFY(obj->highlightItem() == 0);
- QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
- QTRY_VERIFY(obj->flow() == 0);
- QTRY_COMPARE(obj->isWrapEnabled(), false);
- QTRY_COMPARE(obj->cacheBuffer(), 0);
- QTRY_COMPARE(obj->cellWidth(), qreal(100)); //### Should 100 be the default?
- QTRY_COMPARE(obj->cellHeight(), qreal(100));
- delete obj;
-}
-
-void tst_QQuickGridView::properties()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview2.qml")));
- QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
-
- QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->model() != QVariant());
- QTRY_VERIFY(obj->delegate() != 0);
- QTRY_COMPARE(obj->currentIndex(), 0);
- QTRY_VERIFY(obj->currentItem() != 0);
- QTRY_COMPARE(obj->count(), 4);
- QTRY_VERIFY(obj->highlight() != 0);
- QTRY_VERIFY(obj->highlightItem() != 0);
- QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
- QTRY_VERIFY(obj->flow() == 0);
- QTRY_COMPARE(obj->isWrapEnabled(), true);
- QTRY_COMPARE(obj->cacheBuffer(), 200);
- QTRY_COMPARE(obj->cellWidth(), qreal(100));
- QTRY_COMPARE(obj->cellHeight(), qreal(100));
- delete obj;
-}
-
-void tst_QQuickGridView::propertyChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
- QTRY_VERIFY(gridView);
-
- QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
- QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
- QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
- QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
-
- QTRY_COMPARE(gridView->isWrapEnabled(), true);
- QTRY_COMPARE(gridView->cacheBuffer(), 10);
- QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
-
- gridView->setWrapEnabled(false);
- gridView->setCacheBuffer(3);
- gridView->setFlow(QQuickGridView::TopToBottom);
-
- QTRY_COMPARE(gridView->isWrapEnabled(), false);
- QTRY_COMPARE(gridView->cacheBuffer(), 3);
- QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
-
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
- QTRY_COMPARE(cacheBufferSpy.count(),1);
- QTRY_COMPARE(flowSpy.count(),1);
-
- gridView->setWrapEnabled(false);
- gridView->setCacheBuffer(3);
- gridView->setFlow(QQuickGridView::TopToBottom);
-
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
- QTRY_COMPARE(cacheBufferSpy.count(),1);
- QTRY_COMPARE(flowSpy.count(),1);
-
- gridView->setFlow(QQuickGridView::LeftToRight);
- QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
-
- gridView->setWrapEnabled(true);
- gridView->setCacheBuffer(5);
- gridView->setLayoutDirection(Qt::RightToLeft);
-
- QTRY_COMPARE(gridView->isWrapEnabled(), true);
- QTRY_COMPARE(gridView->cacheBuffer(), 5);
- QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
-
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
- QTRY_COMPARE(cacheBufferSpy.count(),2);
- QTRY_COMPARE(layoutSpy.count(),1);
- QTRY_COMPARE(flowSpy.count(),2);
-
- gridView->setWrapEnabled(true);
- gridView->setCacheBuffer(5);
- gridView->setLayoutDirection(Qt::RightToLeft);
-
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
- QTRY_COMPARE(cacheBufferSpy.count(),2);
- QTRY_COMPARE(layoutSpy.count(),1);
- QTRY_COMPARE(flowSpy.count(),2);
-
- gridView->setFlow(QQuickGridView::TopToBottom);
- QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
- QTRY_COMPARE(flowSpy.count(),3);
-
- gridView->setFlow(QQuickGridView::TopToBottom);
- QTRY_COMPARE(flowSpy.count(),3);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::componentChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
- QTRY_VERIFY(gridView);
-
- QDeclarativeComponent component(canvas->engine());
- component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
-
- QDeclarativeComponent delegateComponent(canvas->engine());
- delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
-
- QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
- QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
- QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
- QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
-
- gridView->setHighlight(&component);
- gridView->setDelegate(&delegateComponent);
- gridView->setHeader(&component);
- gridView->setFooter(&component);
-
- QTRY_COMPARE(gridView->highlight(), &component);
- QTRY_COMPARE(gridView->delegate(), &delegateComponent);
- QTRY_COMPARE(gridView->header(), &component);
- QTRY_COMPARE(gridView->footer(), &component);
-
- QTRY_COMPARE(highlightSpy.count(),1);
- QTRY_COMPARE(delegateSpy.count(),1);
- QTRY_COMPARE(headerSpy.count(),1);
- QTRY_COMPARE(footerSpy.count(),1);
-
- gridView->setHighlight(&component);
- gridView->setDelegate(&delegateComponent);
- gridView->setHeader(&component);
- gridView->setFooter(&component);
-
- QTRY_COMPARE(highlightSpy.count(),1);
- QTRY_COMPARE(delegateSpy.count(),1);
- QTRY_COMPARE(headerSpy.count(),1);
- QTRY_COMPARE(footerSpy.count(),1);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::modelChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
- QTRY_VERIFY(gridView);
-
- QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
- QTRY_VERIFY(alternateModel);
- QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
- QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
-
- gridView->setModel(modelVariant);
- QTRY_COMPARE(gridView->model(), modelVariant);
- QTRY_COMPARE(modelSpy.count(),1);
-
- gridView->setModel(modelVariant);
- QTRY_COMPARE(modelSpy.count(),1);
-
- gridView->setModel(QVariant());
- QTRY_COMPARE(modelSpy.count(),2);
- delete canvas;
-}
-
-void tst_QQuickGridView::positionViewAtIndex()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.);
- QTRY_COMPARE(item->y(), (i/3)*60.);
- }
-
- // Position on a currently visible item
- gridview->positionViewAtIndex(4, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->indexAt(120, 90), 4);
- QTRY_COMPARE(gridview->contentY(), 60.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.);
- QTRY_COMPARE(item->y(), (i/3)*60.);
- }
-
- // Position on an item beyond the visible items
- gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->indexAt(40, 450), 21);
- QTRY_COMPARE(gridview->contentY(), 420.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.);
- QTRY_COMPARE(item->y(), (i/3)*60.);
- }
-
- // Position on an item that would leave empty space if positioned at the top
- gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->indexAt(120, 630), 31);
- QTRY_COMPARE(gridview->contentY(), 520.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.);
- QTRY_COMPARE(item->y(), (i/3)*60.);
- }
-
- // Position at the beginning again
- gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->indexAt(0, 0), 0);
- QTRY_COMPARE(gridview->indexAt(40, 30), 0);
- QTRY_COMPARE(gridview->indexAt(80, 60), 4);
- QTRY_COMPARE(gridview->contentY(), 0.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.);
- QTRY_COMPARE(item->y(), (i/3)*60.);
- }
-
- // Position at End
- gridview->positionViewAtIndex(30, QQuickGridView::End);
- QTRY_COMPARE(gridview->contentY(), 340.);
-
- // Position in Center
- gridview->positionViewAtIndex(15, QQuickGridView::Center);
- QTRY_COMPARE(gridview->contentY(), 170.);
-
- // Ensure at least partially visible
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentY(), 170.);
-
- gridview->setContentY(302);
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentY(), 302.);
-
- gridview->setContentY(360);
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentY(), 300.);
-
- gridview->setContentY(60);
- gridview->positionViewAtIndex(20, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentY(), 60.);
-
- gridview->setContentY(20);
- gridview->positionViewAtIndex(20, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentY(), 100.);
-
- // Ensure completely visible
- gridview->setContentY(120);
- gridview->positionViewAtIndex(20, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentY(), 120.);
-
- gridview->setContentY(302);
- gridview->positionViewAtIndex(15, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentY(), 300.);
-
- gridview->setContentY(60);
- gridview->positionViewAtIndex(20, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentY(), 100.);
-
- // Test for Top To Bottom layout
- ctxt->setContextProperty("testTopToBottom", QVariant(true));
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), (i/5)*80.);
- QTRY_COMPARE(item->y(), (i%5)*60.);
- }
-
- // Position at End
- gridview->positionViewAtIndex(30, QQuickGridView::End);
- QTRY_COMPARE(gridview->contentX(), 320.);
- QTRY_COMPARE(gridview->contentY(), 0.);
-
- // Position in Center
- gridview->positionViewAtIndex(15, QQuickGridView::Center);
- QTRY_COMPARE(gridview->contentX(), 160.);
-
- // Ensure at least partially visible
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), 160.);
-
- gridview->setContentX(170);
- gridview->positionViewAtIndex(25, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), 170.);
-
- gridview->positionViewAtIndex(30, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), 320.);
-
- gridview->setContentX(170);
- gridview->positionViewAtIndex(25, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentX(), 240.);
-
- // positionViewAtBeginning
- gridview->positionViewAtBeginning();
- QTRY_COMPARE(gridview->contentX(), 0.);
-
- gridview->setContentX(80);
- canvas->rootObject()->setProperty("showHeader", true);
- gridview->positionViewAtBeginning();
- QTRY_COMPARE(gridview->contentX(), -30.);
-
- // positionViewAtEnd
- gridview->positionViewAtEnd();
- QTRY_COMPARE(gridview->contentX(), 400.); // 8*80 - 240 (8 columns)
-
- gridview->setContentX(80);
- canvas->rootObject()->setProperty("showFooter", true);
- gridview->positionViewAtEnd();
- QTRY_COMPARE(gridview->contentX(), 430.);
-
- // set current item to outside visible view, position at beginning
- // and ensure highlight moves to current item
- gridview->setCurrentIndex(6);
- gridview->positionViewAtBeginning();
- QTRY_COMPARE(gridview->contentX(), -30.);
- QVERIFY(gridview->highlightItem());
- QCOMPARE(gridview->highlightItem()->x(), 80.);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::snapping()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- gridview->setHeight(220);
- QCOMPARE(gridview->height(), 220.);
-
- gridview->positionViewAtIndex(12, QQuickGridView::Visible);
- QCOMPARE(gridview->contentY(), 80.);
-
- gridview->setContentY(0);
- QCOMPARE(gridview->contentY(), 0.);
-
- gridview->setSnapMode(QQuickGridView::SnapToRow);
- QCOMPARE(gridview->snapMode(), QQuickGridView::SnapToRow);
-
- gridview->positionViewAtIndex(12, QQuickGridView::Visible);
- QCOMPARE(gridview->contentY(), 60.);
-
- gridview->positionViewAtIndex(15, QQuickGridView::End);
- QCOMPARE(gridview->contentY(), 120.);
-
- delete canvas;
-
-}
-
-void tst_QQuickGridView::mirroring()
-{
- QQuickView *canvasA = createView();
- canvasA->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
- QQuickGridView *gridviewA = findItem<QQuickGridView>(canvasA->rootObject(), "view");
- QTRY_VERIFY(gridviewA != 0);
-
- QQuickView *canvasB = createView();
- canvasB->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
- QQuickGridView *gridviewB = findItem<QQuickGridView>(canvasB->rootObject(), "view");
- QTRY_VERIFY(gridviewA != 0);
- qApp->processEvents();
-
- QList<QString> objectNames;
- objectNames << "item1" << "item2"; // << "item3"
-
- gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
- gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
- QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
-
- // LTR != RTL
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
-
- gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
- gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
-
- // LTR == LTR
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
-
- QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
- QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
- QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
-
- // LTR != LTR+mirror
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
-
- gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
-
- // RTL == LTR+mirror
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
-
- gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
-
- // RTL != RTL+mirror
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
-
- gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
-
- // LTR == RTL+mirror
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
-
- delete canvasA;
- delete canvasB;
-}
-
-void tst_QQuickGridView::positionViewAtIndex_rightToLeft()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testTopToBottom", QVariant(true));
- ctxt->setContextProperty("testRightToLeft", QVariant(true));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- }
-
- // Position on a currently visible item
- gridview->positionViewAtIndex(6, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->contentX(), -320.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- }
-
- // Position on an item beyond the visible items
- gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->contentX(), -560.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- }
-
- // Position on an item that would leave empty space if positioned at the top
- gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->contentX(), -640.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- }
-
- // Position at the beginning again
- gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
- QTRY_COMPARE(gridview->contentX(), -240.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
- QTRY_COMPARE(item->y(), qreal((i%5)*60));
- }
-
- // Position at End
- gridview->positionViewAtIndex(30, QQuickGridView::End);
- QTRY_COMPARE(gridview->contentX(), -560.);
-
- // Position in Center
- gridview->positionViewAtIndex(15, QQuickGridView::Center);
- QTRY_COMPARE(gridview->contentX(), -400.);
-
- // Ensure at least partially visible
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), -400.);
-
- gridview->setContentX(-555.);
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), -555.);
-
- gridview->setContentX(-239);
- gridview->positionViewAtIndex(15, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), -320.);
-
- gridview->setContentX(-239);
- gridview->positionViewAtIndex(20, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), -400.);
-
- gridview->setContentX(-640);
- gridview->positionViewAtIndex(20, QQuickGridView::Visible);
- QTRY_COMPARE(gridview->contentX(), -560.);
-
- // Ensure completely visible
- gridview->setContentX(-400);
- gridview->positionViewAtIndex(20, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentX(), -400.);
-
- gridview->setContentX(-315);
- gridview->positionViewAtIndex(15, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentX(), -320.);
-
- gridview->setContentX(-640);
- gridview->positionViewAtIndex(20, QQuickGridView::Contain);
- QTRY_COMPARE(gridview->contentX(), -560.);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::resetModel()
-{
- QQuickView *canvas = createView();
-
- QStringList strings;
- strings << "one" << "two" << "three";
- QStringListModel model(strings);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaygrid.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(gridview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
- QTRY_COMPARE(display->text(), strings.at(i));
- }
-
- strings.clear();
- strings << "four" << "five" << "six" << "seven";
- model.setStringList(strings);
-
- QTRY_COMPARE(gridview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
- QTRY_COMPARE(display->text(), strings.at(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::enforceRange()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
- qApp->processEvents();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
- QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
- QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // view should be positioned at the top of the range.
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QTRY_VERIFY(item);
- QTRY_COMPARE(gridview->contentY(), -100.0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- // Check currentIndex is updated when contentItem moves
- gridview->setContentY(0);
- QTRY_COMPARE(gridview->currentIndex(), 2);
-
- gridview->setCurrentIndex(5);
- QTRY_COMPARE(gridview->contentY(), 100.);
-
- TestModel model2;
- for (int i = 0; i < 5; i++)
- model2.addItem("Item" + QString::number(i), "");
-
- ctxt->setContextProperty("testModel", &model2);
- QCOMPARE(gridview->count(), 5);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::enforceRange_rightToLeft()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(true));
- ctxt->setContextProperty("testTopToBottom", QVariant(true));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
- qApp->processEvents();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
- QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
- QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
-
- // view should be positioned at the top of the range.
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QTRY_COMPARE(gridview->contentX(), -140.);
- QTRY_COMPARE(gridview->contentY(), 0.0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- // Check currentIndex is updated when contentItem moves
- gridview->setContentX(-240);
- QTRY_COMPARE(gridview->currentIndex(), 3);
-
- gridview->setCurrentIndex(7);
- QTRY_COMPARE(gridview->contentX(), -340.);
- QTRY_COMPARE(gridview->contentY(), 0.0);
-
- TestModel model2;
- for (int i = 0; i < 5; i++)
- model2.addItem("Item" + QString::number(i), "");
-
- ctxt->setContextProperty("testModel", &model2);
- QCOMPARE(gridview->count(), 5);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::QTBUG_8456()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("setindex.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QTRY_COMPARE(gridview->currentIndex(), 0);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::manualHighlight()
-{
- QQuickView *canvas = createView();
-
- QString filename(TESTDATA("manual-highlight.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
- QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
- QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
-
- gridview->setCurrentIndex(2);
-
- QTRY_COMPARE(gridview->currentIndex(), 2);
- QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
- QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
- QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
-
- gridview->positionViewAtIndex(8, QQuickGridView::Contain);
-
- QTRY_COMPARE(gridview->currentIndex(), 2);
- QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
- QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
- QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
-
- gridview->setFlow(QQuickGridView::TopToBottom);
- QTRY_COMPARE(gridview->flow(), QQuickGridView::TopToBottom);
-
- gridview->setCurrentIndex(0);
- QTRY_COMPARE(gridview->currentIndex(), 0);
- QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
- QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
- QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
-
- delete canvas;
-}
-
-
-void tst_QQuickGridView::footer()
-{
- QFETCH(QQuickGridView::Flow, flow);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(QPointF, initialFooterPos);
- QFETCH(QPointF, changedFooterPos);
- QFETCH(QPointF, initialContentPos);
- QFETCH(QPointF, changedContentPos);
- QFETCH(QPointF, firstDelegatePos);
- QFETCH(QPointF, resizeContentPos);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 7; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("footer.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- gridview->setFlow(flow);
- gridview->setLayoutDirection(layoutDirection);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
- QVERIFY(footer);
-
- QVERIFY(footer == gridview->footerItem());
-
- QCOMPARE(footer->pos(), initialFooterPos);
- QCOMPARE(footer->width(), 100.);
- QCOMPARE(footer->height(), 30.);
- QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- if (flow == QQuickGridView::LeftToRight) {
- // shrink by one row
- model.removeItem(2);
- QTRY_COMPARE(footer->y(), initialFooterPos.y() - gridview->cellHeight());
- } else {
- // shrink by one column
- model.removeItem(2);
- model.removeItem(3);
- if (layoutDirection == Qt::LeftToRight)
- QTRY_COMPARE(footer->x(), initialFooterPos.x() - gridview->cellWidth());
- else
- QTRY_COMPARE(footer->x(), initialFooterPos.x() + gridview->cellWidth());
- }
-
- // remove all items
- model.clear();
-
- QPointF posWhenNoItems(0, 0);
- if (layoutDirection == Qt::RightToLeft)
- posWhenNoItems.setX(flow == QQuickGridView::LeftToRight ? gridview->width() - footer->width() : -footer->width());
- QTRY_COMPARE(footer->pos(), posWhenNoItems);
-
- // if header is present, it's at a negative pos, so the footer should not move
- canvas->rootObject()->setProperty("showHeader", true);
- QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
- QTRY_COMPARE(footer->pos(), posWhenNoItems);
- canvas->rootObject()->setProperty("showHeader", false);
-
- // add 30 items
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QSignalSpy footerItemSpy(gridview, SIGNAL(footerItemChanged()));
- QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
-
- QCOMPARE(footerItemSpy.count(), 1);
-
- footer = findItem<QQuickText>(contentItem, "footer");
- QVERIFY(!footer);
- footer = findItem<QQuickText>(contentItem, "footer2");
- QVERIFY(footer);
-
- QVERIFY(footer == gridview->footerItem());
-
- QCOMPARE(footer->pos(), changedFooterPos);
- QCOMPARE(footer->width(), 50.);
- QCOMPARE(footer->height(), 20.);
- QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- gridview->positionViewAtEnd();
- footer->setHeight(10);
- footer->setWidth(40);
- QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::footer_data()
-{
- QTest::addColumn<QQuickGridView::Flow>("flow");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<QPointF>("initialFooterPos");
- QTest::addColumn<QPointF>("changedFooterPos");
- QTest::addColumn<QPointF>("initialContentPos");
- QTest::addColumn<QPointF>("changedContentPos");
- QTest::addColumn<QPointF>("firstDelegatePos");
- QTest::addColumn<QPointF>("resizeContentPos");
-
- // footer1 = 100 x 30
- // footer2 = 50 x 20
- // cells = 80 * 60
- // view width = 240
- // view height = 320
-
- // footer below items, bottom left
- QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
- << QPointF(0, 3 * 60) // 180 = height of 3 rows (cell height is 60)
- << QPointF(0, 10 * 60) // 30 items = 10 rows
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 10 * 60 - 320 + 10);
-
- // footer below items, bottom right
- QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
- << QPointF(240 - 100, 3 * 60)
- << QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(240 - 80, 0)
- << QPointF(0, 10 * 60 - 320 + 10);
-
- // footer to right of items
- QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
- << QPointF(2 * 80, 0) // 2 columns, cell width 80
- << QPointF(6 * 80, 0) // 30 items = 6 columns
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(6 * 80 - 240 + 40, 0);
-
- // footer to left of items
- QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
- << QPointF(-(2 * 80) - 100, 0)
- << QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
- << QPointF(-240, 0)
- << QPointF(-240, 0) // unchanged, footer change doesn't change content pos
- << QPointF(-80, 0)
- << QPointF(-(6 * 80) - 40, 0);
-}
-
-void tst_QQuickGridView::header()
-{
- QFETCH(QQuickGridView::Flow, flow);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(QPointF, initialHeaderPos);
- QFETCH(QPointF, changedHeaderPos);
- QFETCH(QPointF, initialContentPos);
- QFETCH(QPointF, changedContentPos);
- QFETCH(QPointF, firstDelegatePos);
- QFETCH(QPointF, resizeContentPos);
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QQuickView *canvas = createView();
- canvas->rootContext()->setContextProperty("testModel", &model);
- canvas->rootContext()->setContextProperty("initialViewWidth", 240);
- canvas->rootContext()->setContextProperty("initialViewHeight", 320);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- gridview->setFlow(flow);
- gridview->setLayoutDirection(layoutDirection);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *header = findItem<QQuickText>(contentItem, "header");
- QVERIFY(header);
-
- QVERIFY(header == gridview->headerItem());
-
- QCOMPARE(header->pos(), initialHeaderPos);
- QCOMPARE(header->width(), 100.);
- QCOMPARE(header->height(), 30.);
- QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- model.clear();
- QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
-
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QSignalSpy headerItemSpy(gridview, SIGNAL(headerItemChanged()));
- QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
-
- QCOMPARE(headerItemSpy.count(), 1);
-
- header = findItem<QQuickText>(contentItem, "header");
- QVERIFY(!header);
- header = findItem<QQuickText>(contentItem, "header2");
- QVERIFY(header);
-
- QVERIFY(header == gridview->headerItem());
-
- QCOMPARE(header->pos(), changedHeaderPos);
- QCOMPARE(header->width(), 50.);
- QCOMPARE(header->height(), 20.);
- QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- header->setHeight(10);
- header->setWidth(40);
- QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
-
- delete canvas;
-
-
- // QTBUG-21207 header should become visible if view resizes from initial empty size
-
- canvas = createView();
- canvas->rootContext()->setContextProperty("testModel", &model);
- canvas->rootContext()->setContextProperty("initialViewWidth", 240);
- canvas->rootContext()->setContextProperty("initialViewHeight", 320);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
-
- gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- gridview->setFlow(flow);
- gridview->setLayoutDirection(layoutDirection);
-
- gridview->setWidth(240);
- gridview->setHeight(320);
- QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
- QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::header_data()
-{
- QTest::addColumn<QQuickGridView::Flow>("flow");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<QPointF>("initialHeaderPos");
- QTest::addColumn<QPointF>("changedHeaderPos");
- QTest::addColumn<QPointF>("initialContentPos");
- QTest::addColumn<QPointF>("changedContentPos");
- QTest::addColumn<QPointF>("firstDelegatePos");
- QTest::addColumn<QPointF>("resizeContentPos");
-
- // header1 = 100 x 30
- // header2 = 50 x 20
- // cells = 80 x 60
- // view width = 240
-
- // header above items, top left
- QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, 0)
- << QPointF(0, -10);
-
- // header above items, top right
- QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
- << QPointF(240 - 100, -30)
- << QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(160, 0)
- << QPointF(0, -10);
-
- // header to left of items
- QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
- << QPointF(-100, 0)
- << QPointF(-50, 0)
- << QPointF(-100, 0)
- << QPointF(-50, 0)
- << QPointF(0, 0)
- << QPointF(-40, 0);
-
- // header to right of items
- QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(-(240 - 100), 0)
- << QPointF(-(240 - 50), 0)
- << QPointF(-80, 0)
- << QPointF(-(240 - 40), 0);
-}
-
-void tst_QQuickGridView::resizeViewAndRepaint()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("initialHeight", 100);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizeview.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // item at index 10 should not be currently visible
- QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- gridview->setHeight(320);
- QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- gridview->setHeight(100);
- QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- delete canvas;
-}
-
-void tst_QQuickGridView::indexAt()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Billy", "22345");
- model.addItem("Sam", "2945");
- model.addItem("Ben", "04321");
- model.addItem("Jim", "0780");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(gridview->count(), model.count());
-
- QCOMPARE(gridview->indexAt(0, 0), 0);
- QCOMPARE(gridview->indexAt(79, 59), 0);
- QCOMPARE(gridview->indexAt(80, 0), 1);
- QCOMPARE(gridview->indexAt(0, 60), 3);
- QCOMPARE(gridview->indexAt(240, 0), -1);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::onAdd()
-{
- QFETCH(int, initialItemCount);
- QFETCH(int, itemsToAdd);
-
- const int delegateWidth = 50;
- const int delegateHeight = 100;
- TestModel model;
- QQuickView *canvas = createView();
- canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
-
- // these initial items should not trigger GridView.onAdd
- for (int i=0; i<initialItemCount; i++)
- model.addItem("dummy value", "dummy value");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("delegateWidth", delegateWidth);
- ctxt->setContextProperty("delegateHeight", delegateHeight);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
-
- QObject *object = canvas->rootObject();
- object->setProperty("width", canvas->width());
- object->setProperty("height", canvas->height());
- qApp->processEvents();
-
- QList<QPair<QString, QString> > items;
- for (int i=0; i<itemsToAdd; i++)
- items << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.addItems(items);
-
- QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
- qApp->processEvents();
-
- QVariantList result = object->property("addedDelegates").toList();
- QTRY_COMPARE(result.count(), items.count());
- for (int i=0; i<items.count(); i++)
- QCOMPARE(result[i].toString(), items[i].first);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::onAdd_data()
-{
- QTest::addColumn<int>("initialItemCount");
- QTest::addColumn<int>("itemsToAdd");
-
- QTest::newRow("0, add 1") << 0 << 1;
- QTest::newRow("0, add 2") << 0 << 2;
- QTest::newRow("0, add 10") << 0 << 10;
-
- QTest::newRow("1, add 1") << 1 << 1;
- QTest::newRow("1, add 2") << 1 << 2;
- QTest::newRow("1, add 10") << 1 << 10;
-
- QTest::newRow("5, add 1") << 5 << 1;
- QTest::newRow("5, add 2") << 5 << 2;
- QTest::newRow("5, add 10") << 5 << 10;
-}
-
-void tst_QQuickGridView::onRemove()
-{
- QFETCH(int, initialItemCount);
- QFETCH(int, indexToRemove);
- QFETCH(int, removeCount);
-
- const int delegateWidth = 50;
- const int delegateHeight = 100;
- TestModel model;
- for (int i=0; i<initialItemCount; i++)
- model.addItem(QString("value %1").arg(i), "dummy value");
-
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("delegateWidth", delegateWidth);
- ctxt->setContextProperty("delegateHeight", delegateHeight);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
- QObject *object = canvas->rootObject();
-
- model.removeItems(indexToRemove, removeCount);
- QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
- QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
-
- delete canvas;
-}
-
-void tst_QQuickGridView::onRemove_data()
-{
- QTest::addColumn<int>("initialItemCount");
- QTest::addColumn<int>("indexToRemove");
- QTest::addColumn<int>("removeCount");
-
- QTest::newRow("remove first") << 1 << 0 << 1;
- QTest::newRow("two items, remove first") << 2 << 0 << 1;
- QTest::newRow("two items, remove last") << 2 << 1 << 1;
- QTest::newRow("two items, remove all") << 2 << 0 << 2;
-
- QTest::newRow("four items, remove first") << 4 << 0 << 1;
- QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
- QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
- QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
- QTest::newRow("four items, remove last") << 4 << 3 << 1;
- QTest::newRow("four items, remove all") << 4 << 0 << 4;
-
- QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
- QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
- QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
-}
-
-void tst_QQuickGridView::columnCount()
-{
- QQuickView canvas;
- canvas.setSource(QUrl::fromLocalFile(TESTDATA("gridview4.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QQuickGridView *view = qobject_cast<QQuickGridView*>(canvas.rootObject());
-
- QCOMPARE(view->cellWidth(), qreal(405)/qreal(9));
- QCOMPARE(view->cellHeight(), qreal(100));
-
- QList<QQuickItem*> items = findItems<QQuickItem>(view, "delegate");
- QCOMPARE(items.size(), 18);
- QCOMPARE(items.at(8)->y(), qreal(0));
- QCOMPARE(items.at(9)->y(), qreal(100));
-}
-
-void tst_QQuickGridView::margins()
-{
- {
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QCOMPARE(gridview->contentX(), -30.);
- QCOMPARE(gridview->xOrigin(), 0.);
-
- // check end bound
- gridview->positionViewAtEnd();
- qreal pos = gridview->contentX();
- gridview->setContentX(pos + 80);
- gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos + 50);
-
- // remove item before visible and check that left margin is maintained
- // and xOrigin is updated
- gridview->setContentX(200);
- model.removeItems(0, 4);
- QTest::qWait(100);
- gridview->setContentX(-50);
- gridview->returnToBounds();
- QCOMPARE(gridview->xOrigin(), 100.);
- QTRY_COMPARE(gridview->contentX(), 70.);
-
- // reduce left margin
- gridview->setLeftMargin(20);
- QCOMPARE(gridview->xOrigin(), 100.);
- QTRY_COMPARE(gridview->contentX(), 80.);
-
- // check end bound
- gridview->positionViewAtEnd();
- QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
- pos = gridview->contentX();
- gridview->setContentX(pos + 80);
- gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos + 50);
-
- // reduce right margin
- pos = gridview->contentX();
- gridview->setRightMargin(40);
- QCOMPARE(gridview->xOrigin(), 0.);
- QTRY_COMPARE(gridview->contentX(), pos-10);
-
- delete canvas;
- }
- {
- //RTL
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(true));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QCOMPARE(gridview->contentX(), -240+30.);
- QCOMPARE(gridview->xOrigin(), 0.);
-
- // check end bound
- gridview->positionViewAtEnd();
- qreal pos = gridview->contentX();
- gridview->setContentX(pos - 80);
- gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos - 50);
-
- // remove item before visible and check that left margin is maintained
- // and xOrigin is updated
- gridview->setContentX(-400);
- model.removeItems(0, 4);
- QTest::qWait(100);
- gridview->setContentX(-240+50);
- gridview->returnToBounds();
- QCOMPARE(gridview->xOrigin(), -100.);
- QTRY_COMPARE(gridview->contentX(), -240-70.);
-
- // reduce left margin (i.e. right side due to RTL)
- pos = gridview->contentX();
- gridview->setLeftMargin(20);
- QCOMPARE(gridview->xOrigin(), -100.);
- QTRY_COMPARE(gridview->contentX(), -240-80.);
-
- // check end bound
- gridview->positionViewAtEnd();
- QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
- pos = gridview->contentX();
- gridview->setContentX(pos - 80);
- gridview->returnToBounds();
- QTRY_COMPARE(gridview->contentX(), pos - 50);
-
- // reduce right margin (i.e. left side due to RTL)
- pos = gridview->contentX();
- gridview->setRightMargin(40);
- QCOMPARE(gridview->xOrigin(), 0.);
- QTRY_COMPARE(gridview->contentX(), pos+10);
-
- delete canvas;
- }
-}
-
-void tst_QQuickGridView::creationContext()
-{
- QQuickView canvas;
- canvas.setGeometry(0,0,240,320);
- canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
- qApp->processEvents();
-
- QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
- QVERIFY(rootItem);
- QVERIFY(rootItem->property("count").toInt() > 0);
-
- QQuickItem *item;
- QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
- QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
- QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
-}
-
-void tst_QQuickGridView::snapToRow_data()
-{
- QTest::addColumn<QQuickGridView::Flow>("flow");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<int>("highlightRangeMode");
- QTest::addColumn<QPoint>("flickStart");
- QTest::addColumn<QPoint>("flickEnd");
- QTest::addColumn<qreal>("snapAlignment");
- QTest::addColumn<qreal>("endExtent");
- QTest::addColumn<qreal>("startExtent");
-
- QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
-
- QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
-
- QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
-
- QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
-
- QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
-
- QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
-}
-
-void tst_QQuickGridView::snapToRow()
-{
- QFETCH(QQuickGridView::Flow, flow);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(int, highlightRangeMode);
- QFETCH(QPoint, flickStart);
- QFETCH(QPoint, flickEnd);
- QFETCH(qreal, snapAlignment);
- QFETCH(qreal, endExtent);
- QFETCH(qreal, startExtent);
-
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToRow.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
-
- gridview->setFlow(flow);
- gridview->setLayoutDirection(layoutDirection);
- gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
-
- QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // confirm that a flick hits an item boundary
- flick(canvas, flickStart, flickEnd, 180);
- QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
- if (flow == QQuickGridView::LeftToRight)
- QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
- else
- QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
-
- // flick to end
- do {
- flick(canvas, flickStart, flickEnd, 180);
- QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
- } while (flow == QQuickGridView::LeftToRight
- ? !gridview->isAtYEnd()
- : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
-
- if (flow == QQuickGridView::LeftToRight)
- QCOMPARE(gridview->contentY(), endExtent);
- else
- QCOMPARE(gridview->contentX(), endExtent);
-
- // flick to start
- do {
- flick(canvas, flickEnd, flickStart, 180);
- QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
- } while (flow == QQuickGridView::LeftToRight
- ? !gridview->isAtYBeginning()
- : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
-
- if (flow == QQuickGridView::LeftToRight)
- QCOMPARE(gridview->contentY(), startExtent);
- else
- QCOMPARE(gridview->contentX(), startExtent);
-
- delete canvas;
-}
-
-void tst_QQuickGridView::unaligned()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 10; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("unaligned.qml")));
- qApp->processEvents();
-
- QQuickGridView *gridview = qobject_cast<QQuickGridView*>(canvas->rootObject());
- QVERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
-
- for (int i = 0; i < 10; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QVERIFY(item);
- QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
- QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
- }
-
- // appending
- for (int i = 10; i < 18; ++i) {
- model.addItem("Item" + QString::number(i), "");
- QQuickItem *item = 0;
- QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
- QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
- QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
- }
-
- // inserting
- for (int i = 0; i < 10; ++i) {
- model.insertItem(i, "Item" + QString::number(i), "");
- QQuickItem *item = 0;
- QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
- QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
- QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
- }
-
- // removing
- model.removeItems(7, 10);
- QTRY_COMPARE(model.count(), gridview->count());
- for (int i = 0; i < 18; ++i) {
- QQuickItem *item = 0;
- QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
- QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
- QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
- }
-
- delete canvas;
-}
-
-QQuickView *tst_QQuickGridView::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- return canvas;
-}
-
-void tst_QQuickGridView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
-{
- const int pointCount = 5;
- QPoint diff = to - from;
-
- // send press, five equally spaced moves, and release.
- QTest::mousePress(canvas, Qt::LeftButton, 0, from);
-
- for (int i = 0; i < pointCount; ++i) {
- QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- QTest::qWait(duration/pointCount);
- QCoreApplication::processEvents();
- }
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
-}
-
-void tst_QQuickGridView::cacheBuffer()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 90; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testRightToLeft", QVariant(false));
- ctxt->setContextProperty("testTopToBottom", QVariant(false));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
- QVERIFY(gridview != 0);
-
- QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QVERIFY(gridview->delegate() != 0);
- QVERIFY(gridview->model() != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_COMPARE(item->x(), (i%3)*80.0);
- QTRY_COMPARE(item->y(), (i/3)*60.0);
- }
-
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- canvas->rootObject()->setProperty("cacheBuffer", 200);
- QTRY_VERIFY(gridview->cacheBuffer() == 200);
-
- // items will be created one at a time
- for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(gridview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- int newItemCount = 0;
- newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count() && i < newItemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.0);
- QTRY_COMPARE(item->y(), (i/3)*60.0);
- }
-
- // move view and confirm items in view are visible immediately and outside are created async
- gridview->setContentY(300);
-
- for (int i = 15; i < 34; ++i) { // 34 due to staggered item creation
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item);
- QTRY_COMPARE(item->x(), (i%3)*80.0);
- QTRY_COMPARE(item->y(), (i/3)*60.0);
- }
-
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
-
- // ensure buffered items are created
- for (int i = 34; i < qMin(44,model.count()); ++i) {
- QQuickItem *item = 0;
- while (!item) {
- qGuiApp->processEvents(); // allow refill to happen
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(gridview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- delete canvas;
-}
-
-void tst_QQuickGridView::asynchronous()
-{
- QQuickView *canvas = createView();
- canvas->show();
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- canvas->setSource(TESTDATA("asyncloader.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootObject);
-
- QQuickGridView *gridview = 0;
- while (!gridview) {
- bool b = false;
- controller.incubateWhile(&b);
- gridview = rootObject->findChild<QQuickGridView*>("view");
- }
-
- // items will be created one at a time
- for (int i = 0; i < 12; ++i) {
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(gridview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- // verify positioning
- QQuickItem *contentItem = gridview->contentItem();
- for (int i = 0; i < 12; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QVERIFY(item->x() == (i%3)*100);
- QVERIFY(item->y() == (i/3)*100);
- }
-
- delete canvas;
-}
-
-/*
- Find an item with the specified objectName. If index is supplied then the
- item must also evaluate the {index} expression equal to index
-*/
-template<typename T>
-T *tst_QQuickGridView::findItem(QQuickItem *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
- if (context) {
- if (context->contextProperty("index").toInt() == index) {
- return static_cast<T*>(item);
- }
- }
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-template<typename T>
-QList<T*> tst_QQuickGridView::findItems(QQuickItem *parent, const QString &objectName)
-{
- QList<T*> items;
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- items.append(static_cast<T*>(item));
- //qDebug() << " found:" << item;
- }
- items += findItems<T>(item, objectName);
- }
-
- return items;
-}
-
-void tst_QQuickGridView::dumpTree(QQuickItem *parent, int depth)
-{
- static QString padding(" ");
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
- qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
- dumpTree(item, depth+1);
- }
-}
-
-
-QTEST_MAIN(tst_QQuickGridView)
-
-#include "tst_qquickgridview.moc"
-
diff --git a/tests/auto/declarative/qquickimage/qquickimage.pro b/tests/auto/declarative/qquickimage/qquickimage.pro
deleted file mode 100644
index 46cbdb49aa..0000000000
--- a/tests/auto/declarative/qquickimage/qquickimage.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickimage
-macx:CONFIG -= app_bundle
-
-HEADERS += ../shared/testhttpserver.h
-SOURCES += tst_qquickimage.cpp ../shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickimage/tst_qquickimage.cpp b/tests/auto/declarative/qquickimage/tst_qquickimage.cpp
deleted file mode 100644
index 520c0fe5da..0000000000
--- a/tests/auto/declarative/qquickimage/tst_qquickimage.cpp
+++ /dev/null
@@ -1,732 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QTextDocument>
-#include <QTcpServer>
-#include <QTcpSocket>
-#include <QDir>
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickimage_p.h>
-#include <private/qquickimagebase_p.h>
-#include <private/qquickloader_p.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtTest/QSignalSpy>
-#include <QtGui/QPainter>
-#include <QtGui/QImageReader>
-
-#include "../shared/util.h"
-#include "../shared/testhttpserver.h"
-
-#define SERVER_PORT 14451
-#define SERVER_ADDR "http://127.0.0.1:14451"
-
-Q_DECLARE_METATYPE(QQuickImageBase::Status)
-
-class tst_qquickimage : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickimage();
-
-private slots:
- void noSource();
- void imageSource();
- void imageSource_data();
- void clearSource();
- void resized();
- void preserveAspectRatio();
- void smooth();
- void mirror();
- void svg();
- void geometry();
- void geometry_data();
- void big();
- void tiling_QTBUG_6716();
- void tiling_QTBUG_6716_data();
- void noLoading();
- void paintedWidthHeight();
- void sourceSize_QTBUG_14303();
- void sourceSize_QTBUG_16389();
- void nullPixmapPaint();
- void imageCrash_QTBUG_22125();
-
-private:
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &id, int index=-1);
-
- QDeclarativeEngine engine;
-};
-
-tst_qquickimage::tst_qquickimage()
-{
-}
-
-void tst_qquickimage::noSource()
-{
- QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->source(), QUrl());
- QVERIFY(obj->status() == QQuickImage::Null);
- QCOMPARE(obj->width(), 0.);
- QCOMPARE(obj->height(), 0.);
- QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
- QCOMPARE(obj->progress(), 0.0);
-
- delete obj;
-}
-
-void tst_qquickimage::imageSource_data()
-{
- QTest::addColumn<QString>("source");
- QTest::addColumn<double>("width");
- QTest::addColumn<double>("height");
- QTest::addColumn<bool>("remote");
- QTest::addColumn<bool>("async");
- QTest::addColumn<bool>("cache");
- QTest::addColumn<QString>("error");
-
- QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << true << "";
- QTest::newRow("local no cache") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << false << "";
- QTest::newRow("local async") << QUrl::fromLocalFile(TESTDATA("colors1.png")).toString() << 120.0 << 120.0 << false << true << true << "";
- QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << 0.0 << 0.0 << false
- << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString();
- QTest::newRow("local async not found") << QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString() << 0.0 << 0.0 << false
- << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString();
- QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << "";
- QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
- if (QImageReader::supportedImageFormats().contains("svg"))
- QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << "";
-
- QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
- << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
-
-}
-
-void tst_qquickimage::imageSource()
-{
- QFETCH(QString, source);
- QFETCH(double, width);
- QFETCH(double, height);
- QFETCH(bool, remote);
- QFETCH(bool, async);
- QFETCH(bool, cache);
- QFETCH(QString, error);
-
- TestHTTPServer server(SERVER_PORT);
- if (remote) {
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
- server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
- }
-
- if (!error.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
-
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: "
- + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
- + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
-
- if (async)
- QVERIFY(obj->asynchronous() == true);
- else
- QVERIFY(obj->asynchronous() == false);
-
- if (cache)
- QVERIFY(obj->cache() == true);
- else
- QVERIFY(obj->cache() == false);
-
- if (remote || async)
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
-
- QCOMPARE(obj->source(), remote ? source : QUrl(source));
-
- if (error.isEmpty()) {
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QCOMPARE(obj->width(), qreal(width));
- QCOMPARE(obj->height(), qreal(height));
- QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
- QCOMPARE(obj->progress(), 1.0);
- } else {
- QTRY_VERIFY(obj->status() == QQuickImage::Error);
- }
-
- delete obj;
-}
-
-void tst_qquickimage::clearSource()
-{
- QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
- QCOMPARE(obj->width(), 120.);
- QCOMPARE(obj->height(), 120.);
- QCOMPARE(obj->progress(), 1.0);
-
- ctxt->setContextProperty("srcImage", "");
- QVERIFY(obj->source().isEmpty());
- QVERIFY(obj->status() == QQuickImage::Null);
- QCOMPARE(obj->width(), 0.);
- QCOMPARE(obj->height(), 0.);
- QCOMPARE(obj->progress(), 0.0);
-
- delete obj;
-}
-
-void tst_qquickimage::resized()
-{
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
- delete obj;
-}
-
-
-void tst_qquickimage::preserveAspectRatio()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->show();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
- QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
- QVERIFY(image != 0);
- image->setWidth(80.0);
- QCOMPARE(image->width(), 80.);
- QCOMPARE(image->height(), 80.);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
- image = qobject_cast<QQuickImage*>(canvas->rootObject());
- image->setHeight(60.0);
- QVERIFY(image != 0);
- QCOMPARE(image->height(), 60.);
- QCOMPARE(image->width(), 60.);
- delete canvas;
-}
-
-void tst_qquickimage::smooth()
-{
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.);
- QCOMPARE(obj->height(), 300.);
- QCOMPARE(obj->smooth(), true);
- QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
-
- delete obj;
-}
-
-void tst_qquickimage::mirror()
-{
- QSKIP("Test is broken on multiple levels, will need incremental fixes");
-
- QMap<QQuickImage::FillMode, QImage> screenshots;
- QList<QQuickImage::FillMode> fillModes;
- fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
- << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally;
-
- qreal width = 300;
- qreal height = 250;
-
- foreach (QQuickImage::FillMode fillMode, fillModes) {
- QQuickView *canvas = new QQuickView;
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml")));
-
- QQuickImage *obj = canvas->rootObject()->findChild<QQuickImage*>("image");
- QVERIFY(obj != 0);
-
- obj->setFillMode(fillMode);
- obj->setProperty("mirror", true);
- canvas->show();
-
- QImage screenshot = canvas->grabFrameBuffer();
- screenshots[fillMode] = screenshot;
- delete canvas;
- }
-
- foreach (QQuickImage::FillMode fillMode, fillModes) {
- QPixmap srcPixmap;
- QVERIFY(srcPixmap.load(TESTDATA("pattern.png")));
-
- QPixmap expected(width, height);
- expected.fill();
- QPainter p_e(&expected);
- QTransform transform;
- transform.translate(width, 0).scale(-1, 1.0);
- p_e.setTransform(transform);
-
- switch (fillMode) {
- case QQuickImage::Stretch:
- p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
- break;
- case QQuickImage::PreserveAspectFit:
- p_e.drawPixmap(QRect(25, 0, height, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
- break;
- case QQuickImage::PreserveAspectCrop:
- {
- qreal ratio = width/srcPixmap.width(); // width is the longer side
- QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio);
- rect.moveCenter(QRect(0, 0, width, height).center());
- p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
- break;
- }
- case QQuickImage::Tile:
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
- break;
- case QQuickImage::TileVertically:
- transform.scale(width / srcPixmap.width(), 1.0);
- p_e.setTransform(transform);
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
- break;
- case QQuickImage::TileHorizontally:
- transform.scale(1.0, height / srcPixmap.height());
- p_e.setTransform(transform);
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
- break;
- case QQuickImage::Pad:
- break;
- }
-
- QImage img = expected.toImage();
- QEXPECT_FAIL("", "QTBUG-21005 fails", Continue);
- QCOMPARE(screenshots[fillMode], img);
- }
-}
-
-void tst_qquickimage::svg()
-{
- if (!QImageReader::supportedImageFormats().contains("svg"))
- QSKIP("svg support not available");
-
- QString src = QUrl::fromLocalFile(TESTDATA("heart.svg")).toString();
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 300.0);
- QCOMPARE(obj->height(), 300.0);
- obj->setSourceSize(QSize(200,200));
-
- QCOMPARE(obj->width(), 200.0);
- QCOMPARE(obj->height(), 200.0);
- delete obj;
-}
-
-void tst_qquickimage::geometry_data()
-{
- QTest::addColumn<QString>("fillMode");
- QTest::addColumn<bool>("explicitWidth");
- QTest::addColumn<bool>("explicitHeight");
- QTest::addColumn<double>("itemWidth");
- QTest::addColumn<double>("paintedWidth");
- QTest::addColumn<double>("boundingWidth");
- QTest::addColumn<double>("itemHeight");
- QTest::addColumn<double>("paintedHeight");
- QTest::addColumn<double>("boundingHeight");
-
- // tested image has width 200, height 100
-
- // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match
- QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
- QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0;
- QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0;
- QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0;
-
- // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match
- QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
- QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0;
- QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
- QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
-
- // bounding rect, painted rect and item rect are equal in stretching and tiling images
- QStringList fillModes;
- fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
- foreach (QString fillMode, fillModes) {
- QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
- QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
- QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
- QTest::newRow(QString(fillMode + " explicit width 300, height 400").toLatin1()) << fillMode << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 400.0 << 400.0;
- }
-}
-
-void tst_qquickimage::geometry()
-{
- QFETCH(QString, fillMode);
- QFETCH(bool, explicitWidth);
- QFETCH(bool, explicitHeight);
- QFETCH(double, itemWidth);
- QFETCH(double, itemHeight);
- QFETCH(double, paintedWidth);
- QFETCH(double, paintedHeight);
- QFETCH(double, boundingWidth);
- QFETCH(double, boundingHeight);
-
- QString src = QUrl::fromLocalFile(TESTDATA("rect.png")).toString();
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; ";
-
- if (explicitWidth)
- componentStr.append("width: 300; ");
- if (explicitHeight)
- componentStr.append("height: 400; ");
- componentStr.append("}");
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->width(), itemWidth);
- QCOMPARE(obj->paintedWidth(), paintedWidth);
- QCOMPARE(obj->boundingRect().width(), boundingWidth);
-
- QCOMPARE(obj->height(), itemHeight);
- QCOMPARE(obj->paintedHeight(), paintedHeight);
- QCOMPARE(obj->boundingRect().height(), boundingHeight);
- delete obj;
-}
-
-void tst_qquickimage::big()
-{
- // If the JPEG loader does not implement scaling efficiently, it would
- // have to build a 400 MB image. That would be a bug in the JPEG loader.
-
- QString src = QUrl::fromLocalFile(TESTDATA("big.jpeg")).toString();
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }";
-
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 100.0);
- QCOMPARE(obj->height(), 256.0);
-
- delete obj;
-}
-
-// As tiling_QTBUG_6716 doesn't complete, it doesn't delete the
-// canvas which causes leak warnings. Use this delete on stack
-// destruction pattern to work around this.
-template<typename T>
-struct AutoDelete {
- AutoDelete(T *t) : t(t) {}
- ~AutoDelete() { delete t; }
-private:
- T *t;
-};
-
-void tst_qquickimage::tiling_QTBUG_6716()
-{
- QSKIP("Test is broken on multiple levels, will need incremental fixes");
-
- QFETCH(QString, source);
-
- QQuickView *canvas = new QQuickView(0);
- AutoDelete<QQuickView> del(canvas);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA(source)));
- canvas->show();
- qApp->processEvents();
-
- QQuickImage *tiling = findItem<QQuickImage>(canvas->rootObject(), "tiling");
-
- QVERIFY(tiling != 0);
- QImage img = canvas->grabFrameBuffer();
- for (int x = 0; x < tiling->width(); ++x) {
- for (int y = 0; y < tiling->height(); ++y) {
- QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
- }
- }
-}
-
-void tst_qquickimage::tiling_QTBUG_6716_data()
-{
- QTest::addColumn<QString>("source");
- QTest::newRow("vertical_tiling") << "vtiling.qml";
- QTest::newRow("horizontal_tiling") << "htiling.qml";
-}
-
-void tst_qquickimage::noLoading()
-{
- qRegisterMetaType<QQuickImageBase::Status>();
-
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
- server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
-
- QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; cache: true }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart.png")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->status() == QQuickImage::Ready);
-
- QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
- QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
- QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
-
- // Loading local file
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
- QTRY_COMPARE(sourceSpy.count(), 1);
- QTRY_COMPARE(progressSpy.count(), 0);
- QTRY_COMPARE(statusSpy.count(), 0);
-
- // Loading remote file
- ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
- QTRY_VERIFY(obj->status() == QQuickImage::Loading);
- QTRY_VERIFY(obj->progress() == 0.0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
- QTRY_COMPARE(sourceSpy.count(), 2);
- QTRY_COMPARE(progressSpy.count(), 2);
- QTRY_COMPARE(statusSpy.count(), 2);
-
- // Loading remote file again - should not go through 'Loading' state.
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
- ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
- QTRY_VERIFY(obj->progress() == 1.0);
- QTRY_COMPARE(sourceSpy.count(), 4);
- QTRY_COMPARE(progressSpy.count(), 2);
- QTRY_COMPARE(statusSpy.count(), 2);
-
- delete obj;
-}
-
-void tst_qquickimage::paintedWidthHeight()
-{
- {
- QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }";
-
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 200.0);
- QCOMPARE(obj->height(), 25.0);
- QCOMPARE(obj->paintedWidth(), 25.0);
- QCOMPARE(obj->paintedHeight(), 25.0);
-
- delete obj;
- }
-
- {
- QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
- QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 26.0);
- QCOMPARE(obj->height(), 175.0);
- QCOMPARE(obj->paintedWidth(), 26.0);
- QCOMPARE(obj->paintedHeight(), 26.0);
-
- delete obj;
- }
-}
-
-void tst_qquickimage::sourceSize_QTBUG_14303()
-{
- QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
- QDeclarativeContext *ctxt = engine.rootContext();
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
-
- QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
-
- QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->status() == QQuickImage::Ready);
-
- QTRY_COMPARE(obj->sourceSize().width(), 200);
- QTRY_COMPARE(obj->sourceSize().height(), 200);
- QTRY_COMPARE(sourceSizeSpy.count(), 0);
-
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
- QTRY_COMPARE(obj->sourceSize().width(), 120);
- QTRY_COMPARE(obj->sourceSize().height(), 120);
- QTRY_COMPARE(sourceSizeSpy.count(), 1);
-
- ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
- QTRY_COMPARE(obj->sourceSize().width(), 200);
- QTRY_COMPARE(obj->sourceSize().height(), 200);
- QTRY_COMPARE(sourceSizeSpy.count(), 2);
-
- delete obj;
-}
-
-void tst_qquickimage::sourceSize_QTBUG_16389()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug_16389.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickImage *image = findItem<QQuickImage>(canvas->rootObject(), "iconImage");
- QQuickItem *handle = findItem<QQuickItem>(canvas->rootObject(), "blueHandle");
-
- QCOMPARE(image->sourceSize().width(), 200);
- QCOMPARE(image->sourceSize().height(), 200);
- QCOMPARE(image->paintedWidth(), 0.0);
- QCOMPARE(image->paintedHeight(), 0.0);
-
- handle->setY(20);
-
- QCOMPARE(image->sourceSize().width(), 200);
- QCOMPARE(image->sourceSize().height(), 200);
- QCOMPARE(image->paintedWidth(), 20.0);
- QCOMPARE(image->paintedHeight(), 20.0);
-
- delete canvas;
-}
-
-static int numberOfWarnings = 0;
-static void checkWarnings(QtMsgType, const char *msg)
-{
- if (!QString(msg).contains("QGLContext::makeCurrent(): Failed."))
- numberOfWarnings++;
-}
-
-// QTBUG-15690
-void tst_qquickimage::nullPixmapPaint()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("nullpixmap.qml")));
- canvas->show();
-
- QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
- QTRY_VERIFY(image != 0);
- image->setSource(SERVER_ADDR + QString("/no-such-file.png"));
-
- QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings);
-
- // used to print "QTransform::translate with NaN called"
- QPixmap pm = QPixmap::fromImage(canvas->grabFrameBuffer());
- qInstallMsgHandler(previousMsgHandler);
- QVERIFY(numberOfWarnings == 0);
- delete image;
-}
-
-void tst_qquickimage::imageCrash_QTBUG_22125()
-{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""), TestHTTPServer::Delay);
-
- {
- QQuickView view(QUrl::fromLocalFile(TESTDATA("qtbug_22125.qml")));
- view.show();
- qApp->processEvents();
- qApp->processEvents();
- // shouldn't crash when the view drops out of scope due to
- // QDeclarativePixmapData attempting to dereference a pointer to
- // the destroyed reader.
- }
-
- // shouldn't crash when deleting cancelled QDeclarativePixmapReplys.
- QTest::qWait(520); // Delay mode delays for 500 ms.
- qApp->processEvents(QEventLoop::DeferredDeletion);
-}
-
-/*
- Find an item with the specified objectName. If index is supplied then the
- item must also evaluate the {index} expression equal to index
-*/
-template<typename T>
-T *tst_qquickimage::findItem(QQuickItem *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeExpression e(qmlContext(item), item, "index");
- if (e.evaluate().toInt() == index)
- return static_cast<T*>(item);
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-QTEST_MAIN(tst_qquickimage)
-
-#include "tst_qquickimage.moc"
diff --git a/tests/auto/declarative/qquickitem/qquickitem.pro b/tests/auto/declarative/qquickitem/qquickitem.pro
deleted file mode 100644
index f484bae014..0000000000
--- a/tests/auto/declarative/qquickitem/qquickitem.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickitem
-SOURCES += tst_qquickitem.cpp
-
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private widgets testlib
diff --git a/tests/auto/declarative/qquickitem/tst_qquickitem.cpp b/tests/auto/declarative/qquickitem/tst_qquickitem.cpp
deleted file mode 100644
index f8660540d9..0000000000
--- a/tests/auto/declarative/qquickitem/tst_qquickitem.cpp
+++ /dev/null
@@ -1,1190 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-
-#include "qquickitem.h"
-#include "qquickcanvas.h"
-#include "qquickview.h"
-#include <QtWidgets/QGraphicsSceneMouseEvent>
-#include "private/qquickfocusscope_p.h"
-#include "private/qquickitem_p.h"
-#include <QDebug>
-#include <QTimer>
-#include "../shared/util.h"
-
-class TestItem : public QQuickItem
-{
-Q_OBJECT
-public:
- TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {}
-
- bool focused;
- int pressCount;
- int releaseCount;
- int wheelCount;
-protected:
- virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
- virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
- virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
- virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
- virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
-};
-
-class TestPolishItem : public QQuickItem
-{
-Q_OBJECT
-public:
- TestPolishItem(QQuickItem *parent)
- : QQuickItem(parent), wasPolished(false) {
- QTimer::singleShot(10, this, SLOT(doPolish()));
- }
-
- bool wasPolished;
-
-protected:
- virtual void updatePolish() {
- wasPolished = true;
- }
-
-public slots:
- void doPolish() {
- polish();
- }
-};
-
-class TestFocusScope : public QQuickFocusScope
-{
-Q_OBJECT
-public:
- TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
-
- bool focused;
-protected:
- virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
- virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
-};
-
-class tst_qquickitem : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickitem();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
-
- void noCanvas();
- void simpleFocus();
- void scopedFocus();
- void addedToCanvas();
- void changeParent();
-
- void constructor();
- void setParentItem();
-
- void visible();
- void enabled();
-
- void mouseGrab();
- void polishOutsideAnimation();
-
- void wheelEvent_data();
- void wheelEvent();
- void hoverEvent_data();
- void hoverEvent();
- void hoverEventInParent();
-
- void paintOrder_data();
- void paintOrder();
-
-private:
-
- enum PaintOrderOp {
- NoOp, Append, Remove, StackBefore, StackAfter, SetZ
- };
-
- void ensureFocus(QWindow *w) {
- w->show();
- w->requestActivateWindow();
- qApp->processEvents();
- }
-};
-
-tst_qquickitem::tst_qquickitem()
-{
-}
-
-void tst_qquickitem::initTestCase()
-{
-}
-
-void tst_qquickitem::cleanupTestCase()
-{
-}
-
-// Focus has no effect when outside a canvas
-void tst_qquickitem::noCanvas()
-{
- QQuickItem *root = new TestItem;
- QQuickItem *child = new TestItem(root);
- QQuickItem *scope = new TestItem(root);
- QQuickFocusScope *scopedChild = new TestFocusScope(scope);
- QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
-
- QCOMPARE(root->hasFocus(), false);
- QCOMPARE(child->hasFocus(), false);
- QCOMPARE(scope->hasFocus(), false);
- QCOMPARE(scopedChild->hasFocus(), false);
- QCOMPARE(scopedChild2->hasFocus(), false);
-
- root->setFocus(true);
- scope->setFocus(true);
- scopedChild2->setFocus(true);
- QCOMPARE(root->hasFocus(), true);
- QCOMPARE(child->hasFocus(), false);
- QCOMPARE(scope->hasFocus(), true);
- QCOMPARE(scopedChild->hasFocus(), false);
- QCOMPARE(scopedChild2->hasFocus(), true);
-
- root->setFocus(false);
- child->setFocus(true);
- scopedChild->setFocus(true);
- scope->setFocus(false);
- QCOMPARE(root->hasFocus(), false);
- QCOMPARE(child->hasFocus(), true);
- QCOMPARE(scope->hasFocus(), false);
- QCOMPARE(scopedChild->hasFocus(), true);
- QCOMPARE(scopedChild2->hasFocus(), true);
-
- delete root;
-}
-
-struct FocusData {
- FocusData() : focus(false), activeFocus(false) {}
-
- void set(bool f, bool af) { focus = f; activeFocus = af; }
- bool focus;
- bool activeFocus;
-};
-struct FocusState : public QHash<QQuickItem *, FocusData>
-{
- FocusState() : activeFocusItem(0) {}
- FocusState &operator<<(QQuickItem *item) {
- insert(item, FocusData());
- return *this;
- }
-
- void active(QQuickItem *i) {
- activeFocusItem = i;
- }
- QQuickItem *activeFocusItem;
-};
-
-#define FVERIFY() \
- do { \
- if (focusState.activeFocusItem) { \
- QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
- if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
- QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
- else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
- QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
- } else { \
- QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
- } \
- for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
- iter != focusState.end(); \
- iter++) { \
- QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
- QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
- } \
- } while (false)
-
-// Tests a simple set of top-level scoped items
-void tst_qquickitem::simpleFocus()
-{
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
-
- QQuickItem *l1c1 = new TestItem(canvas.rootItem());
- QQuickItem *l1c2 = new TestItem(canvas.rootItem());
- QQuickItem *l1c3 = new TestItem(canvas.rootItem());
-
- QQuickItem *l2c1 = new TestItem(l1c1);
- QQuickItem *l2c2 = new TestItem(l1c1);
- QQuickItem *l2c3 = new TestItem(l1c3);
-
- FocusState focusState;
- focusState << l1c1 << l1c2 << l1c3
- << l2c1 << l2c2 << l2c3;
- FVERIFY();
-
- l1c1->setFocus(true);
- focusState[l1c1].set(true, true);
- focusState.active(l1c1);
- FVERIFY();
-
- l2c3->setFocus(true);
- focusState[l1c1].set(false, false);
- focusState[l2c3].set(true, true);
- focusState.active(l2c3);
- FVERIFY();
-
- l1c3->setFocus(true);
- focusState[l2c3].set(false, false);
- focusState[l1c3].set(true, true);
- focusState.active(l1c3);
- FVERIFY();
-
- l1c2->setFocus(false);
- FVERIFY();
-
- l1c3->setFocus(false);
- focusState[l1c3].set(false, false);
- focusState.active(0);
- FVERIFY();
-
- l2c1->setFocus(true);
- focusState[l2c1].set(true, true);
- focusState.active(l2c1);
- FVERIFY();
-}
-
-// Items with a focus scope
-void tst_qquickitem::scopedFocus()
-{
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
-
- QQuickItem *l1c1 = new TestItem(canvas.rootItem());
- QQuickItem *l1c2 = new TestItem(canvas.rootItem());
- QQuickItem *l1c3 = new TestItem(canvas.rootItem());
-
- QQuickItem *l2c1 = new TestItem(l1c1);
- QQuickItem *l2c2 = new TestItem(l1c1);
- QQuickItem *l2c3 = new TestFocusScope(l1c3);
-
- QQuickItem *l3c1 = new TestItem(l2c3);
- QQuickItem *l3c2 = new TestFocusScope(l2c3);
-
- QQuickItem *l4c1 = new TestItem(l3c2);
- QQuickItem *l4c2 = new TestItem(l3c2);
-
- FocusState focusState;
- focusState << l1c1 << l1c2 << l1c3
- << l2c1 << l2c2 << l2c3
- << l3c1 << l3c2
- << l4c1 << l4c2;
- FVERIFY();
-
- l4c2->setFocus(true);
- focusState[l4c2].set(true, false);
- FVERIFY();
-
- l4c1->setFocus(true);
- focusState[l4c2].set(false, false);
- focusState[l4c1].set(true, false);
- FVERIFY();
-
- l1c1->setFocus(true);
- focusState[l1c1].set(true, true);
- focusState.active(l1c1);
- FVERIFY();
-
- l3c2->setFocus(true);
- focusState[l3c2].set(true, false);
- FVERIFY();
-
- l2c3->setFocus(true);
- focusState[l1c1].set(false, false);
- focusState[l2c3].set(true, true);
- focusState[l3c2].set(true, true);
- focusState[l4c1].set(true, true);
- focusState.active(l4c1);
- FVERIFY();
-
- l3c2->setFocus(false);
- focusState[l3c2].set(false, false);
- focusState[l4c1].set(true, false);
- focusState.active(l2c3);
- FVERIFY();
-
- l3c2->setFocus(true);
- focusState[l3c2].set(true, true);
- focusState[l4c1].set(true, true);
- focusState.active(l4c1);
- FVERIFY();
-
- l4c1->setFocus(false);
- focusState[l4c1].set(false, false);
- focusState.active(l3c2);
- FVERIFY();
-
- l1c3->setFocus(true);
- focusState[l1c3].set(true, true);
- focusState[l2c3].set(false, false);
- focusState[l3c2].set(true, false);
- focusState.active(l1c3);
- FVERIFY();
-}
-
-// Tests focus corrects itself when a tree is added to a canvas for the first time
-void tst_qquickitem::addedToCanvas()
-{
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
-
- QQuickItem *item = new TestItem;
-
- FocusState focusState;
- focusState << item;
-
- item->setFocus(true);
- focusState[item].set(true, false);
- FVERIFY();
-
- item->setParentItem(canvas.rootItem());
- focusState[item].set(true, true);
- focusState.active(item);
- FVERIFY();
- }
-
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
-
- QQuickItem *item = new TestItem(canvas.rootItem());
-
- QQuickItem *tree = new TestItem;
- QQuickItem *c1 = new TestItem(tree);
- QQuickItem *c2 = new TestItem(tree);
-
- FocusState focusState;
- focusState << item << tree << c1 << c2;
-
- item->setFocus(true);
- c1->setFocus(true);
- c2->setFocus(true);
- focusState[item].set(true, true);
- focusState[c1].set(true, false);
- focusState[c2].set(true, false);
- focusState.active(item);
- FVERIFY();
-
- tree->setParentItem(item);
- focusState[c1].set(false, false);
- focusState[c2].set(false, false);
- FVERIFY();
- }
-
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
-
- QQuickItem *tree = new TestItem;
- QQuickItem *c1 = new TestItem(tree);
- QQuickItem *c2 = new TestItem(tree);
-
- FocusState focusState;
- focusState << tree << c1 << c2;
- c1->setFocus(true);
- c2->setFocus(true);
- focusState[c1].set(true, false);
- focusState[c2].set(true, false);
- FVERIFY();
-
- tree->setParentItem(canvas.rootItem());
- focusState[c1].set(true, true);
- focusState[c2].set(false, false);
- focusState.active(c1);
- FVERIFY();
- }
-
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *tree = new TestFocusScope;
- QQuickItem *c1 = new TestItem(tree);
- QQuickItem *c2 = new TestItem(tree);
-
- FocusState focusState;
- focusState << tree << c1 << c2;
- c1->setFocus(true);
- c2->setFocus(true);
- focusState[c1].set(true, false);
- focusState[c2].set(true, false);
- FVERIFY();
-
- tree->setParentItem(canvas.rootItem());
- focusState[c1].set(true, false);
- focusState[c2].set(false, false);
- FVERIFY();
-
- tree->setFocus(true);
- focusState[tree].set(true, true);
- focusState[c1].set(true, true);
- focusState.active(c1);
- FVERIFY();
- }
-
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *tree = new TestFocusScope;
- QQuickItem *c1 = new TestItem(tree);
- QQuickItem *c2 = new TestItem(tree);
-
- FocusState focusState;
- focusState << tree << c1 << c2;
- tree->setFocus(true);
- c1->setFocus(true);
- c2->setFocus(true);
- focusState[tree].set(true, false);
- focusState[c1].set(true, 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);
- FVERIFY();
- }
-
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
- QQuickItem *tree = new TestFocusScope;
- QQuickItem *c1 = new TestItem(tree);
- QQuickItem *c2 = new TestItem(tree);
-
- FocusState focusState;
- focusState << child << tree << c1 << c2;
- child->setFocus(true);
- tree->setFocus(true);
- c1->setFocus(true);
- c2->setFocus(true);
- focusState[child].set(true, true);
- focusState[tree].set(true, false);
- focusState[c1].set(true, 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);
- FVERIFY();
-
- tree->setFocus(true);
- focusState[child].set(false, false);
- focusState[tree].set(true, true);
- focusState[c1].set(true, true);
- focusState.active(c1);
- FVERIFY();
- }
-}
-
-void tst_qquickitem::changeParent()
-{
- // Parent to no parent
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
-
- FocusState focusState;
- focusState << child;
- FVERIFY();
-
- child->setFocus(true);
- focusState[child].set(true, true);
- focusState.active(child);
- FVERIFY();
-
- child->setParentItem(0);
- focusState[child].set(true, false);
- focusState.active(0);
- FVERIFY();
- }
-
- // Different parent, same focus scope
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
- QQuickItem *child2 = new TestItem(canvas.rootItem());
-
- FocusState focusState;
- focusState << child << child2;
- FVERIFY();
-
- child->setFocus(true);
- focusState[child].set(true, true);
- focusState.active(child);
- FVERIFY();
-
- child->setParentItem(child2);
- FVERIFY();
- }
-
- // Different parent, different focus scope
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
- QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
- QQuickItem *item = new TestItem(child);
-
- FocusState focusState;
- focusState << child << child2 << item;
- FVERIFY();
-
- item->setFocus(true);
- focusState[item].set(true, true);
- focusState.active(item);
- FVERIFY();
-
- item->setParentItem(child2);
- focusState[item].set(true, false);
- focusState.active(0);
- FVERIFY();
- }
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
- QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
- QQuickItem *item = new TestItem(child2);
-
- FocusState focusState;
- focusState << child << child2 << item;
- FVERIFY();
-
- item->setFocus(true);
- focusState[item].set(true, false);
- focusState.active(0);
- FVERIFY();
-
- item->setParentItem(child);
- focusState[item].set(true, true);
- focusState.active(item);
- FVERIFY();
- }
- {
- QQuickCanvas canvas;
- ensureFocus(&canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
- QQuickItem *child = new TestItem(canvas.rootItem());
- QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
- QQuickItem *item = new TestItem(child2);
-
- FocusState focusState;
- focusState << child << child2 << item;
- FVERIFY();
-
- child->setFocus(true);
- item->setFocus(true);
- focusState[child].set(true, true);
- focusState[item].set(true, false);
- focusState.active(child);
- FVERIFY();
-
- item->setParentItem(child);
- focusState[item].set(false, false);
- FVERIFY();
- }
-
-}
-
-void tst_qquickitem::constructor()
-{
- QQuickItem *root = new QQuickItem;
- QVERIFY(root->parent() == 0);
- QVERIFY(root->parentItem() == 0);
-
- QQuickItem *child1 = new QQuickItem(root);
- QVERIFY(child1->parent() == root);
- QVERIFY(child1->parentItem() == root);
- QCOMPARE(root->childItems().count(), 1);
- QCOMPARE(root->childItems().at(0), child1);
-
- QQuickItem *child2 = new QQuickItem(root);
- QVERIFY(child2->parent() == root);
- QVERIFY(child2->parentItem() == root);
- QCOMPARE(root->childItems().count(), 2);
- QCOMPARE(root->childItems().at(0), child1);
- QCOMPARE(root->childItems().at(1), child2);
-
- delete root;
-}
-
-void tst_qquickitem::setParentItem()
-{
- QQuickItem *root = new QQuickItem;
- QVERIFY(root->parent() == 0);
- QVERIFY(root->parentItem() == 0);
-
- QQuickItem *child1 = new QQuickItem;
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
-
- child1->setParentItem(root);
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == root);
- QCOMPARE(root->childItems().count(), 1);
- QCOMPARE(root->childItems().at(0), child1);
-
- QQuickItem *child2 = new QQuickItem;
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == 0);
- child2->setParentItem(root);
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == root);
- QCOMPARE(root->childItems().count(), 2);
- QCOMPARE(root->childItems().at(0), child1);
- QCOMPARE(root->childItems().at(1), child2);
-
- child1->setParentItem(0);
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
- QCOMPARE(root->childItems().count(), 1);
- QCOMPARE(root->childItems().at(0), child2);
-
- delete root;
-
- QVERIFY(child1->parent() == 0);
- QVERIFY(child1->parentItem() == 0);
- QVERIFY(child2->parent() == 0);
- QVERIFY(child2->parentItem() == 0);
-
- delete child1;
- delete child2;
-}
-
-void tst_qquickitem::visible()
-{
- QQuickItem *root = new QQuickItem;
-
- QQuickItem *child1 = new QQuickItem;
- child1->setParentItem(root);
-
- QQuickItem *child2 = new QQuickItem;
- child2->setParentItem(root);
-
- QVERIFY(child1->isVisible());
- QVERIFY(child2->isVisible());
-
- root->setVisible(false);
- QVERIFY(!child1->isVisible());
- QVERIFY(!child2->isVisible());
-
- root->setVisible(true);
- QVERIFY(child1->isVisible());
- QVERIFY(child2->isVisible());
-
- child1->setVisible(false);
- QVERIFY(!child1->isVisible());
- QVERIFY(child2->isVisible());
-
- child2->setParentItem(child1);
- QVERIFY(!child1->isVisible());
- QVERIFY(!child2->isVisible());
-
- child2->setParentItem(root);
- QVERIFY(!child1->isVisible());
- QVERIFY(child2->isVisible());
-
- delete root;
- delete child1;
- delete child2;
-}
-
-void tst_qquickitem::enabled()
-{
- QQuickItem *root = new QQuickItem;
-
- QQuickItem *child1 = new QQuickItem;
- child1->setParentItem(root);
-
- QQuickItem *child2 = new QQuickItem;
- child2->setParentItem(root);
-
- QVERIFY(child1->isEnabled());
- QVERIFY(child2->isEnabled());
-
- root->setEnabled(false);
- QVERIFY(!child1->isEnabled());
- QVERIFY(!child2->isEnabled());
-
- root->setEnabled(true);
- QVERIFY(child1->isEnabled());
- QVERIFY(child2->isEnabled());
-
- child1->setEnabled(false);
- QVERIFY(!child1->isEnabled());
- QVERIFY(child2->isEnabled());
-
- child2->setParentItem(child1);
- QVERIFY(!child1->isEnabled());
- QVERIFY(!child2->isEnabled());
-
- child2->setParentItem(root);
- QVERIFY(!child1->isEnabled());
- QVERIFY(child2->isEnabled());
-
- delete root;
- delete child1;
- delete child2;
-}
-
-void tst_qquickitem::mouseGrab()
-{
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(200, 200);
- canvas->show();
-
- TestItem *child1 = new TestItem;
- child1->setAcceptedMouseButtons(Qt::LeftButton);
- child1->setSize(QSizeF(200, 100));
- child1->setParentItem(canvas->rootItem());
-
- TestItem *child2 = new TestItem;
- child2->setAcceptedMouseButtons(Qt::LeftButton);
- child2->setY(51);
- child2->setSize(QSizeF(200, 100));
- child2->setParentItem(canvas->rootItem());
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(100);
- QVERIFY(canvas->mouseGrabberItem() == child1);
- QTest::qWait(100);
-
- QCOMPARE(child1->pressCount, 1);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QVERIFY(canvas->mouseGrabberItem() == 0);
- QCOMPARE(child1->releaseCount, 1);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QVERIFY(canvas->mouseGrabberItem() == child1);
- QCOMPARE(child1->pressCount, 2);
- child1->setEnabled(false);
- QVERIFY(canvas->mouseGrabberItem() == 0);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QCOMPARE(child1->releaseCount, 1);
- child1->setEnabled(true);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QVERIFY(canvas->mouseGrabberItem() == child1);
- QCOMPARE(child1->pressCount, 3);
- child1->setVisible(false);
- QVERIFY(canvas->mouseGrabberItem() == 0);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QCOMPARE(child1->releaseCount, 1);
- child1->setVisible(true);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QVERIFY(canvas->mouseGrabberItem() == child1);
- QCOMPARE(child1->pressCount, 4);
- child2->grabMouse();
- QVERIFY(canvas->mouseGrabberItem() == child2);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QCOMPARE(child1->releaseCount, 1);
- QCOMPARE(child2->releaseCount, 1);
-
- child2->grabMouse();
- QVERIFY(canvas->mouseGrabberItem() == child2);
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QCOMPARE(child1->pressCount, 4);
- QCOMPARE(child2->pressCount, 1);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
- QTest::qWait(50);
- QCOMPARE(child1->releaseCount, 1);
- QCOMPARE(child2->releaseCount, 2);
-
- delete child1;
- delete child2;
- delete canvas;
-}
-
-void tst_qquickitem::polishOutsideAnimation()
-{
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(200, 200);
- canvas->show();
-
- TestPolishItem *item = new TestPolishItem(canvas->rootItem());
- item->setSize(QSizeF(200, 100));
- QTest::qWait(50);
- QTRY_VERIFY(item->wasPolished);
-
- delete item;
- delete canvas;
-}
-
-void tst_qquickitem::wheelEvent_data()
-{
- QTest::addColumn<bool>("visible");
- QTest::addColumn<bool>("enabled");
-
- QTest::newRow("visible and enabled") << true << true;
- QTest::newRow("visible and disabled") << true << false;
- QTest::newRow("invisible and enabled") << false << true;
- QTest::newRow("invisible and disabled") << false << false;
-}
-
-void tst_qquickitem::wheelEvent()
-{
- QFETCH(bool, visible);
- QFETCH(bool, enabled);
-
- const bool shouldReceiveWheelEvents = visible && enabled;
-
- QQuickCanvas *canvas = new QQuickCanvas;
- canvas->resize(200, 200);
- canvas->show();
-
- TestItem *item = new TestItem;
- item->setSize(QSizeF(200, 100));
- item->setParentItem(canvas->rootItem());
-
- item->setEnabled(enabled);
- item->setVisible(visible);
-
- QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
- event.setAccepted(false);
- QApplication::sendEvent(canvas, &event);
-
- if (shouldReceiveWheelEvents) {
- QVERIFY(event.isAccepted());
- QCOMPARE(item->wheelCount, 1);
- } else {
- QVERIFY(!event.isAccepted());
- QCOMPARE(item->wheelCount, 0);
- }
-
- delete canvas;
-}
-
-class HoverItem : public QQuickItem
-{
-Q_OBJECT
-public:
- HoverItem(QQuickItem *parent = 0)
- : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
- { }
- void resetCounters() {
- hoverEnterCount = 0;
- hoverMoveCount = 0;
- hoverLeaveCount = 0;
- }
- int hoverEnterCount;
- int hoverMoveCount;
- int hoverLeaveCount;
-protected:
- virtual void hoverEnterEvent(QHoverEvent *event) {
- event->accept();
- ++hoverEnterCount;
- }
- virtual void hoverMoveEvent(QHoverEvent *event) {
- event->accept();
- ++hoverMoveCount;
- }
- virtual void hoverLeaveEvent(QHoverEvent *event) {
- event->accept();
- ++hoverLeaveCount;
- }
-};
-
-void tst_qquickitem::hoverEvent_data()
-{
- QTest::addColumn<bool>("visible");
- QTest::addColumn<bool>("enabled");
- QTest::addColumn<bool>("acceptHoverEvents");
-
- QTest::newRow("visible, enabled, accept hover") << true << true << true;
- QTest::newRow("visible, disabled, accept hover") << true << false << true;
- QTest::newRow("invisible, enabled, accept hover") << false << true << true;
- QTest::newRow("invisible, disabled, accept hover") << false << false << true;
-
- QTest::newRow("visible, enabled, not accept hover") << true << true << false;
- QTest::newRow("visible, disabled, not accept hover") << true << false << false;
- QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
- QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
-}
-
-// ### For some unknown reason QTest::mouseMove() isn't working correctly.
-static void sendMouseMove(QObject *object, const QPoint &position)
-{
- QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
- QApplication::sendEvent(object, &moveEvent);
-}
-
-void tst_qquickitem::hoverEvent()
-{
- QFETCH(bool, visible);
- QFETCH(bool, enabled);
- QFETCH(bool, acceptHoverEvents);
-
- QQuickCanvas *canvas = new QQuickCanvas();
- canvas->resize(200, 200);
- canvas->show();
-
- HoverItem *item = new HoverItem;
- item->setSize(QSizeF(100, 100));
- item->setParentItem(canvas->rootItem());
-
- item->setEnabled(enabled);
- item->setVisible(visible);
- item->setAcceptHoverEvents(acceptHoverEvents);
-
- const QPoint outside(150, 150);
- const QPoint inside(50, 50);
- const QPoint anotherInside(51, 51);
-
- sendMouseMove(canvas, outside);
- item->resetCounters();
-
- // Enter, then move twice inside, then leave.
- sendMouseMove(canvas, inside);
- sendMouseMove(canvas, anotherInside);
- sendMouseMove(canvas, inside);
- sendMouseMove(canvas, outside);
-
- const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
- if (shouldReceiveHoverEvents) {
- QCOMPARE(item->hoverEnterCount, 1);
- QCOMPARE(item->hoverMoveCount, 2);
- QCOMPARE(item->hoverLeaveCount, 1);
- } else {
- QCOMPARE(item->hoverEnterCount, 0);
- QCOMPARE(item->hoverMoveCount, 0);
- QCOMPARE(item->hoverLeaveCount, 0);
- }
-
- delete canvas;
-}
-
-void tst_qquickitem::hoverEventInParent()
-{
- QQuickCanvas *canvas = new QQuickCanvas();
- canvas->resize(200, 200);
- canvas->show();
-
- HoverItem *parentItem = new HoverItem(canvas->rootItem());
- parentItem->setSize(QSizeF(200, 200));
- parentItem->setAcceptHoverEvents(true);
-
- HoverItem *leftItem = new HoverItem(parentItem);
- leftItem->setSize(QSizeF(100, 200));
- leftItem->setAcceptHoverEvents(true);
-
- HoverItem *rightItem = new HoverItem(parentItem);
- rightItem->setSize(QSizeF(100, 200));
- rightItem->setPos(QPointF(100, 0));
- rightItem->setAcceptHoverEvents(true);
-
- const QPoint insideLeft(50, 100);
- const QPoint insideRight(150, 100);
-
- sendMouseMove(canvas, insideLeft);
- parentItem->resetCounters();
- leftItem->resetCounters();
- rightItem->resetCounters();
-
- sendMouseMove(canvas, insideRight);
- QCOMPARE(parentItem->hoverEnterCount, 0);
- QCOMPARE(parentItem->hoverLeaveCount, 0);
- QCOMPARE(leftItem->hoverEnterCount, 0);
- QCOMPARE(leftItem->hoverLeaveCount, 1);
- QCOMPARE(rightItem->hoverEnterCount, 1);
- QCOMPARE(rightItem->hoverLeaveCount, 0);
-
- sendMouseMove(canvas, insideLeft);
- QCOMPARE(parentItem->hoverEnterCount, 0);
- QCOMPARE(parentItem->hoverLeaveCount, 0);
- QCOMPARE(leftItem->hoverEnterCount, 1);
- QCOMPARE(leftItem->hoverLeaveCount, 1);
- QCOMPARE(rightItem->hoverEnterCount, 1);
- QCOMPARE(rightItem->hoverLeaveCount, 1);
-
- delete canvas;
-}
-
-void tst_qquickitem::paintOrder_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<int>("op");
- QTest::addColumn<QVariant>("param1");
- QTest::addColumn<QVariant>("param2");
- QTest::addColumn<QStringList>("expected");
-
- QTest::newRow("test 1 noop") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(NoOp) << QVariant() << QVariant()
- << (QStringList() << "1" << "2" << "3");
- QTest::newRow("test 1 add") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(Append) << QVariant("new") << QVariant()
- << (QStringList() << "1" << "2" << "3" << "new");
- QTest::newRow("test 1 remove") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(Remove) << QVariant(1) << QVariant()
- << (QStringList() << "1" << "3");
- QTest::newRow("test 1 stack before") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(StackBefore) << QVariant(2) << QVariant(1)
- << (QStringList() << "1" << "3" << "2");
- QTest::newRow("test 1 stack after") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(StackAfter) << QVariant(0) << QVariant(1)
- << (QStringList() << "2" << "1" << "3");
- QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(SetZ) << QVariant(1) << QVariant(qreal(1.))
- << (QStringList() << "1" << "3" << "2");
-
- QTest::newRow("test 2 noop") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(NoOp) << QVariant() << QVariant()
- << (QStringList() << "1" << "3" << "2");
- QTest::newRow("test 2 add") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(Append) << QVariant("new") << QVariant()
- << (QStringList() << "1" << "3" << "new" << "2");
- QTest::newRow("test 2 remove 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(Remove) << QVariant(1) << QVariant()
- << (QStringList() << "1" << "3");
- QTest::newRow("test 2 remove 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(Remove) << QVariant(2) << QVariant()
- << (QStringList() << "1" << "2");
- QTest::newRow("test 2 stack before 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(StackBefore) << QVariant(1) << QVariant(0)
- << (QStringList() << "1" << "3" << "2");
- QTest::newRow("test 2 stack before 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(StackBefore) << QVariant(2) << QVariant(0)
- << (QStringList() << "3" << "1" << "2");
- QTest::newRow("test 2 stack after 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(StackAfter) << QVariant(0) << QVariant(1)
- << (QStringList() << "1" << "3" << "2");
- QTest::newRow("test 2 stack after 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
- << int(StackAfter) << QVariant(0) << QVariant(2)
- << (QStringList() << "3" << "1" << "2");
- QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
- << int(SetZ) << QVariant(2) << QVariant(qreal(2.))
- << (QStringList() << "1" << "2" << "3");
-}
-
-void tst_qquickitem::paintOrder()
-{
- QFETCH(QUrl, source);
- QFETCH(int, op);
- QFETCH(QVariant, param1);
- QFETCH(QVariant, param2);
- QFETCH(QStringList, expected);
-
- QQuickView view;
- view.setSource(source);
-
- QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
- QVERIFY(root);
-
- switch (op) {
- case Append: {
- QQuickItem *item = new QQuickItem(root);
- item->setObjectName(param1.toString());
- }
- break;
- case Remove: {
- QQuickItem *item = root->childItems().at(param1.toInt());
- delete item;
- }
- break;
- case StackBefore: {
- QQuickItem *item1 = root->childItems().at(param1.toInt());
- QQuickItem *item2 = root->childItems().at(param2.toInt());
- item1->stackBefore(item2);
- }
- break;
- case StackAfter: {
- QQuickItem *item1 = root->childItems().at(param1.toInt());
- QQuickItem *item2 = root->childItems().at(param2.toInt());
- item1->stackAfter(item2);
- }
- break;
- case SetZ: {
- QQuickItem *item = root->childItems().at(param1.toInt());
- item->setZ(param2.toReal());
- }
- break;
- default:
- break;
- }
-
- QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
-
- QStringList items;
- for (int i = 0; i < list.count(); ++i)
- items << list.at(i)->objectName();
-
- QCOMPARE(items, expected);
-}
-
-
-QTEST_MAIN(tst_qquickitem)
-
-#include "tst_qquickitem.moc"
diff --git a/tests/auto/declarative/qquickitem2/qquickitem2.pro b/tests/auto/declarative/qquickitem2/qquickitem2.pro
deleted file mode 100644
index 2fe1eb1e3a..0000000000
--- a/tests/auto/declarative/qquickitem2/qquickitem2.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickitem2
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickitem.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qquickitem2/tst_qquickitem.cpp b/tests/auto/declarative/qquickitem2/tst_qquickitem.cpp
deleted file mode 100644
index 3604128ccd..0000000000
--- a/tests/auto/declarative/qquickitem2/tst_qquickitem.cpp
+++ /dev/null
@@ -1,1254 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquickitem_p.h>
-#include "../shared/util.h"
-
-class tst_QQuickItem : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickItem();
-
-private slots:
- void initTestCase();
- void keys();
- void keysProcessingOrder();
- void keyNavigation();
- void keyNavigation_RightToLeft();
- void keyNavigation_skipNotVisible();
- void keyNavigation_implicitSetting();
- void layoutMirroring();
- void layoutMirroringIllegalParent();
- void smooth();
- void clip();
- void mapCoordinates();
- void mapCoordinates_data();
- void propertyChanges();
- void transforms();
- void transforms_data();
- void childrenRect();
- void childrenRectBug();
- void childrenRectBug2();
- void childrenRectBug3();
-
- void childrenProperty();
- void resourcesProperty();
-
- void transformCrash();
- void implicitSize();
- void qtbug_16871();
-private:
- QDeclarativeEngine engine;
-};
-
-template<typename T>
-T *findItem(QQuickItem *parent, const QString &objectName)
-{
- if (!parent)
- return 0;
-
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->QQuickItem::children().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
- return static_cast<T*>(item);
- item = findItem<T>(item, objectName);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-class KeysTestObject : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool processLast READ processLast NOTIFY processLastChanged)
-
-public:
- KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0), mLast(false) {}
-
- void reset() {
- mKey = 0;
- mText = QString();
- mModifiers = 0;
- mForwardedKey = 0;
- }
-
- bool processLast() const { return mLast; }
- void setProcessLast(bool b) {
- if (b != mLast) {
- mLast = b;
- emit processLastChanged();
- }
- }
-
-public slots:
- void keyPress(int key, QString text, int modifiers) {
- mKey = key;
- mText = text;
- mModifiers = modifiers;
- }
- void keyRelease(int key, QString text, int modifiers) {
- mKey = key;
- mText = text;
- mModifiers = modifiers;
- }
- void forwardedKey(int key) {
- mForwardedKey = key;
- }
-
-signals:
- void processLastChanged();
-
-public:
- int mKey;
- QString mText;
- int mModifiers;
- int mForwardedKey;
- bool mLast;
-
-private:
-};
-
-class KeyTestItem : public QQuickItem
-{
- Q_OBJECT
-public:
- KeyTestItem(QQuickItem *parent=0) : QQuickItem(parent), mKey(0) {}
-
-protected:
- void keyPressEvent(QKeyEvent *e) {
- mKey = e->key();
-
- if (e->key() == Qt::Key_A)
- e->accept();
- else
- e->ignore();
- }
-
- void keyReleaseEvent(QKeyEvent *e) {
- if (e->key() == Qt::Key_B)
- e->accept();
- else
- e->ignore();
- }
-
-public:
- int mKey;
-};
-
-QML_DECLARE_TYPE(KeyTestItem);
-
-
-tst_QQuickItem::tst_QQuickItem()
-{
-}
-
-void tst_QQuickItem::initTestCase()
-{
- qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
-}
-
-void tst_QQuickItem::keys()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- KeysTestObject *testObject = new KeysTestObject;
- canvas->rootContext()->setContextProperty("keysTestObject", testObject);
-
- canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
- canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(true));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keystest.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QVERIFY(canvas->rootObject());
- QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
-
- QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_A));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
- QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(!key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_A));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
- QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_Return));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
- QCOMPARE(testObject->mText, QLatin1String("Return"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_0));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
- QCOMPARE(testObject->mText, QLatin1String("0"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_9));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
- QCOMPARE(testObject->mText, QLatin1String("9"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(!key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
- QCOMPARE(testObject->mText, QLatin1String("Tab"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
- QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
- QCOMPARE(testObject->mText, QLatin1String("Backtab"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(false));
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_A));
- QCOMPARE(testObject->mForwardedKey, 0);
- QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(!key.isAccepted());
-
- testObject->reset();
-
- canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
- QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), false);
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, 0);
- QVERIFY(!key.isAccepted());
-
- canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
- QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_Return));
- QVERIFY(key.isAccepted());
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickItem::keysProcessingOrder()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- KeysTestObject *testObject = new KeysTestObject;
- canvas->rootContext()->setContextProperty("keysTestObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keyspriority.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- KeyTestItem *testItem = qobject_cast<KeyTestItem*>(canvas->rootObject());
- QVERIFY(testItem);
-
- QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_A));
- QCOMPARE(testObject->mText, QLatin1String("A"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- testObject->setProcessLast(true);
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, 0);
- QVERIFY(key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "B", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, int(Qt::Key_B));
- QCOMPARE(testObject->mText, QLatin1String("B"));
- QVERIFY(testObject->mModifiers == Qt::NoModifier);
- QVERIFY(!key.isAccepted());
-
- testObject->reset();
-
- key = QKeyEvent(QEvent::KeyRelease, Qt::Key_B, Qt::NoModifier, "B", false, 1);
- QApplication::sendEvent(canvas, &key);
- QCOMPARE(testObject->mKey, 0);
- QVERIFY(key.isAccepted());
-
- delete canvas;
- delete testObject;
-}
-
-QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString)
-{
- QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
- QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
- return itemPrivate;
-}
-
-QVariant childProperty(QQuickItem *rootItem, const char * itemString, const char * property)
-{
- QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
- return item->property(property);
-}
-
-bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
-{
- QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
- QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
- return itemPrivate->anchors()->mirrored();
-}
-
-void tst_QQuickItem::layoutMirroring()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("layoutmirroring.qml")));
- canvas->show();
-
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootItem);
- QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
- QVERIFY(rootPrivate);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
-
- QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
-
- // load dynamic content using Loader that needs to inherit mirroring
- rootItem->setProperty("state", "newContent");
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
-
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
-
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
-
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
-
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
-
- // disable inheritance
- rootItem->setProperty("childrenInherit", false);
-
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
-
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
-
- // re-enable inheritance
- rootItem->setProperty("childrenInherit", true);
-
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
-
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
-
- //
- // dynamic parenting
- //
- QQuickItem *parentItem1 = new QQuickItem();
- QQuickItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
- QQuickItemPrivate::get(parentItem1)->isMirrorImplicit = false;
- QQuickItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
- QQuickItemPrivate::get(parentItem1)->resolveLayoutMirror();
-
- // inherit in constructor
- QQuickItem *childItem1 = new QQuickItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
-
- // inherit through a parent change
- QQuickItem *childItem2 = new QQuickItem();
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
- childItem2->setParentItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
-
- // stop inherting through a parent change
- QQuickItem *parentItem2 = new QQuickItem();
- QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
- QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
- childItem2->setParentItem(parentItem2);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
-
- delete parentItem1;
- delete parentItem2;
-}
-
-void tst_QQuickItem::layoutMirroringIllegalParent()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
- QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
- QObject *object = component.create();
- QVERIFY(object != 0);
-}
-
-void tst_QQuickItem::keyNavigation()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- QVariant result;
- QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
- Q_RETURN_ARG(QVariant, result)));
- QVERIFY(result.toBool());
-
- // right
- QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // down
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // left
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // up
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // tab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // backtab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- delete canvas;
-}
-
-void tst_QQuickItem::keyNavigation_RightToLeft()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootItem);
- QQuickItemPrivate* rootItemPrivate = QQuickItemPrivate::get(rootItem);
-
- rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true
- rootItemPrivate->isMirrorImplicit = false;
- rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true
- rootItemPrivate->resolveLayoutMirror();
-
- QEvent wa(QEvent::WindowActivate);
- QApplication::sendEvent(canvas, &wa);
- QFocusEvent fe(QEvent::FocusIn);
- QApplication::sendEvent(canvas, &fe);
-
- QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- QVariant result;
- QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
- Q_RETURN_ARG(QVariant, result)));
- QVERIFY(result.toBool());
-
- // right
- QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // left
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- delete canvas;
-}
-
-void tst_QQuickItem::keyNavigation_skipNotVisible()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // Set item 2 to not visible
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- item->setVisible(false);
- QVERIFY(!item->isVisible());
-
- // right
- QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // tab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // backtab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- //Set item 3 to not visible
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- item->setVisible(false);
- QVERIFY(!item->isVisible());
-
- // tab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // backtab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- delete canvas;
-}
-
-void tst_QQuickItem::keyNavigation_implicitSetting()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest_implicit.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QEvent wa(QEvent::WindowActivate);
- QApplication::sendEvent(canvas, &wa);
- QFocusEvent fe(QEvent::FocusIn);
- QApplication::sendEvent(canvas, &fe);
-
- QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- QVariant result;
- QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
- Q_RETURN_ARG(QVariant, result)));
- QVERIFY(result.toBool());
-
- // right
- QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // back to item1
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // down
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // move to item4
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // left
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // back to item4
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // up
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item2");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // back to item4
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // tab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item1");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // back to item4
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item4");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- // backtab
- key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
- QApplication::sendEvent(canvas, &key);
- QVERIFY(key.isAccepted());
-
- item = findItem<QQuickItem>(canvas->rootObject(), "item3");
- QVERIFY(item);
- QVERIFY(item->hasActiveFocus());
-
- delete canvas;
-}
-
-void tst_QQuickItem::smooth()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0; Item { smooth: false; }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QSignalSpy spy(item, SIGNAL(smoothChanged(bool)));
-
- QVERIFY(item);
- QVERIFY(!item->smooth());
-
- item->setSmooth(true);
- QVERIFY(item->smooth());
- QCOMPARE(spy.count(),1);
- QList<QVariant> arguments = spy.first();
- QVERIFY(arguments.count() == 1);
- QVERIFY(arguments.at(0).toBool() == true);
-
- item->setSmooth(true);
- QCOMPARE(spy.count(),1);
-
- item->setSmooth(false);
- QVERIFY(!item->smooth());
- QCOMPARE(spy.count(),2);
- item->setSmooth(false);
- QCOMPARE(spy.count(),2);
-
- delete item;
-}
-
-void tst_QQuickItem::clip()
-{
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0\nItem { clip: false\n }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QSignalSpy spy(item, SIGNAL(clipChanged(bool)));
-
- QVERIFY(item);
- QVERIFY(!item->clip());
-
- item->setClip(true);
- QVERIFY(item->clip());
-
- QList<QVariant> arguments = spy.first();
- QVERIFY(arguments.count() == 1);
- QVERIFY(arguments.at(0).toBool() == true);
-
- QCOMPARE(spy.count(),1);
- item->setClip(true);
- QCOMPARE(spy.count(),1);
-
- item->setClip(false);
- QVERIFY(!item->clip());
- QCOMPARE(spy.count(),2);
- item->setClip(false);
- QCOMPARE(spy.count(),2);
-
- delete item;
-}
-
-void tst_QQuickItem::mapCoordinates()
-{
- QFETCH(int, x);
- QFETCH(int, y);
-
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(300, 300));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root != 0);
- QQuickItem *a = findItem<QQuickItem>(canvas->rootObject(), "itemA");
- QVERIFY(a != 0);
- QQuickItem *b = findItem<QQuickItem>(canvas->rootObject(), "itemB");
- QVERIFY(b != 0);
-
- QVariant result;
-
- QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
-
- QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
-
- QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
-
- QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromScene(QPointF(x, y)));
-
- QString warning1 = QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")).toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
- QString warning2 = QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")).toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
-
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
- QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QVERIFY(result.toBool());
-
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
- QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
- Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
- QVERIFY(result.toBool());
-
- delete canvas;
-}
-
-void tst_QQuickItem::mapCoordinates_data()
-{
- QTest::addColumn<int>("x");
- QTest::addColumn<int>("y");
-
- for (int i=-20; i<=20; i+=10)
- QTest::newRow(QTest::toString(i)) << i << i;
-}
-
-void tst_QQuickItem::transforms_data()
-{
- QTest::addColumn<QByteArray>("qml");
- QTest::addColumn<QTransform>("transform");
- QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
- << QTransform(1,0,0,0,1,0,10,20,1);
- QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
- << QTransform(0,1,0,-1,0,0,0,0,1);
- QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2 }")
- << QTransform(1.5,0,0,0,-2,0,0,0,1);
- QTest::newRow("sequence") << QByteArray("[ Translate { x: 10; y: 20 }, Scale { xScale: 1.5; yScale: -2 } ]")
- << QTransform(1,0,0,0,1,0,10,20,1) * QTransform(1.5,0,0,0,-2,0,0,0,1);
-}
-
-void tst_QQuickItem::transforms()
-{
- QFETCH(QByteArray, qml);
- QFETCH(QTransform, transform);
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(item->itemTransform(0,0), transform);
-}
-
-void tst_QQuickItem::childrenProperty()
-{
- QDeclarativeComponent component(&engine, TESTDATA("childrenProperty.qml"));
-
- QObject *o = component.create();
- QVERIFY(o != 0);
-
- QCOMPARE(o->property("test1").toBool(), true);
- QCOMPARE(o->property("test2").toBool(), true);
- QCOMPARE(o->property("test3").toBool(), true);
- QCOMPARE(o->property("test4").toBool(), true);
- QCOMPARE(o->property("test5").toBool(), true);
- delete o;
-}
-
-void tst_QQuickItem::resourcesProperty()
-{
- QDeclarativeComponent component(&engine, TESTDATA("resourcesProperty.qml"));
-
- QObject *o = component.create();
- QVERIFY(o != 0);
-
- QCOMPARE(o->property("test1").toBool(), true);
- QCOMPARE(o->property("test2").toBool(), true);
- QCOMPARE(o->property("test3").toBool(), true);
- QCOMPARE(o->property("test4").toBool(), true);
- QCOMPARE(o->property("test5").toBool(), true);
- delete o;
-}
-
-void tst_QQuickItem::propertyChanges()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(300, 300));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
-
- QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item");
- QQuickItem *parentItem = findItem<QQuickItem>(canvas->rootObject(), "parentItem");
-
- QVERIFY(item);
- QVERIFY(parentItem);
-
- QSignalSpy parentSpy(item, SIGNAL(parentChanged(QQuickItem *)));
- QSignalSpy widthSpy(item, SIGNAL(widthChanged()));
- QSignalSpy heightSpy(item, SIGNAL(heightChanged()));
- QSignalSpy baselineOffsetSpy(item, SIGNAL(baselineOffsetChanged(qreal)));
- QSignalSpy childrenRectSpy(parentItem, SIGNAL(childrenRectChanged(QRectF)));
- QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool)));
- QSignalSpy wantsFocusSpy(parentItem, SIGNAL(activeFocusChanged(bool)));
- QSignalSpy childrenChangedSpy(parentItem, SIGNAL(childrenChanged()));
- QSignalSpy xSpy(item, SIGNAL(xChanged()));
- QSignalSpy ySpy(item, SIGNAL(yChanged()));
-
- item->setParentItem(parentItem);
- item->setWidth(100.0);
- item->setHeight(200.0);
- item->setFocus(true);
- item->setBaselineOffset(10.0);
-
- QCOMPARE(item->parentItem(), parentItem);
- QCOMPARE(parentSpy.count(),1);
- QList<QVariant> parentArguments = parentSpy.first();
- QVERIFY(parentArguments.count() == 1);
- QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
- QCOMPARE(childrenChangedSpy.count(),1);
-
- item->setParentItem(parentItem);
- QCOMPARE(childrenChangedSpy.count(),1);
-
- QCOMPARE(item->width(), 100.0);
- QCOMPARE(widthSpy.count(),1);
-
- QCOMPARE(item->height(), 200.0);
- QCOMPARE(heightSpy.count(),1);
-
- QCOMPARE(item->baselineOffset(), 10.0);
- QCOMPARE(baselineOffsetSpy.count(),1);
- QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
- QVERIFY(baselineOffsetArguments.count() == 1);
- QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
-
- QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
- QCOMPARE(childrenRectSpy.count(),1);
- QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
- QVERIFY(childrenRectArguments.count() == 1);
- QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
-
- QCOMPARE(item->hasActiveFocus(), true);
- QCOMPARE(focusSpy.count(),1);
- QList<QVariant> focusArguments = focusSpy.first();
- QVERIFY(focusArguments.count() == 1);
- QCOMPARE(focusArguments.at(0).toBool(), true);
-
- QCOMPARE(parentItem->hasActiveFocus(), false);
- QCOMPARE(parentItem->hasFocus(), false);
- QCOMPARE(wantsFocusSpy.count(),0);
-
- item->setX(10.0);
- QCOMPARE(item->x(), 10.0);
- QCOMPARE(xSpy.count(), 1);
-
- item->setY(10.0);
- QCOMPARE(item->y(), 10.0);
- QCOMPARE(ySpy.count(), 1);
-
- delete canvas;
-}
-
-void tst_QQuickItem::childrenRect()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRect.qml")));
- canvas->setBaseSize(QSize(240,320));
- canvas->show();
-
- QQuickItem *o = canvas->rootObject();
- QQuickItem *item = o->findChild<QQuickItem*>("testItem");
- QCOMPARE(item->width(), qreal(0));
- QCOMPARE(item->height(), qreal(0));
-
- o->setProperty("childCount", 1);
- QCOMPARE(item->width(), qreal(10));
- QCOMPARE(item->height(), qreal(20));
-
- o->setProperty("childCount", 5);
- QCOMPARE(item->width(), qreal(50));
- QCOMPARE(item->height(), qreal(100));
-
- o->setProperty("childCount", 0);
- QCOMPARE(item->width(), qreal(0));
- QCOMPARE(item->height(), qreal(0));
-
- delete o;
- delete canvas;
-}
-
-// QTBUG-11383
-void tst_QQuickItem::childrenRectBug()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug.qml")));
- canvas->show();
-
- QQuickItem *o = canvas->rootObject();
- QQuickItem *item = o->findChild<QQuickItem*>("theItem");
- QCOMPARE(item->width(), qreal(200));
- QCOMPARE(item->height(), qreal(100));
- QCOMPARE(item->x(), qreal(100));
-
- delete canvas;
-}
-
-// QTBUG-11465
-void tst_QQuickItem::childrenRectBug2()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug2.qml")));
- canvas->show();
-
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(canvas->rootObject());
- QVERIFY(rect);
- QQuickItem *item = rect->findChild<QQuickItem*>("theItem");
- QCOMPARE(item->width(), qreal(100));
- QCOMPARE(item->height(), qreal(110));
- QCOMPARE(item->x(), qreal(130));
-
- QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- rectPrivate->setState("row");
- QCOMPARE(item->width(), qreal(210));
- QCOMPARE(item->height(), qreal(50));
- QCOMPARE(item->x(), qreal(75));
-
- delete canvas;
-}
-
-// QTBUG-12722
-void tst_QQuickItem::childrenRectBug3()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug3.qml")));
- canvas->show();
-
- //don't crash on delete
- delete canvas;
-}
-
-// QTBUG-13893
-void tst_QQuickItem::transformCrash()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("transformCrash.qml")));
- canvas->show();
-
- delete canvas;
-}
-
-void tst_QQuickItem::implicitSize()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("implicitsize.qml")));
- canvas->show();
-
- QQuickItem *item = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(item);
- QCOMPARE(item->width(), qreal(80));
- QCOMPARE(item->height(), qreal(60));
-
- QCOMPARE(item->implicitWidth(), qreal(200));
- QCOMPARE(item->implicitHeight(), qreal(100));
-
- QMetaObject::invokeMethod(item, "resetSize");
-
- QCOMPARE(item->width(), qreal(200));
- QCOMPARE(item->height(), qreal(100));
-
- QMetaObject::invokeMethod(item, "changeImplicit");
-
- QCOMPARE(item->implicitWidth(), qreal(150));
- QCOMPARE(item->implicitHeight(), qreal(80));
- QCOMPARE(item->width(), qreal(150));
- QCOMPARE(item->height(), qreal(80));
-
- delete canvas;
-}
-
-void tst_QQuickItem::qtbug_16871()
-{
- QDeclarativeComponent component(&engine, TESTDATA("qtbug_16871.qml"));
- QObject *o = component.create();
- QVERIFY(o != 0);
- delete o;
-}
-
-QTEST_MAIN(tst_QQuickItem)
-
-#include "tst_qquickitem.moc"
diff --git a/tests/auto/declarative/qquicklistview/qquicklistview.pro b/tests/auto/declarative/qquicklistview/qquicklistview.pro
deleted file mode 100644
index 3ffd3a7dc6..0000000000
--- a/tests/auto/declarative/qquicklistview/qquicklistview.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquicklistview
-macx:CONFIG -= app_bundle
-
-HEADERS += incrementalmodel.h
-SOURCES += tst_qquicklistview.cpp incrementalmodel.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private widgets widgets-private v8-private opengl-private testlib
diff --git a/tests/auto/declarative/qquicklistview/tst_qquicklistview.cpp b/tests/auto/declarative/qquicklistview/tst_qquicklistview.cpp
deleted file mode 100644
index 3b41600eb6..0000000000
--- a/tests/auto/declarative/qquicklistview/tst_qquicklistview.cpp
+++ /dev/null
@@ -1,4379 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtWidgets/QStringListModel>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-#include <QtDeclarative/private/qquickitem_p.h>
-#include <QtDeclarative/private/qquicklistview_p.h>
-#include <QtDeclarative/private/qquicktext_p.h>
-#include <QtDeclarative/private/qquickvisualitemmodel_p.h>
-#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
-#include <QtDeclarative/private/qlistmodelinterface_p.h>
-#include <QtDeclarative/private/qdeclarativechangeset_p.h>
-#include "../shared/util.h"
-#include "incrementalmodel.h"
-#include <math.h>
-
-Q_DECLARE_METATYPE(Qt::LayoutDirection)
-Q_DECLARE_METATYPE(QQuickListView::Orientation)
-
-class tst_QQuickListView : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickListView();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- // Test both QListModelInterface and QAbstractItemModel model types
- void qListModelInterface_items();
- void qAbstractItemModel_items();
-
- void qListModelInterface_changed();
- void qAbstractItemModel_changed();
-
- void qListModelInterface_inserted();
- void qListModelInterface_inserted_more();
- void qListModelInterface_inserted_more_data();
- void qAbstractItemModel_inserted();
- void qAbstractItemModel_inserted_more();
- void qAbstractItemModel_inserted_more_data();
-
- void qListModelInterface_removed();
- void qAbstractItemModel_removed();
-
- void qListModelInterface_moved();
- void qListModelInterface_moved_data();
- void qAbstractItemModel_moved();
- void qAbstractItemModel_moved_data();
-
- void multipleChanges();
- void multipleChanges_data();
-
- void qListModelInterface_clear();
- void qAbstractItemModel_clear();
-
- void insertBeforeVisible();
- void insertBeforeVisible_data();
- void swapWithFirstItem();
- void itemList();
- void currentIndex_delayedItemCreation();
- void currentIndex_delayedItemCreation_data();
- void currentIndex();
- void noCurrentIndex();
- void enforceRange();
- void enforceRange_withoutHighlight();
- void spacing();
- void sections();
- void sectionsPositioning();
- void sectionsDelegate();
- void cacheBuffer();
- void positionViewAtIndex();
- void resetModel();
- void propertyChanges();
- void componentChanges();
- void modelChanges();
- void manualHighlight();
- void header();
- void header_data();
- void header_delayItemCreation();
- void footer();
- void footer_data();
- void headerFooter();
- void resizeView();
- void resizeViewAndRepaint();
- void sizeLessThan1();
- void QTBUG_14821();
- void resizeDelegate();
- void resizeFirstDelegate();
- void QTBUG_16037();
- void indexAt();
- void incrementalModel();
- void onAdd();
- void onAdd_data();
- void onRemove();
- void onRemove_data();
- void rightToLeft();
- void test_mirroring();
- void margins();
- void creationContext();
- void snapToItem_data();
- void snapToItem();
-
- void QTBUG_9791();
- void QTBUG_11105();
- void QTBUG_21742();
-
- void asynchronous();
-
-private:
- template <class T> void items();
- template <class T> void changed();
- template <class T> void inserted();
- template <class T> void inserted_more();
- template <class T> void removed(bool animated);
- template <class T> void moved();
- template <class T> void clear();
- QQuickView *createView();
- void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
- QQuickItem *findVisibleChild(QQuickItem *parent, const QString &objectName);
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &id, int index=-1);
- template<typename T>
- QList<T*> findItems(QQuickItem *parent, const QString &objectName);
- void dumpTree(QQuickItem *parent, int depth = 0);
-
- void inserted_more_data();
- void moved_data();
-};
-
-void tst_QQuickListView::initTestCase()
-{
-}
-
-void tst_QQuickListView::cleanupTestCase()
-{
-
-}
-class TestObject : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool error READ error WRITE setError NOTIFY changedError)
- Q_PROPERTY(bool animate READ animate NOTIFY changedAnim)
- Q_PROPERTY(bool invalidHighlight READ invalidHighlight NOTIFY changedHl)
- Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
-
-public:
- TestObject(QObject *parent = 0)
- : QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
- , mCacheBuffer(0) {}
-
- bool error() const { return mError; }
- void setError(bool err) { mError = err; emit changedError(); }
-
- bool animate() const { return mAnimate; }
- void setAnimate(bool anim) { mAnimate = anim; emit changedAnim(); }
-
- bool invalidHighlight() const { return mInvalidHighlight; }
- void setInvalidHighlight(bool invalid) { mInvalidHighlight = invalid; emit changedHl(); }
-
- int cacheBuffer() const { return mCacheBuffer; }
- void setCacheBuffer(int buffer) { mCacheBuffer = buffer; emit changedCacheBuffer(); }
-
-signals:
- void changedError();
- void changedAnim();
- void changedHl();
- void changedCacheBuffer();
-
-public:
- bool mError;
- bool mAnimate;
- bool mInvalidHighlight;
- int mCacheBuffer;
-};
-
-template<typename T>
-void tst_qquicklistview_move(int from, int to, int n, T *items)
-{
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
- if (n == 1) {
- items->move(from, to);
- } else {
- T replaced;
- int i=0;
- typename T::ConstIterator it=items->begin(); it += from+n;
- for (; i<to-from; ++i,++it)
- replaced.append(*it);
- i=0;
- it=items->begin(); it += from;
- for (; i<n; ++i,++it)
- replaced.append(*it);
- typename T::ConstIterator f=replaced.begin();
- typename T::Iterator t=items->begin(); t += from;
- for (; f != replaced.end(); ++f, ++t)
- *t = *f;
- }
-}
-
-class TestModel : public QListModelInterface
-{
- Q_OBJECT
-public:
- TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
- ~TestModel() {}
-
- enum Roles { Name, Number };
-
- QString name(int index) const { return list.at(index).first; }
- QString number(int index) const { return list.at(index).second; }
-
- int count() const { return list.count(); }
-
- QList<int> roles() const { return QList<int>() << Name << Number; }
- QString toString(int role) const {
- switch (role) {
- case Name:
- return "name";
- case Number:
- return "number";
- default:
- return "";
- }
- }
-
- QVariant data(int index, int role) const
- {
- if (role==0)
- return list.at(index).first;
- if (role==1)
- return list.at(index).second;
- return QVariant();
- }
- QHash<int, QVariant> data(int index, const QList<int> &roles) const {
- QHash<int,QVariant> returnHash;
-
- for (int i = 0; i < roles.size(); ++i) {
- int role = roles.at(i);
- QVariant info;
- switch (role) {
- case Name:
- info = list.at(index).first;
- break;
- case Number:
- info = list.at(index).second;
- break;
- default:
- break;
- }
- returnHash.insert(role, info);
- }
- return returnHash;
- }
-
- void addItem(const QString &name, const QString &number) {
- list.append(QPair<QString,QString>(name, number));
- emit itemsInserted(list.count()-1, 1);
- }
-
- void insertItem(int index, const QString &name, const QString &number) {
- list.insert(index, QPair<QString,QString>(name, number));
- emit itemsInserted(index, 1);
- }
-
- void insertItems(int index, const QList<QPair<QString, QString> > &items) {
- for (int i=0; i<items.count(); i++)
- list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
- emit itemsInserted(index, items.count());
- }
-
- void removeItem(int index) {
- list.removeAt(index);
- emit itemsRemoved(index, 1);
- }
-
- void removeItems(int index, int count) {
- int c = count;
- while (c--)
- list.removeAt(index);
- emit itemsRemoved(index, count);
- }
-
- void moveItem(int from, int to) {
- list.move(from, to);
- emit itemsMoved(from, to, 1);
- }
-
- void moveItems(int from, int to, int count) {
- tst_qquicklistview_move(from, to, count, &list);
- emit itemsMoved(from, to, count);
- }
-
- void modifyItem(int index, const QString &name, const QString &number) {
- list[index] = QPair<QString,QString>(name, number);
- emit itemsChanged(index, 1, roles());
- }
-
- void clear() {
- int count = list.count();
- list.clear();
- emit itemsRemoved(0, count);
- }
-
-private:
- QList<QPair<QString,QString> > list;
-};
-
-
-class TestModel2 : public QAbstractListModel
-{
-public:
- enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
-
- TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
- QHash<int, QByteArray> roles;
- roles[Name] = "name";
- roles[Number] = "number";
- setRoleNames(roles);
- }
-
- int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
- QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
- QVariant rv;
- if (role == Name)
- rv = list.at(index.row()).first;
- else if (role == Number)
- rv = list.at(index.row()).second;
-
- return rv;
- }
-
- int count() const { return rowCount(); }
- QString name(int index) const { return list.at(index).first; }
- QString number(int index) const { return list.at(index).second; }
-
- void addItem(const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), list.count(), list.count());
- list.append(QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void addItems(const QList<QPair<QString, QString> > &items) {
- emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
- for (int i=0; i<items.count(); i++)
- list.append(QPair<QString,QString>(items[i].first, items[i].second));
- emit endInsertRows();
- }
-
- void insertItem(int index, const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), index, index);
- list.insert(index, QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void insertItems(int index, const QList<QPair<QString, QString> > &items) {
- emit beginInsertRows(QModelIndex(), index, index+items.count()-1);
- for (int i=0; i<items.count(); i++)
- list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
- emit endInsertRows();
- }
-
- void removeItem(int index) {
- emit beginRemoveRows(QModelIndex(), index, index);
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void removeItems(int index, int count) {
- emit beginRemoveRows(QModelIndex(), index, index+count-1);
- while (count--)
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void moveItem(int from, int to) {
- emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
- list.move(from, to);
- emit endMoveRows();
- }
-
- void moveItems(int from, int to, int count) {
- emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
- tst_qquicklistview_move(from, to, count, &list);
- emit endMoveRows();
- }
-
- void modifyItem(int idx, const QString &name, const QString &number) {
- list[idx] = QPair<QString,QString>(name, number);
- emit dataChanged(index(idx,0), index(idx,0));
- }
-
- void clear() {
- int count = list.count();
- emit beginRemoveRows(QModelIndex(), 0, count-1);
- list.clear();
- emit endRemoveRows();
- }
-
-private:
- QList<QPair<QString,QString> > list;
-};
-
-tst_QQuickListView::tst_QQuickListView()
-{
-}
-
-template <class T>
-void tst_QQuickListView::items()
-{
- QQuickView *canvas = createView();
-
- T model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
-
- QTRY_VERIFY(listview->highlightItem() != 0);
- QTRY_COMPARE(listview->count(), model.count());
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- // current item should be first item
- QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
-
- for (int i = 0; i < model.count(); ++i) {
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- // switch to other delegate
- testObject->setAnimate(true);
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
- QTRY_VERIFY(listview->currentItem());
-
- // set invalid highlight
- testObject->setInvalidHighlight(true);
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
- QTRY_VERIFY(listview->currentItem());
- QTRY_VERIFY(listview->highlightItem() == 0);
-
- // back to normal highlight
- testObject->setInvalidHighlight(false);
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
- QTRY_VERIFY(listview->currentItem());
- QTRY_VERIFY(listview->highlightItem() != 0);
-
- // set an empty model and confirm that items are destroyed
- T model2;
- ctxt->setContextProperty("testModel", &model2);
-
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_VERIFY(itemCount == 0);
-
- QTRY_COMPARE(listview->highlightResizeSpeed(), 1000.0);
- QTRY_COMPARE(listview->highlightMoveSpeed(), 1000.0);
-
- delete canvas;
- delete testObject;
-}
-
-
-template <class T>
-void tst_QQuickListView::changed()
-{
- QQuickView *canvas = createView();
-
- T model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickFlickable *listview = findItem<QQuickFlickable>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.modifyItem(1, "Will", "9876");
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- delete canvas;
- delete testObject;
-}
-
-template <class T>
-void tst_QQuickListView::inserted()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- T model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.insertItem(1, "Will", "9876");
-
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count(); ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_COMPARE(item->y(), i*20.0);
- }
-
- model.insertItem(0, "Foo", "1111"); // zero index, and current item
-
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
-
- name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- QTRY_COMPARE(listview->currentIndex(), 1);
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count(); ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_COMPARE(item->y(), i*20.0);
- }
-
- for (int i = model.count(); i < 30; ++i)
- model.insertItem(i, "Hello", QString::number(i));
-
- listview->setContentY(80);
-
- // Insert item outside visible area
- model.insertItem(1, "Hello", "1324");
-
- QTRY_VERIFY(listview->contentY() == 80);
-
- // Confirm items positioned correctly
- for (int i = 5; i < 5+15; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.0 - 20.0);
- }
-
-// QTRY_COMPARE(listview->contentItemHeight(), model.count() * 20.0);
-
- // QTBUG-19675
- model.clear();
- model.insertItem(0, "Hello", "1234");
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->y(), 0.);
- QVERIFY(listview->contentY() == 0);
-
- delete canvas;
- delete testObject;
-}
-
-template <class T>
-void tst_QQuickListView::inserted_more()
-{
- QFETCH(qreal, contentY);
- QFETCH(int, insertIndex);
- QFETCH(int, insertCount);
- QFETCH(qreal, itemsOffsetAfterMove);
-
- QQuickText *name;
- QQuickText *number;
- QQuickView *canvas = createView();
- canvas->show();
-
- T model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- listview->setContentY(contentY);
-
- QList<QPair<QString, QString> > newData;
- for (int i=0; i<insertCount; i++)
- newData << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.insertItems(insertIndex, newData);
- QTRY_COMPARE(listview->property("count").toInt(), model.count());
-
- // check visibleItems.first() is in correct position
- QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item0);
- QCOMPARE(item0->y(), itemsOffsetAfterMove);
-
- QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
- int firstVisibleIndex = -1;
- for (int i=0; i<items.count(); i++) {
- if (items[i]->y() >= contentY) {
- QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
- firstVisibleIndex = e.evaluate().toInt();
- break;
- }
- }
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::inserted_more_data()
-{
- QTest::addColumn<qreal>("contentY");
- QTest::addColumn<int>("insertIndex");
- QTest::addColumn<int>("insertCount");
- QTest::addColumn<qreal>("itemsOffsetAfterMove");
-
- QTest::newRow("add 1, before visible items")
- << 80.0 // show 4-19
- << 3 << 1
- << -20.0; // insert above first visible i.e. 0 is at -20, first visible should not move
-
- QTest::newRow("add multiple, before visible")
- << 80.0 // show 4-19
- << 3 << 3
- << -20.0 * 3; // again first visible should not move
-
- QTest::newRow("add 1, at start of visible, content at start")
- << 0.0
- << 0 << 1
- << 0.0;
-
- QTest::newRow("add multiple, start of visible, content at start")
- << 0.0
- << 0 << 3
- << 0.0;
-
- QTest::newRow("add 1, at start of visible, content not at start")
- << 80.0 // show 4-19
- << 4 << 1
- << 0.0;
-
- QTest::newRow("add multiple, at start of visible, content not at start")
- << 80.0 // show 4-19
- << 4 << 3
- << 0.0;
-
-
- QTest::newRow("add 1, at end of visible, content at start")
- << 0.0
- << 15 << 1
- << 0.0;
-
- QTest::newRow("add 1, at end of visible, content at start")
- << 0.0
- << 15 << 3
- << 0.0;
-
- QTest::newRow("add 1, at end of visible, content not at start")
- << 80.0 // show 4-19
- << 19 << 1
- << 0.0;
-
- QTest::newRow("add multiple, at end of visible, content not at start")
- << 80.0 // show 4-19
- << 19 << 3
- << 0.0;
-
-
- QTest::newRow("add 1, after visible, content at start")
- << 0.0
- << 16 << 1
- << 0.0;
-
- QTest::newRow("add 1, after visible, content at start")
- << 0.0
- << 16 << 3
- << 0.0;
-
- QTest::newRow("add 1, after visible, content not at start")
- << 80.0 // show 4-19
- << 20 << 1
- << 0.0;
-
- QTest::newRow("add multiple, after visible, content not at start")
- << 80.0 // show 4-19
- << 20 << 3
- << 0.0;
-}
-
-void tst_QQuickListView::insertBeforeVisible()
-{
- QFETCH(int, insertIndex);
- QFETCH(int, insertCount);
- QFETCH(int, cacheBuffer);
-
- QQuickText *name;
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- listview->setCacheBuffer(cacheBuffer);
-
- // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
- int firstVisibleIndex = 20; // move to an index where the top item is not visible
- listview->setContentY(firstVisibleIndex * 20.0);
- listview->setCurrentIndex(firstVisibleIndex);
- qApp->processEvents();
- QTRY_COMPARE(listview->currentIndex(), firstVisibleIndex);
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
- QVERIFY(item);
- QCOMPARE(item->y(), listview->contentY());
-
- QList<QPair<QString, QString> > newData;
- for (int i=0; i<insertCount; i++)
- newData << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.insertItems(insertIndex, newData);
- QTRY_COMPARE(listview->property("count").toInt(), model.count());
-
- // now, moving to the top of the view should position the inserted items correctly
- int itemsOffsetAfterMove = -(insertCount * 20);
- listview->setCurrentIndex(0);
- QTRY_COMPARE(listview->currentIndex(), 0);
- QTRY_COMPARE(listview->contentY(), 0.0 + itemsOffsetAfterMove);
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::insertBeforeVisible_data()
-{
- QTest::addColumn<int>("insertIndex");
- QTest::addColumn<int>("insertCount");
- QTest::addColumn<int>("cacheBuffer");
-
- QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
- QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
- QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
-
- QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
- QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
- QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
-
- QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 3 << 0;
- QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 3 << 100;
- QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 3 << 500;
-
- QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 3 << 0;
- QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 3 << 100;
- QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 3 << 500;
-}
-
-template <class T>
-void tst_QQuickListView::removed(bool /* animated */)
-{
- QQuickView *canvas = createView();
-
- T model;
- for (int i = 0; i < 50; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.removeItem(1);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- // Remove first item (which is the current item);
- model.removeItem(0); // post: top item starts at 20
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(),i*20.0 + 20.0);
- }
-
- // Remove items not visible
- model.removeItem(18);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(),i*20.0+20.0);
- }
-
- // Remove items before visible
- listview->setContentY(80);
- listview->setCurrentIndex(10);
-
- model.removeItem(1); // post: top item will be at 40
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- // Confirm items positioned correctly
- for (int i = 2; i < 18; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(),40+i*20.0);
- }
-
- // Remove current index
- QTRY_VERIFY(listview->currentIndex() == 9);
- QQuickItem *oldCurrent = listview->currentItem();
- model.removeItem(9);
-
- QTRY_COMPARE(listview->currentIndex(), 9);
- QTRY_VERIFY(listview->currentItem() != oldCurrent);
-
- listview->setContentY(40); // That's the top now
- // let transitions settle.
- QTest::qWait(300);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(),40+i*20.0);
- }
-
- // remove current item beyond visible items.
- listview->setCurrentIndex(20);
- listview->setContentY(40);
- model.removeItem(20);
-
- QTRY_COMPARE(listview->currentIndex(), 20);
- QTRY_VERIFY(listview->currentItem() != 0);
-
- // remove item before current, but visible
- listview->setCurrentIndex(8);
- oldCurrent = listview->currentItem();
- model.removeItem(6);
-
- QTRY_COMPARE(listview->currentIndex(), 7);
- QTRY_VERIFY(listview->currentItem() == oldCurrent);
-
- listview->setContentY(80);
- QTest::qWait(300);
-
- // remove all visible items
- model.removeItems(1, 18);
- QTRY_COMPARE(listview->count() , model.count());
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i+1);
- if (!item) qWarning() << "Item" << i+1 << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(),80+i*20.0);
- }
-
- model.removeItems(1, 17);
- QTRY_COMPARE(listview->count() , model.count());
-
- model.removeItems(2, 1);
- QTRY_COMPARE(listview->count() , model.count());
-
- model.addItem("New", "1");
- QTRY_COMPARE(listview->count() , model.count());
-
- QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", model.count()-1));
- QCOMPARE(name->text(), QString("New"));
-
- // Add some more items so that we don't run out
- model.clear();
- for (int i = 0; i < 50; i++)
- model.addItem("Item" + QString::number(i), "");
-
- // QTBUG-QTBUG-20575
- listview->setCurrentIndex(0);
- listview->setContentY(30);
- model.removeItem(0);
- QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", 0));
-
- // QTBUG-19198 move to end and remove all visible items one at a time.
- listview->positionViewAtEnd();
- for (int i = 0; i < 18; ++i)
- model.removeItems(model.count() - 1, 1);
- QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() > 16);
-
- delete canvas;
- delete testObject;
-}
-
-template <class T>
-void tst_QQuickListView::clear()
-{
- QQuickView *canvas = createView();
-
- T model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- model.clear();
-
- QTRY_VERIFY(listview->count() == 0);
- QTRY_VERIFY(listview->currentItem() == 0);
- QTRY_VERIFY(listview->contentY() == 0);
- QVERIFY(listview->currentIndex() == -1);
-
- // confirm sanity when adding an item to cleared list
- model.addItem("New", "1");
- QTRY_VERIFY(listview->count() == 1);
- QVERIFY(listview->currentItem() != 0);
- QVERIFY(listview->currentIndex() == 0);
-
- delete canvas;
- delete testObject;
-}
-
-template <class T>
-void tst_QQuickListView::moved()
-{
- QFETCH(qreal, contentY);
- QFETCH(int, from);
- QFETCH(int, to);
- QFETCH(int, count);
- QFETCH(qreal, itemsOffsetAfterMove);
-
- QQuickText *name;
- QQuickText *number;
- QQuickView *canvas = createView();
- canvas->show();
-
- T model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickItem *currentItem = listview->currentItem();
- QTRY_VERIFY(currentItem != 0);
-
- listview->setContentY(contentY);
- model.moveItems(from, to, count);
-
- // wait for items to move
- QTest::qWait(100);
-
- QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
- int firstVisibleIndex = -1;
- for (int i=0; i<items.count(); i++) {
- if (items[i]->y() >= contentY) {
- QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
- firstVisibleIndex = e.evaluate().toInt();
- break;
- }
- }
- QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
-
- // Confirm items positioned correctly and indexes correct
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
- if (i >= firstVisibleIndex + 16) // index has moved out of view
- continue;
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
-
- // current index should have been updated
- if (item == currentItem)
- QTRY_COMPARE(listview->currentIndex(), i);
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::moved_data()
-{
- QTest::addColumn<qreal>("contentY");
- QTest::addColumn<int>("from");
- QTest::addColumn<int>("to");
- QTest::addColumn<int>("count");
- QTest::addColumn<qreal>("itemsOffsetAfterMove");
-
- // model starts with 30 items, each 20px high, in area 320px high
- // 16 items should be visible at a time
- // itemsOffsetAfterMove should be > 0 whenever items above the visible pos have moved
-
- QTest::newRow("move 1 forwards, within visible items")
- << 0.0
- << 1 << 4 << 1
- << 0.0;
-
- QTest::newRow("move 1 forwards, from non-visible -> visible")
- << 80.0 // show 4-19
- << 1 << 18 << 1
- << 20.0; // removed 1 item above the first visible, so item 0 should drop down by 1 to minimize movement
-
- QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
- << 80.0 // show 4-19
- << 0 << 4 << 1
- << 20.0; // first item has moved to below item4, everything drops down by size of 1 item
-
- QTest::newRow("move 1 forwards, from visible -> non-visible")
- << 0.0
- << 1 << 16 << 1
- << 0.0;
-
- QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
- << 0.0
- << 0 << 16 << 1
- << 0.0;
-
-
- QTest::newRow("move 1 backwards, within visible items")
- << 0.0
- << 4 << 1 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, within visible items (to first index)")
- << 0.0
- << 4 << 0 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from non-visible -> visible")
- << 0.0
- << 20 << 4 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
- << 0.0
- << 29 << 15 << 1
- << 0.0;
-
- QTest::newRow("move 1 backwards, from visible -> non-visible")
- << 80.0 // show 4-19
- << 16 << 1 << 1
- << -20.0; // to minimize movement, item 0 moves to -20, and other items do not move
-
- QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
- << 80.0 // show 4-19
- << 16 << 0 << 1
- << -20.0; // to minimize movement, item 16 (now at 0) moves to -20, and other items do not move
-
-
- QTest::newRow("move multiple forwards, within visible items")
- << 0.0
- << 0 << 5 << 3
- << 0.0;
-
- QTest::newRow("move multiple forwards, before visible items")
- << 140.0 // show 7-22
- << 4 << 5 << 3 // 4,5,6 move to below 7
- << 20.0 * 3; // 4,5,6 moved down
-
- QTest::newRow("move multiple forwards, from non-visible -> visible")
- << 80.0 // show 4-19
- << 1 << 5 << 3
- << 20.0 * 3; // moving 3 from above the content y should adjust y positions accordingly
-
- QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
- << 80.0 // show 4-19
- << 0 << 5 << 3
- << 20.0 * 3; // moving 3 from above the content y should adjust y positions accordingly
-
- QTest::newRow("move multiple forwards, from visible -> non-visible")
- << 0.0
- << 1 << 16 << 3
- << 0.0;
-
- QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
- << 0.0
- << 0 << 16 << 3
- << 0.0;
-
-
- QTest::newRow("move multiple backwards, within visible items")
- << 0.0
- << 4 << 1 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, within visible items (move first item)")
- << 0.0
- << 10 << 0 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from non-visible -> visible")
- << 0.0
- << 20 << 4 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
- << 0.0
- << 27 << 10 << 3
- << 0.0;
-
- QTest::newRow("move multiple backwards, from visible -> non-visible")
- << 80.0 // show 4-19
- << 16 << 1 << 3
- << -20.0 * 3; // to minimize movement, 0 moves by -60, and other items do not move
-
- QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
- << 80.0 // show 4-19
- << 16 << 0 << 3
- << -20.0 * 3; // to minimize movement, 16,17,18 move to above item 0, and other items do not move
-}
-
-
-struct ListChange {
- enum { Inserted, Removed, Moved, SetCurrent } type;
- int index;
- int count;
- int to; // Move
-
- static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
- static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
- static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
- static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
-};
-Q_DECLARE_METATYPE(QList<ListChange>)
-
-void tst_QQuickListView::multipleChanges()
-{
- QFETCH(int, startCount);
- QFETCH(QList<ListChange>, changes);
- QFETCH(int, newCount);
- QFETCH(int, newCurrentIndex);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < startCount; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- for (int i=0; i<changes.count(); i++) {
- switch (changes[i].type) {
- case ListChange::Inserted:
- {
- QList<QPair<QString, QString> > items;
- for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
- items << qMakePair(QString("new item " + j), QString::number(j));
- model.insertItems(changes[i].index, items);
- break;
- }
- case ListChange::Removed:
- model.removeItems(changes[i].index, changes[i].count);
- break;
- case ListChange::Moved:
- model.moveItems(changes[i].index, changes[i].to, changes[i].count);
- break;
- case ListChange::SetCurrent:
- listview->setCurrentIndex(changes[i].index);
- break;
- }
- }
-
- QTRY_COMPARE(listview->count(), newCount);
- QCOMPARE(listview->count(), model.count());
- QTRY_COMPARE(listview->currentIndex(), newCurrentIndex);
-
- QQuickText *name;
- QQuickText *number;
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i=0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickListView::multipleChanges_data()
-{
- QTest::addColumn<int>("startCount");
- QTest::addColumn<QList<ListChange> >("changes");
- QTest::addColumn<int>("newCount");
- QTest::addColumn<int>("newCurrentIndex");
-
- QList<ListChange> changes;
-
- for (int i=1; i<30; i++)
- changes << ListChange::remove(0);
- QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
-
- changes << ListChange::remove(0);
- QTest::newRow("remove all") << 30 << changes << 0 << -1;
-
- changes.clear();
- changes << ListChange::setCurrent(29);
- for (int i=29; i>0; i--)
- changes << ListChange::remove(i);
- QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
-
- QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
- << ListChange::remove(0, 1)
- << ListChange::insert(0, 1)
- ) << 10 << 1;
-
- QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::remove(2, 1)
- << ListChange::insert(2, 1)
- ) << 10 << 3;
-
- QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::remove(1, 3)
- << ListChange::insert(2, 2)
- ) << 9 << 1;
-
- QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::remove(1, 3)
- << ListChange::move(1, 5, 1)
- ) << 7 << 5;
-
- QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::remove(4, 3)
- << ListChange::move(4, 1, 1)
- ) << 7 << 1;
-
-
- QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 2)
- << ListChange::insert(0, 4)
- << ListChange::insert(0, 6)
- ) << 12 << 10;
-
- QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 2)
- << ListChange::insert(0, 4)
- << ListChange::insert(0, 6)
- << ListChange::setCurrent(3)
- << ListChange::insert(3, 2)
- ) << 14 << 5;
-
- QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 30)
- << ListChange::remove(0, 30)
- ) << 0 << -1;
-
- QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
- << ListChange::insert(1)
- << ListChange::setCurrent(1)
- << ListChange::remove(1)
- ) << 30 << 1;
-
- QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 10)
- << ListChange::remove(5, 10)
- ) << 10 << 5;
-
- QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 3)
- << ListChange::move(0, 10, 3)
- ) << 13 << 0;
-
- QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
- << ListChange::insert(0, 3)
- << ListChange::move(0, 8, 5)
- ) << 13 << 11;
-
- QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(9)
- << ListChange::insert(10, 3)
- << ListChange::move(8, 0, 5)
- ) << 13 << 1;
-
-
- QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::move(1, 2, 2)
- << ListChange::move(2, 1, 2)
- ) << 10 << 1;
-
- QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(2)
- << ListChange::move(1, 2, 3)
- << ListChange::move(3, 0, 5)
- ) << 10 << 0;
-
- QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 0, 1)
- << ListChange::remove(0)
- ) << 9 << 0;
-
- QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 0, 1)
- << ListChange::insert(0)
- ) << 11 << 1;
-
- QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(1)
- << ListChange::move(5, 1, 3)
- << ListChange::remove(1, 3)
- ) << 7 << 1;
-
- QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(5)
- << ListChange::move(5, 1, 3)
- << ListChange::insert(1, 5)
- ) << 15 << 6;
-
- QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
- << ListChange::setCurrent(3)
- << ListChange::move(0, 1, 2)
- << ListChange::insert(3, 5)
- ) << 15 << 8;
-
-
- QTest::newRow("clear current") << 0 << (QList<ListChange>()
- << ListChange::insert(0, 5)
- << ListChange::setCurrent(-1)
- << ListChange::remove(0, 5)
- << ListChange::insert(0, 5)
- ) << 5 << -1;
-}
-
-void tst_QQuickListView::swapWithFirstItem()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- // ensure content position is stable
- listview->setContentY(0);
- model.moveItem(1, 0);
- QTRY_VERIFY(listview->contentY() == 0);
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickListView::enforceRange()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-enforcerange.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
- QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
- QTRY_COMPARE(listview->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // view should be positioned at the top of the range.
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QTRY_VERIFY(item);
- QTRY_COMPARE(listview->contentY(), -100.0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(0));
- QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(0));
-
- // Check currentIndex is updated when contentItem moves
- listview->setContentY(20);
-
- QTRY_COMPARE(listview->currentIndex(), 6);
-
- // change model
- TestModel model2;
- for (int i = 0; i < 5; i++)
- model2.addItem("Item" + QString::number(i), "");
-
- ctxt->setContextProperty("testModel", &model2);
- QCOMPARE(listview->count(), 5);
-
- delete canvas;
-}
-
-void tst_QQuickListView::enforceRange_withoutHighlight()
-{
- // QTBUG-20287
- // If no highlight is set but StrictlyEnforceRange is used, the content should still move
- // to the correct position (i.e. to the next/previous item, not next/previous section)
- // when moving up/down via incrementCurrentIndex() and decrementCurrentIndex()
-
- QQuickView *canvas = createView();
- canvas->show();
- QTest::qWait(200);
-
- TestModel model;
- model.addItem("Item 0", "a");
- model.addItem("Item 1", "b");
- model.addItem("Item 2", "b");
- model.addItem("Item 3", "c");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-enforcerange-nohighlight.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- qreal expectedPos = -100.0;
-
- expectedPos += 10.0; // scroll past 1st section's delegate (10px height)
- QTRY_COMPARE(listview->contentY(), expectedPos);
-
- expectedPos += 20 + 10; // scroll past 1st section and section delegate of 2nd section
- QTest::keyClick(canvas, Qt::Key_Down);
-
- QTRY_COMPARE(listview->contentY(), expectedPos);
-
- expectedPos += 20; // scroll past 1st item of 2nd section
- QTest::keyClick(canvas, Qt::Key_Down);
- QTRY_COMPARE(listview->contentY(), expectedPos);
-
- expectedPos += 20 + 10; // scroll past 2nd item of 2nd section and section delegate of 3rd section
- QTest::keyClick(canvas, Qt::Key_Down);
- QTRY_COMPARE(listview->contentY(), expectedPos);
-
- delete canvas;
-}
-
-void tst_QQuickListView::spacing()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- listview->setSpacing(10);
- QTRY_VERIFY(listview->spacing() == 10);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*30);
- }
-
- listview->setSpacing(0);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.0);
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::sections()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i/5));
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
- QQuickText *next = findItem<QQuickText>(item, "nextSection");
- QCOMPARE(next->text().toInt(), (i+1)/5);
- }
-
- QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged()));
-
- // Remove section boundary
- model.removeItem(5);
- QTRY_COMPARE(listview->count(), model.count());
-
- // New section header created
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 5);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 40.0);
-
- model.insertItem(3, "New Item", "0");
- QTRY_COMPARE(listview->count(), model.count());
-
- // Section header moved
- item = findItem<QQuickItem>(contentItem, "wrapper", 5);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 20.0);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 6);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 40.0);
-
- // insert item which will become a section header
- model.insertItem(6, "Replace header", "1");
- QTRY_COMPARE(listview->count(), model.count());
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 6);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 40.0);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 7);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 20.0);
-
- QTRY_COMPARE(listview->currentSection(), QString("0"));
-
- listview->setContentY(140);
- QTRY_COMPARE(listview->currentSection(), QString("1"));
-
- QTRY_COMPARE(currentSectionChangedSpy.count(), 1);
-
- listview->setContentY(20);
- QTRY_COMPARE(listview->currentSection(), QString("0"));
-
- QTRY_COMPARE(currentSectionChangedSpy.count(), 2);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 1);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 20.0);
-
- // check that headers change when item changes
- listview->setContentY(0);
- model.modifyItem(0, "changed", "2");
- QTest::qWait(300);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 1);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->height(), 40.0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::sectionsDelegate()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i/5));
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections_delegate.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20));
- QQuickText *next = findItem<QQuickText>(item, "nextSection");
- QCOMPARE(next->text().toInt(), (i+1)/5);
- }
-
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*6));
- }
-
- model.modifyItem(0, "One", "aaa");
- model.modifyItem(1, "Two", "aaa");
- model.modifyItem(2, "Three", "aaa");
- model.modifyItem(3, "Four", "aaa");
- model.modifyItem(4, "Five", "aaa");
- QTest::qWait(300);
-
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem,
- "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*6));
- }
-
- // remove section boundary
- model.removeItem(5);
- QTRY_COMPARE(listview->count(), model.count());
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem,
- "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
- QVERIFY(item);
- }
-
- // QTBUG-17606
- QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "sect_1");
- QCOMPARE(items.count(), 1);
-
- // QTBUG-17759
- model.modifyItem(0, "One", "aaa");
- model.modifyItem(1, "One", "aaa");
- model.modifyItem(2, "One", "aaa");
- model.modifyItem(3, "Four", "aaa");
- model.modifyItem(4, "Four", "aaa");
- model.modifyItem(5, "Four", "aaa");
- model.modifyItem(6, "Five", "aaa");
- model.modifyItem(7, "Five", "aaa");
- model.modifyItem(8, "Five", "aaa");
- model.modifyItem(9, "Two", "aaa");
- model.modifyItem(10, "Two", "aaa");
- model.modifyItem(11, "Two", "aaa");
- QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_aaa").count(), 1);
- canvas->rootObject()->setProperty("sectionProperty", "name");
- // ensure view has settled.
- QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_Four").count(), 1);
- for (int i = 0; i < 4; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem,
- "sect_" + model.name(i*3));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*4));
- }
-
- // QTBUG-17769
- model.removeItems(10, 20);
- // ensure view has settled.
- QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 10);
- // Drag view up beyond bounds
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,20));
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,0), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- }
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,-50), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- }
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,-200), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- }
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-200));
- // view should settle back at 0
- QTRY_COMPARE(listview->contentY(), 0.0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::sectionsPositioning()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i/5));
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections_delegate.qml")));
- qApp->processEvents();
- canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart | QQuickViewSection::NextLabelAtEnd)));
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*6));
- }
-
- QQuickItem *topItem = findVisibleChild(contentItem, "sect_0"); // section header
- QVERIFY(topItem);
- QCOMPARE(topItem->y(), 0.);
-
- QQuickItem *bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
- QVERIFY(bottomItem);
- QCOMPARE(bottomItem->y(), 300.);
-
- // move down a little and check that section header is at top
- listview->setContentY(10);
- QCOMPARE(topItem->y(), 0.);
-
- // push the top header up
- listview->setContentY(110);
- topItem = findVisibleChild(contentItem, "sect_0"); // section header
- QVERIFY(topItem);
- QCOMPARE(topItem->y(), 100.);
-
- QQuickItem *item = findVisibleChild(contentItem, "sect_1");
- QVERIFY(item);
- QCOMPARE(item->y(), 120.);
-
- bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
- QVERIFY(bottomItem);
- QCOMPARE(bottomItem->y(), 410.);
-
- // Move past section 0
- listview->setContentY(120);
- topItem = findVisibleChild(contentItem, "sect_0"); // section header
- QVERIFY(!topItem);
-
- // Push section footer down
- listview->setContentY(70);
- bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
- QVERIFY(bottomItem);
- QCOMPARE(bottomItem->y(), 380.);
-
- // Change current section
- listview->setContentY(10);
- model.modifyItem(0, "One", "aaa");
- model.modifyItem(1, "Two", "aaa");
- model.modifyItem(2, "Three", "aaa");
- model.modifyItem(3, "Four", "aaa");
- model.modifyItem(4, "Five", "aaa");
- QTest::qWait(300);
-
- QTRY_COMPARE(listview->currentSection(), QString("aaa"));
-
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem,
- "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*6));
- }
-
- topItem = findVisibleChild(contentItem, "sect_aaa"); // section header
- QVERIFY(topItem);
- QCOMPARE(topItem->y(), 10.);
-
- // remove section boundary
- listview->setContentY(120);
- model.removeItem(5);
- QTRY_COMPARE(listview->count(), model.count());
- for (int i = 0; i < 3; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem,
- "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
- QVERIFY(item);
- QTRY_COMPARE(item->y(), qreal(i*20*6));
- }
-
- QVERIFY(topItem = findVisibleChild(contentItem, "sect_1"));
- QTRY_COMPARE(topItem->y(), 120.);
-
- // Change the next section
- listview->setContentY(0);
- bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
- QVERIFY(bottomItem);
- QTRY_COMPARE(bottomItem->y(), 300.);
-
- model.modifyItem(14, "New", "new");
-
- QTRY_VERIFY(bottomItem = findVisibleChild(contentItem, "sect_new")); // section footer
- QTRY_COMPARE(bottomItem->y(), 300.);
-
- // Turn sticky footer off
- listview->setContentY(40);
- canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart)));
- item = findVisibleChild(contentItem, "sect_new"); // inline label restored
- QVERIFY(item);
- QCOMPARE(item->y(), 360.);
-
- // Turn sticky header off
- listview->setContentY(30);
- canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels)));
- item = findVisibleChild(contentItem, "sect_aaa"); // inline label restored
- QVERIFY(item);
- QCOMPARE(item->y(), 0.);
-
- delete canvas;
-}
-
-void tst_QQuickListView::currentIndex_delayedItemCreation()
-{
- QFETCH(bool, setCurrentToZero);
-
- QQuickView *canvas = createView();
-
- TestModel model;
-
- // test currentIndexChanged() is emitted even if currentIndex = 0 on start up
- // (since the currentItem will have changed and that shares the same index)
- canvas->rootContext()->setContextProperty("setCurrentToZero", setCurrentToZero);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("fillModelOnComponentCompleted.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QSignalSpy spy(listview, SIGNAL(currentItemChanged()));
- QCOMPARE(listview->currentIndex(), 0);
- QTRY_COMPARE(spy.count(), 1);
-
- delete canvas;
-}
-
-void tst_QQuickListView::currentIndex_delayedItemCreation_data()
-{
- QTest::addColumn<bool>("setCurrentToZero");
-
- QTest::newRow("set to 0") << true;
- QTest::newRow("don't set to 0") << false;
-}
-
-void tst_QQuickListView::currentIndex()
-{
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i));
-
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("testWrap", QVariant(false));
-
- QString filename(TESTDATA("listview-initCurrent.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // current item should be 20th item at startup
- // and current item should be in view
- QCOMPARE(listview->currentIndex(), 20);
- QCOMPARE(listview->contentY(), 100.0);
- QCOMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 20));
- QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
-
- // no wrap
- listview->setCurrentIndex(0);
- QCOMPARE(listview->currentIndex(), 0);
- // confirm that the velocity is updated
- QTRY_VERIFY(listview->verticalVelocity() != 0.0);
-
- listview->incrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 1);
- listview->decrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 0);
-
- listview->decrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 0);
-
- // with wrap
- ctxt->setContextProperty("testWrap", QVariant(true));
- QVERIFY(listview->isWrapEnabled());
-
- listview->decrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), model.count()-1);
-
- QTRY_COMPARE(listview->contentY(), 280.0);
-
- listview->incrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 0);
-
- QTRY_COMPARE(listview->contentY(), 0.0);
-
-
- // footer should become visible if it is out of view, and then current index is set to count-1
- canvas->rootObject()->setProperty("showFooter", true);
- QTRY_VERIFY(listview->footerItem());
- listview->setCurrentIndex(model.count()-2);
- QTRY_VERIFY(listview->footerItem()->y() > listview->contentY() + listview->height());
- listview->setCurrentIndex(model.count()-1);
- QTRY_COMPARE(listview->contentY() + listview->height(), (20.0 * model.count()) + listview->footerItem()->height());
- canvas->rootObject()->setProperty("showFooter", false);
-
- // header should become visible if it is out of view, and then current index is set to 0
- canvas->rootObject()->setProperty("showHeader", true);
- QTRY_VERIFY(listview->headerItem());
- listview->setCurrentIndex(1);
- QTRY_VERIFY(listview->headerItem()->y() + listview->headerItem()->height() < listview->contentY());
- listview->setCurrentIndex(0);
- QTRY_COMPARE(listview->contentY(), -listview->headerItem()->height());
- canvas->rootObject()->setProperty("showHeader", false);
-
-
- // Test keys
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
-
- listview->setCurrentIndex(0);
-
- QTest::keyClick(canvas, Qt::Key_Down);
- QCOMPARE(listview->currentIndex(), 1);
-
- QTest::keyClick(canvas, Qt::Key_Up);
- QCOMPARE(listview->currentIndex(), 0);
-
- // hold down Key_Down
- for (int i=0; i<model.count()-1; i++) {
- QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
- QTRY_COMPARE(listview->currentIndex(), i+1);
- }
- QTest::keyRelease(canvas, Qt::Key_Down);
- QTRY_COMPARE(listview->currentIndex(), model.count()-1);
- QTRY_COMPARE(listview->contentY(), 280.0);
-
- // hold down Key_Up
- for (int i=model.count()-1; i > 0; i--) {
- QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
- QTRY_COMPARE(listview->currentIndex(), i-1);
- }
- QTest::keyRelease(canvas, Qt::Key_Up);
- QTRY_COMPARE(listview->currentIndex(), 0);
- QTRY_COMPARE(listview->contentY(), 0.0);
-
-
- // turn off auto highlight
- listview->setHighlightFollowsCurrentItem(false);
- QVERIFY(listview->highlightFollowsCurrentItem() == false);
-
- QVERIFY(listview->highlightItem());
- qreal hlPos = listview->highlightItem()->y();
-
- listview->setCurrentIndex(4);
- QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
-
- // insert item before currentIndex
- listview->setCurrentIndex(28);
- model.insertItem(0, "Foo", "1111");
- QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
-
- // check removing highlight by setting currentIndex to -1;
- listview->setCurrentIndex(-1);
-
- QCOMPARE(listview->currentIndex(), -1);
- QVERIFY(!listview->highlightItem());
- QVERIFY(!listview->currentItem());
-
- delete canvas;
-}
-
-void tst_QQuickListView::noCurrentIndex()
-{
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), QString::number(i));
-
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- QString filename(TESTDATA("listview-noCurrent.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // current index should be -1 at startup
- // and we should not have a currentItem or highlightItem
- QCOMPARE(listview->currentIndex(), -1);
- QCOMPARE(listview->contentY(), 0.0);
- QVERIFY(!listview->highlightItem());
- QVERIFY(!listview->currentItem());
-
- listview->setCurrentIndex(2);
- QCOMPARE(listview->currentIndex(), 2);
- QVERIFY(listview->highlightItem());
- QVERIFY(listview->currentItem());
-
- delete canvas;
-}
-
-void tst_QQuickListView::itemList()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("itemlist.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
- QTRY_VERIFY(model != 0);
-
- QTRY_VERIFY(model->count() == 3);
- QTRY_COMPARE(listview->currentIndex(), 0);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), 0.0);
- QCOMPARE(item->height(), listview->height());
-
- QQuickText *text = findItem<QQuickText>(contentItem, "text1");
- QTRY_VERIFY(text);
- QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
-
- listview->setCurrentIndex(2);
-
- item = findItem<QQuickItem>(contentItem, "item3");
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), 480.0);
-
- text = findItem<QQuickText>(contentItem, "text3");
- QTRY_VERIFY(text);
- QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
-
- delete canvas;
-}
-
-void tst_QQuickListView::cacheBuffer()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 90; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_VERIFY(listview->delegate() != 0);
- QTRY_VERIFY(listview->model() != 0);
- QTRY_VERIFY(listview->highlight() != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- testObject->setCacheBuffer(200);
- QTRY_VERIFY(listview->cacheBuffer() == 200);
-
- // items will be created one at a time
- for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(listview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- int newItemCount = 0;
- newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
-
- // Confirm items positioned correctly
- for (int i = 0; i < model.count() && i < newItemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- // move view and confirm items in view are visible immediately and outside are created async
- listview->setContentY(300);
-
- for (int i = 15; i < 32; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QVERIFY(item);
- QVERIFY(item->y() == i*20);
- }
-
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
-
- // ensure buffered items are created
- for (int i = 32; i < qMin(41,model.count()); ++i) {
- QQuickItem *item = 0;
- while (!item) {
- qGuiApp->processEvents(); // allow refill to happen
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(listview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::positionViewAtIndex()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position on a currently visible item
- listview->positionViewAtIndex(3, QQuickListView::Beginning);
- QTRY_COMPARE(listview->contentY(), 60.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position on an item beyond the visible items
- listview->positionViewAtIndex(22, QQuickListView::Beginning);
- QTRY_COMPARE(listview->contentY(), 440.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position on an item that would leave empty space if positioned at the top
- listview->positionViewAtIndex(28, QQuickListView::Beginning);
- QTRY_COMPARE(listview->contentY(), 480.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position at the beginning again
- listview->positionViewAtIndex(0, QQuickListView::Beginning);
- QTRY_COMPARE(listview->contentY(), 0.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position at End using last index
- listview->positionViewAtIndex(model.count()-1, QQuickListView::End);
- QTRY_COMPARE(listview->contentY(), 480.);
-
- // Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 24; i < model.count(); ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- // Position at End
- listview->positionViewAtIndex(20, QQuickListView::End);
- QTRY_COMPARE(listview->contentY(), 100.);
-
- // Position in Center
- listview->positionViewAtIndex(15, QQuickListView::Center);
- QTRY_COMPARE(listview->contentY(), 150.);
-
- // Ensure at least partially visible
- listview->positionViewAtIndex(15, QQuickListView::Visible);
- QTRY_COMPARE(listview->contentY(), 150.);
-
- listview->setContentY(302);
- listview->positionViewAtIndex(15, QQuickListView::Visible);
- QTRY_COMPARE(listview->contentY(), 302.);
-
- listview->setContentY(320);
- listview->positionViewAtIndex(15, QQuickListView::Visible);
- QTRY_COMPARE(listview->contentY(), 300.);
-
- listview->setContentY(85);
- listview->positionViewAtIndex(20, QQuickListView::Visible);
- QTRY_COMPARE(listview->contentY(), 85.);
-
- listview->setContentY(75);
- listview->positionViewAtIndex(20, QQuickListView::Visible);
- QTRY_COMPARE(listview->contentY(), 100.);
-
- // Ensure completely visible
- listview->setContentY(120);
- listview->positionViewAtIndex(20, QQuickListView::Contain);
- QTRY_COMPARE(listview->contentY(), 120.);
-
- listview->setContentY(302);
- listview->positionViewAtIndex(15, QQuickListView::Contain);
- QTRY_COMPARE(listview->contentY(), 300.);
-
- listview->setContentY(85);
- listview->positionViewAtIndex(20, QQuickListView::Contain);
- QTRY_COMPARE(listview->contentY(), 100.);
-
- // positionAtBeginnging
- listview->positionViewAtBeginning();
- QTRY_COMPARE(listview->contentY(), 0.);
-
- listview->setContentY(80);
- canvas->rootObject()->setProperty("showHeader", true);
- listview->positionViewAtBeginning();
- QTRY_COMPARE(listview->contentY(), -30.);
-
- // positionAtEnd
- listview->positionViewAtEnd();
- QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320
-
- listview->setContentY(80);
- canvas->rootObject()->setProperty("showFooter", true);
- listview->positionViewAtEnd();
- QTRY_COMPARE(listview->contentY(), 510.);
-
- // set current item to outside visible view, position at beginning
- // and ensure highlight moves to current item
- listview->setCurrentIndex(1);
- listview->positionViewAtBeginning();
- QTRY_COMPARE(listview->contentY(), -30.);
- QVERIFY(listview->highlightItem());
- QCOMPARE(listview->highlightItem()->y(), 20.);
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::resetModel()
-{
- QQuickView *canvas = createView();
-
- QStringList strings;
- strings << "one" << "two" << "three";
- QStringListModel model(strings);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(listview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
- QTRY_COMPARE(display->text(), strings.at(i));
- }
-
- strings.clear();
- strings << "four" << "five" << "six" << "seven";
- model.setStringList(strings);
-
- QTRY_COMPARE(listview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
- QTRY_COMPARE(display->text(), strings.at(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickListView::propertyChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
- QTRY_VERIFY(listView);
-
- QSignalSpy highlightFollowsCurrentItemSpy(listView, SIGNAL(highlightFollowsCurrentItemChanged()));
- QSignalSpy preferredHighlightBeginSpy(listView, SIGNAL(preferredHighlightBeginChanged()));
- QSignalSpy preferredHighlightEndSpy(listView, SIGNAL(preferredHighlightEndChanged()));
- QSignalSpy highlightRangeModeSpy(listView, SIGNAL(highlightRangeModeChanged()));
- QSignalSpy keyNavigationWrapsSpy(listView, SIGNAL(keyNavigationWrapsChanged()));
- QSignalSpy cacheBufferSpy(listView, SIGNAL(cacheBufferChanged()));
- QSignalSpy snapModeSpy(listView, SIGNAL(snapModeChanged()));
-
- QTRY_COMPARE(listView->highlightFollowsCurrentItem(), true);
- QTRY_COMPARE(listView->preferredHighlightBegin(), 0.0);
- QTRY_COMPARE(listView->preferredHighlightEnd(), 0.0);
- QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::ApplyRange);
- QTRY_COMPARE(listView->isWrapEnabled(), true);
- QTRY_COMPARE(listView->cacheBuffer(), 10);
- QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapToItem);
-
- listView->setHighlightFollowsCurrentItem(false);
- listView->setPreferredHighlightBegin(1.0);
- listView->setPreferredHighlightEnd(1.0);
- listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
- listView->setWrapEnabled(false);
- listView->setCacheBuffer(3);
- listView->setSnapMode(QQuickListView::SnapOneItem);
-
- QTRY_COMPARE(listView->highlightFollowsCurrentItem(), false);
- QTRY_COMPARE(listView->preferredHighlightBegin(), 1.0);
- QTRY_COMPARE(listView->preferredHighlightEnd(), 1.0);
- QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
- QTRY_COMPARE(listView->isWrapEnabled(), false);
- QTRY_COMPARE(listView->cacheBuffer(), 3);
- QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapOneItem);
-
- QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
- QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
- QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
- QTRY_COMPARE(highlightRangeModeSpy.count(),1);
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
- QTRY_COMPARE(cacheBufferSpy.count(),1);
- QTRY_COMPARE(snapModeSpy.count(),1);
-
- listView->setHighlightFollowsCurrentItem(false);
- listView->setPreferredHighlightBegin(1.0);
- listView->setPreferredHighlightEnd(1.0);
- listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
- listView->setWrapEnabled(false);
- listView->setCacheBuffer(3);
- listView->setSnapMode(QQuickListView::SnapOneItem);
-
- QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
- QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
- QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
- QTRY_COMPARE(highlightRangeModeSpy.count(),1);
- QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
- QTRY_COMPARE(cacheBufferSpy.count(),1);
- QTRY_COMPARE(snapModeSpy.count(),1);
-
- delete canvas;
-}
-
-void tst_QQuickListView::componentChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
- QTRY_VERIFY(listView);
-
- QDeclarativeComponent component(canvas->engine());
- component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
-
- QDeclarativeComponent delegateComponent(canvas->engine());
- delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
-
- QSignalSpy highlightSpy(listView, SIGNAL(highlightChanged()));
- QSignalSpy delegateSpy(listView, SIGNAL(delegateChanged()));
- QSignalSpy headerSpy(listView, SIGNAL(headerChanged()));
- QSignalSpy footerSpy(listView, SIGNAL(footerChanged()));
-
- listView->setHighlight(&component);
- listView->setHeader(&component);
- listView->setFooter(&component);
- listView->setDelegate(&delegateComponent);
-
- QTRY_COMPARE(listView->highlight(), &component);
- QTRY_COMPARE(listView->header(), &component);
- QTRY_COMPARE(listView->footer(), &component);
- QTRY_COMPARE(listView->delegate(), &delegateComponent);
-
- QTRY_COMPARE(highlightSpy.count(),1);
- QTRY_COMPARE(delegateSpy.count(),1);
- QTRY_COMPARE(headerSpy.count(),1);
- QTRY_COMPARE(footerSpy.count(),1);
-
- listView->setHighlight(&component);
- listView->setHeader(&component);
- listView->setFooter(&component);
- listView->setDelegate(&delegateComponent);
-
- QTRY_COMPARE(highlightSpy.count(),1);
- QTRY_COMPARE(delegateSpy.count(),1);
- QTRY_COMPARE(headerSpy.count(),1);
- QTRY_COMPARE(footerSpy.count(),1);
-
- delete canvas;
-}
-
-void tst_QQuickListView::modelChanges()
-{
- QQuickView *canvas = createView();
- QTRY_VERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
-
- QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
- QTRY_VERIFY(listView);
-
- QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
- QTRY_VERIFY(alternateModel);
- QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
- QSignalSpy modelSpy(listView, SIGNAL(modelChanged()));
-
- listView->setModel(modelVariant);
- QTRY_COMPARE(listView->model(), modelVariant);
- QTRY_COMPARE(modelSpy.count(),1);
-
- listView->setModel(modelVariant);
- QTRY_COMPARE(modelSpy.count(),1);
-
- listView->setModel(QVariant());
- QTRY_COMPARE(modelSpy.count(),2);
-
- delete canvas;
-}
-
-void tst_QQuickListView::QTBUG_9791()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("strictlyenforcerange.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_VERIFY(listview->delegate() != 0);
- QTRY_VERIFY(listview->model() != 0);
-
- QMetaObject::invokeMethod(listview, "fillModel");
- qApp->processEvents();
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QCOMPARE(itemCount, 3);
-
- for (int i = 0; i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), i*300.0);
- }
-
- // check that view is positioned correctly
- QTRY_COMPARE(listview->contentX(), 590.0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::manualHighlight()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- QString filename(TESTDATA("manual-highlight.qml"));
- canvas->setSource(QUrl::fromLocalFile(filename));
-
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(listview->currentIndex(), 0);
- QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
- QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
-
- listview->setCurrentIndex(2);
-
- QTRY_COMPARE(listview->currentIndex(), 2);
- QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
- QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
-
- // QTBUG-15972
- listview->positionViewAtIndex(3, QQuickListView::Contain);
-
- QTRY_COMPARE(listview->currentIndex(), 2);
- QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
- QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
-
- delete canvas;
-}
-
-void tst_QQuickListView::QTBUG_11105()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- listview->positionViewAtIndex(20, QQuickListView::Beginning);
- QCOMPARE(listview->contentY(), 280.);
-
- TestModel model2;
- for (int i = 0; i < 5; i++)
- model2.addItem("Item" + QString::number(i), "");
-
- ctxt->setContextProperty("testModel", &model2);
-
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QCOMPARE(itemCount, 5);
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::header()
-{
- QFETCH(QQuickListView::Orientation, orientation);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(QPointF, initialHeaderPos);
- QFETCH(QPointF, firstDelegatePos);
- QFETCH(QPointF, initialContentPos);
- QFETCH(QPointF, changedHeaderPos);
- QFETCH(QPointF, changedContentPos);
- QFETCH(QPointF, resizeContentPos);
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QQuickView *canvas = createView();
- canvas->rootContext()->setContextProperty("testModel", &model);
- canvas->rootContext()->setContextProperty("initialViewWidth", 240);
- canvas->rootContext()->setContextProperty("initialViewHeight", 320);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- listview->setOrientation(orientation);
- listview->setLayoutDirection(layoutDirection);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *header = findItem<QQuickText>(contentItem, "header");
- QVERIFY(header);
-
- QVERIFY(header == listview->headerItem());
-
- QCOMPARE(header->width(), 100.);
- QCOMPARE(header->height(), 30.);
- QCOMPARE(header->pos(), initialHeaderPos);
- QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- model.clear();
- QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
-
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QSignalSpy headerItemSpy(listview, SIGNAL(headerItemChanged()));
- QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
-
- QCOMPARE(headerItemSpy.count(), 1);
-
- header = findItem<QQuickText>(contentItem, "header");
- QVERIFY(!header);
- header = findItem<QQuickText>(contentItem, "header2");
- QVERIFY(header);
-
- QVERIFY(header == listview->headerItem());
-
- QCOMPARE(header->pos(), changedHeaderPos);
- QCOMPARE(header->width(), 50.);
- QCOMPARE(header->height(), 20.);
- QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- delete canvas;
-
-
- // QTBUG-21207 header should become visible if view resizes from initial empty size
-
- canvas = createView();
- canvas->rootContext()->setContextProperty("testModel", &model);
- canvas->rootContext()->setContextProperty("initialViewWidth", 0.0);
- canvas->rootContext()->setContextProperty("initialViewHeight", 0.0);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
-
- listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- listview->setOrientation(orientation);
- listview->setLayoutDirection(layoutDirection);
-
- listview->setWidth(240);
- listview->setHeight(320);
- QTRY_COMPARE(listview->headerItem()->pos(), initialHeaderPos);
- QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
-
-
- delete canvas;
-}
-
-void tst_QQuickListView::header_data()
-{
- QTest::addColumn<QQuickListView::Orientation>("orientation");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<QPointF>("initialHeaderPos");
- QTest::addColumn<QPointF>("changedHeaderPos");
- QTest::addColumn<QPointF>("initialContentPos");
- QTest::addColumn<QPointF>("changedContentPos");
- QTest::addColumn<QPointF>("firstDelegatePos");
- QTest::addColumn<QPointF>("resizeContentPos");
-
- // header1 = 100 x 30
- // header2 = 50 x 20
- // delegates = 240 x 20
- // view width = 240
-
- // header above items, top left
- QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, 0)
- << QPointF(0, -10);
-
- // header above items, top right
- QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, -30)
- << QPointF(0, -20)
- << QPointF(0, 0)
- << QPointF(0, -10);
-
- // header to left of items
- QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
- << QPointF(-100, 0)
- << QPointF(-50, 0)
- << QPointF(-100, 0)
- << QPointF(-50, 0)
- << QPointF(0, 0)
- << QPointF(-40, 0);
-
- // header to right of items
- QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(-240 + 100, 0)
- << QPointF(-240 + 50, 0)
- << QPointF(-240, 0)
- << QPointF(-240 + 40, 0);
-}
-
-void tst_QQuickListView::header_delayItemCreation()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
-
- canvas->rootContext()->setContextProperty("setCurrentToZero", QVariant(false));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("fillModelOnComponentCompleted.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *header = findItem<QQuickText>(contentItem, "header");
- QVERIFY(header);
- QCOMPARE(header->y(), -header->height());
-
- QCOMPARE(listview->contentY(), -header->height());
-
- model.clear();
- QTRY_COMPARE(header->y(), -header->height());
-
- delete canvas;
-}
-
-void tst_QQuickListView::footer()
-{
- QFETCH(QQuickListView::Orientation, orientation);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(QPointF, initialFooterPos);
- QFETCH(QPointF, firstDelegatePos);
- QFETCH(QPointF, initialContentPos);
- QFETCH(QPointF, changedFooterPos);
- QFETCH(QPointF, changedContentPos);
- QFETCH(QPointF, resizeContentPos);
-
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 3; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("footer.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- listview->setOrientation(orientation);
- listview->setLayoutDirection(layoutDirection);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
- QVERIFY(footer);
-
- QVERIFY(footer == listview->footerItem());
-
- QCOMPARE(footer->pos(), initialFooterPos);
- QCOMPARE(footer->width(), 100.);
- QCOMPARE(footer->height(), 30.);
- QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- // remove one item
- model.removeItem(1);
-
- if (orientation == QQuickListView::Vertical) {
- QTRY_COMPARE(footer->y(), initialFooterPos.y() - 20); // delegate height = 20
- } else {
- QTRY_COMPARE(footer->x(), layoutDirection == Qt::LeftToRight ?
- initialFooterPos.x() - 40 : initialFooterPos.x() + 40); // delegate width = 40
- }
-
- // remove all items
- model.clear();
-
- QPointF posWhenNoItems(0, 0);
- if (orientation == QQuickListView::Horizontal && layoutDirection == Qt::RightToLeft)
- posWhenNoItems.setX(-100);
- QTRY_COMPARE(footer->pos(), posWhenNoItems);
-
- // if header is present, it's at a negative pos, so the footer should not move
- canvas->rootObject()->setProperty("showHeader", true);
- QTRY_COMPARE(footer->pos(), posWhenNoItems);
- canvas->rootObject()->setProperty("showHeader", false);
-
- // add 30 items
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QSignalSpy footerItemSpy(listview, SIGNAL(footerItemChanged()));
- QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
-
- QCOMPARE(footerItemSpy.count(), 1);
-
- footer = findItem<QQuickText>(contentItem, "footer");
- QVERIFY(!footer);
- footer = findItem<QQuickText>(contentItem, "footer2");
- QVERIFY(footer);
-
- QVERIFY(footer == listview->footerItem());
-
- QCOMPARE(footer->pos(), changedFooterPos);
- QCOMPARE(footer->width(), 50.);
- QCOMPARE(footer->height(), 20.);
- QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->pos(), firstDelegatePos);
-
- listview->positionViewAtEnd();
- footer->setHeight(10);
- footer->setWidth(40);
- QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos);
-
- delete canvas;
-}
-
-void tst_QQuickListView::footer_data()
-{
- QTest::addColumn<QQuickListView::Orientation>("orientation");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<QPointF>("initialFooterPos");
- QTest::addColumn<QPointF>("changedFooterPos");
- QTest::addColumn<QPointF>("initialContentPos");
- QTest::addColumn<QPointF>("changedContentPos");
- QTest::addColumn<QPointF>("firstDelegatePos");
- QTest::addColumn<QPointF>("resizeContentPos");
-
- // footer1 = 100 x 30
- // footer2 = 50 x 20
- // delegates = 40 x 20
- // view width = 240
- // view height = 320
-
- // footer below items, bottom left
- QTest::newRow("vertical, layout left to right") << QQuickListView::Vertical << Qt::LeftToRight
- << QPointF(0, 3 * 20)
- << QPointF(0, 30 * 20) // added 30 items
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 30 * 20 - 320 + 10);
-
- // footer below items, bottom right
- QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
- << QPointF(0, 3 * 20)
- << QPointF(0, 30 * 20)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 30 * 20 - 320 + 10);
-
- // footer to right of items
- QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
- << QPointF(40 * 3, 0)
- << QPointF(40 * 30, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(0, 0)
- << QPointF(40 * 30 - 240 + 40, 0);
-
- // footer to left of items
- QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
- << QPointF(-(40 * 3) - 100, 0)
- << QPointF(-(40 * 30) - 50, 0) // 50 = new footer width
- << QPointF(-240, 0)
- << QPointF(-240, 0)
- << QPointF(-40, 0)
- << QPointF(-(40 * 30) - 40, 0);
-}
-
-class LVAccessor : public QQuickListView
-{
-public:
- qreal minY() const { return minYExtent(); }
- qreal maxY() const { return maxYExtent(); }
- qreal minX() const { return minXExtent(); }
- qreal maxX() const { return maxXExtent(); }
-};
-
-void tst_QQuickListView::headerFooter()
-{
- {
- // Vertical
- QQuickView *canvas = createView();
-
- TestModel model;
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(header);
- QCOMPARE(header->y(), -header->height());
-
- QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(footer);
- QCOMPARE(footer->y(), 0.);
-
- QCOMPARE(static_cast<LVAccessor*>(listview)->minY(), header->height());
- QCOMPARE(static_cast<LVAccessor*>(listview)->maxY(), header->height());
-
- delete canvas;
- }
- {
- // Horizontal
- QQuickView *canvas = createView();
-
- TestModel model;
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
- canvas->rootObject()->setProperty("horizontal", true);
- qApp->processEvents();
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(header);
- QCOMPARE(header->x(), -header->width());
-
- QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(footer);
- QCOMPARE(footer->x(), 0.);
-
- QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), header->width());
- QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), header->width());
-
- delete canvas;
- }
- {
- // Horizontal RTL
- QQuickView *canvas = createView();
-
- TestModel model;
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
- canvas->rootObject()->setProperty("horizontal", true);
- canvas->rootObject()->setProperty("rtl", true);
- qApp->processEvents();
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(header);
- QCOMPARE(header->x(), 0.);
-
- QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(footer);
- QCOMPARE(footer->x(), -footer->width());
-
- QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240. - header->width());
- QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240. - header->width());
-
- delete canvas;
- }
-}
-
-void tst_QQuickListView::resizeView()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.);
- }
-
- QVariant heightRatio;
- QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
- QCOMPARE(heightRatio.toReal(), 0.4);
-
- listview->setHeight(200);
-
- QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
- QCOMPARE(heightRatio.toReal(), 0.25);
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::resizeViewAndRepaint()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- for (int i = 0; i < 40; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("initialHeight", 100);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizeview.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // item at index 10 should not be currently visible
- QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- listview->setHeight(320);
- QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- listview->setHeight(100);
- QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
-
- delete canvas;
-}
-
-void tst_QQuickListView::sizeLessThan1()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("sizelessthan1.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // Confirm items positioned correctly
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*0.5);
- }
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::QTBUG_14821()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug14821.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- listview->decrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 99);
-
- listview->incrementCurrentIndex();
- QCOMPARE(listview->currentIndex(), 0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::resizeDelegate()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- QStringList strings;
- for (int i = 0; i < 30; ++i)
- strings << QString::number(i);
- QStringListModel model(strings);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QCOMPARE(listview->count(), model.rowCount());
-
- listview->setCurrentIndex(25);
- listview->setContentY(0);
- QTest::qWait(300);
-
- for (int i = 0; i < 16; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QCOMPARE(item->y(), i*20.0);
- }
-
- QCOMPARE(listview->currentItem()->y(), 500.0);
- QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
-
- canvas->rootObject()->setProperty("delegateHeight", 30);
- QTest::qWait(300);
-
- for (int i = 0; i < 11; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QTRY_COMPARE(item->y(), i*30.0);
- }
-
- QTRY_COMPARE(listview->currentItem()->y(), 750.0);
- QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
-
- listview->setCurrentIndex(1);
- listview->positionViewAtIndex(25, QQuickListView::Beginning);
- listview->positionViewAtIndex(5, QQuickListView::Beginning);
-
- for (int i = 5; i < 16; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QCOMPARE(item->y(), i*30.0);
- }
-
- QTRY_COMPARE(listview->currentItem()->y(), 30.0);
- QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
-
- canvas->rootObject()->setProperty("delegateHeight", 20);
- QTest::qWait(300);
-
- for (int i = 5; i < 11; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
- }
-
- QTRY_COMPARE(listview->currentItem()->y(), 70.0);
- QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::resizeFirstDelegate()
-{
- // QTBUG-20712: Content Y jumps constantly if first delegate height == 0
- // and other delegates have height > 0
-
- QSKIP("Test unstable - QTBUG-22872");
-
- QQuickView *canvas = createView();
- canvas->show();
-
- // bug only occurs when all items in the model are visible
- TestModel model;
- for (int i = 0; i < 10; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickItem *item = 0;
- for (int i = 0; i < model.count(); ++i) {
- item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QCOMPARE(item->y(), i*20.0);
- }
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 0);
- item->setHeight(0);
-
- // check the content y has not jumped up and down
- QCOMPARE(listview->contentY(), 0.0);
- QSignalSpy spy(listview, SIGNAL(contentYChanged()));
- QTest::qWait(100);
- QCOMPARE(spy.count(), 0);
-
- for (int i = 1; i < model.count(); ++i) {
- item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
- QTRY_COMPARE(item->y(), (i-1)*20.0);
- }
-
-
- // QTBUG-22014: refill doesn't clear items scrolling off the top of the
- // list if they follow a zero-sized delegate
-
- for (int i = 0; i < 10; i++)
- model.addItem("Item" + QString::number(i), "");
-
- item = findItem<QQuickItem>(contentItem, "wrapper", 1);
- QVERIFY(item);
- item->setHeight(0);
-
- listview->setCurrentIndex(19);
- qApp->processEvents();
-
- // items 0-2 should have been deleted
- for (int i=0; i<3; i++) {
- QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", i));
- }
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickListView::QTBUG_16037()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug16037.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "listview");
- QTRY_VERIFY(listview != 0);
-
- QVERIFY(listview->contentHeight() <= 0.0);
-
- QMetaObject::invokeMethod(canvas->rootObject(), "setModel");
-
- QTRY_COMPARE(listview->contentHeight(), 80.0);
-
- delete canvas;
-}
-
-void tst_QQuickListView::indexAt()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- for (int i = 0; i < 30; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QCOMPARE(listview->indexAt(0,0), 0);
- QCOMPARE(listview->indexAt(0,19), 0);
- QCOMPARE(listview->indexAt(239,19), 0);
- QCOMPARE(listview->indexAt(0,20), 1);
- QCOMPARE(listview->indexAt(240,20), -1);
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickListView::incrementalModel()
-{
- QQuickView *canvas = createView();
-
- IncrementalModel model;
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QTRY_COMPARE(listview->count(), 20);
-
- listview->positionViewAtIndex(10, QQuickListView::Beginning);
-
- QTRY_COMPARE(listview->count(), 25);
-
- delete canvas;
-}
-
-void tst_QQuickListView::onAdd()
-{
- QFETCH(int, initialItemCount);
- QFETCH(int, itemsToAdd);
-
- const int delegateHeight = 10;
- TestModel2 model;
-
- // these initial items should not trigger ListView.onAdd
- for (int i=0; i<initialItemCount; i++)
- model.addItem("dummy value", "dummy value");
-
- QQuickView *canvas = createView();
- canvas->setGeometry(0,0,200, delegateHeight * (initialItemCount + itemsToAdd));
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("delegateHeight", delegateHeight);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
-
- QObject *object = canvas->rootObject();
- object->setProperty("width", canvas->width());
- object->setProperty("height", canvas->height());
- qApp->processEvents();
-
- QList<QPair<QString, QString> > items;
- for (int i=0; i<itemsToAdd; i++)
- items << qMakePair(QString("value %1").arg(i), QString::number(i));
- model.addItems(items);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QVariantList result = object->property("addedDelegates").toList();
- QCOMPARE(result.count(), items.count());
- for (int i=0; i<items.count(); i++)
- QCOMPARE(result[i].toString(), items[i].first);
-
- delete canvas;
-}
-
-void tst_QQuickListView::onAdd_data()
-{
- QTest::addColumn<int>("initialItemCount");
- QTest::addColumn<int>("itemsToAdd");
-
- QTest::newRow("0, add 1") << 0 << 1;
- QTest::newRow("0, add 2") << 0 << 2;
- QTest::newRow("0, add 10") << 0 << 10;
-
- QTest::newRow("1, add 1") << 1 << 1;
- QTest::newRow("1, add 2") << 1 << 2;
- QTest::newRow("1, add 10") << 1 << 10;
-
- QTest::newRow("5, add 1") << 5 << 1;
- QTest::newRow("5, add 2") << 5 << 2;
- QTest::newRow("5, add 10") << 5 << 10;
-}
-
-void tst_QQuickListView::onRemove()
-{
- QFETCH(int, initialItemCount);
- QFETCH(int, indexToRemove);
- QFETCH(int, removeCount);
-
- const int delegateHeight = 10;
- TestModel2 model;
- for (int i=0; i<initialItemCount; i++)
- model.addItem(QString("value %1").arg(i), "dummy value");
-
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("delegateHeight", delegateHeight);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
- QObject *object = canvas->rootObject();
-
- model.removeItems(indexToRemove, removeCount);
- QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
-
- QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
-
- delete canvas;
-}
-
-void tst_QQuickListView::onRemove_data()
-{
- QTest::addColumn<int>("initialItemCount");
- QTest::addColumn<int>("indexToRemove");
- QTest::addColumn<int>("removeCount");
-
- QTest::newRow("remove first") << 1 << 0 << 1;
- QTest::newRow("two items, remove first") << 2 << 0 << 1;
- QTest::newRow("two items, remove last") << 2 << 1 << 1;
- QTest::newRow("two items, remove all") << 2 << 0 << 2;
-
- QTest::newRow("four items, remove first") << 4 << 0 << 1;
- QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
- QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
- QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
- QTest::newRow("four items, remove last") << 4 << 3 << 1;
- QTest::newRow("four items, remove all") << 4 << 0 << 4;
-
- QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
- QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
- QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
-}
-
-void tst_QQuickListView::rightToLeft()
-{
- QQuickView *canvas = createView();
- canvas->setGeometry(0,0,640,320);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
- qApp->processEvents();
-
- QVERIFY(canvas->rootObject() != 0);
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
- QTRY_VERIFY(model != 0);
-
- QTRY_VERIFY(model->count() == 3);
- QTRY_COMPARE(listview->currentIndex(), 0);
-
- // initial position at first item, right edge aligned
- QCOMPARE(listview->contentX(), -640.);
-
- QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), -100.0);
- QCOMPARE(item->height(), listview->height());
-
- QQuickText *text = findItem<QQuickText>(contentItem, "text1");
- QTRY_VERIFY(text);
- QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
-
- listview->setCurrentIndex(2);
-
- item = findItem<QQuickItem>(contentItem, "item3");
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), -540.0);
-
- text = findItem<QQuickText>(contentItem, "text3");
- QTRY_VERIFY(text);
- QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
-
- QCOMPARE(listview->contentX(), -640.);
-
- // Ensure resizing maintains position relative to right edge
- qobject_cast<QQuickItem*>(canvas->rootObject())->setWidth(600);
- QTRY_COMPARE(listview->contentX(), -600.);
-
- delete canvas;
-}
-
-void tst_QQuickListView::test_mirroring()
-{
- QQuickView *canvasA = createView();
- canvasA->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
- QQuickListView *listviewA = findItem<QQuickListView>(canvasA->rootObject(), "view");
- QTRY_VERIFY(listviewA != 0);
-
- QQuickView *canvasB = createView();
- canvasB->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
- QQuickListView *listviewB = findItem<QQuickListView>(canvasB->rootObject(), "view");
- QTRY_VERIFY(listviewA != 0);
- qApp->processEvents();
-
- QList<QString> objectNames;
- objectNames << "item1" << "item2"; // << "item3"
-
- listviewA->setProperty("layoutDirection", Qt::LeftToRight);
- listviewB->setProperty("layoutDirection", Qt::RightToLeft);
- QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
-
- // LTR != RTL
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
-
- listviewA->setProperty("layoutDirection", Qt::LeftToRight);
- listviewB->setProperty("layoutDirection", Qt::LeftToRight);
-
- // LTR == LTR
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
-
- QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
- QQuickItemPrivate::get(listviewB)->setLayoutMirror(true);
- QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
-
- // LTR != LTR+mirror
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
-
- listviewA->setProperty("layoutDirection", Qt::RightToLeft);
-
- // RTL == LTR+mirror
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
-
- listviewB->setProperty("layoutDirection", Qt::RightToLeft);
-
- // RTL != RTL+mirror
- foreach (const QString objectName, objectNames)
- QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
-
- listviewA->setProperty("layoutDirection", Qt::LeftToRight);
-
- // LTR == RTL+mirror
- foreach (const QString objectName, objectNames)
- QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
-
- delete canvasA;
- delete canvasB;
-}
-
-void tst_QQuickListView::margins()
-{
- QQuickView *canvas = createView();
-
- TestModel2 model;
- for (int i = 0; i < 50; i++)
- model.addItem("Item" + QString::number(i), "");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- QCOMPARE(listview->contentY(), -30.);
- QCOMPARE(listview->yOrigin(), 0.);
-
- // check end bound
- listview->positionViewAtEnd();
- qreal pos = listview->contentY();
- listview->setContentY(pos + 80);
- listview->returnToBounds();
- QTRY_COMPARE(listview->contentY(), pos + 50);
-
- // remove item before visible and check that top margin is maintained
- // and yOrigin is updated
- listview->setContentY(100);
- model.removeItem(1);
- QTest::qWait(100);
- listview->setContentY(-50);
- listview->returnToBounds();
- QCOMPARE(listview->yOrigin(), 20.);
- QTRY_COMPARE(listview->contentY(), -10.);
-
- // reduce top margin
- listview->setTopMargin(20);
- QCOMPARE(listview->yOrigin(), 20.);
- QTRY_COMPARE(listview->contentY(), 0.);
-
- // check end bound
- listview->positionViewAtEnd();
- pos = listview->contentY();
- listview->setContentY(pos + 80);
- listview->returnToBounds();
- QTRY_COMPARE(listview->contentY(), pos + 50);
-
- // reduce bottom margin
- pos = listview->contentY();
- listview->setBottomMargin(40);
- QCOMPARE(listview->yOrigin(), 20.);
- QTRY_COMPARE(listview->contentY(), pos-10);
-
- delete canvas;
-}
-
-void tst_QQuickListView::snapToItem_data()
-{
- QTest::addColumn<QQuickListView::Orientation>("orientation");
- QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
- QTest::addColumn<int>("highlightRangeMode");
- QTest::addColumn<QPoint>("flickStart");
- QTest::addColumn<QPoint>("flickEnd");
- QTest::addColumn<qreal>("snapAlignment");
- QTest::addColumn<qreal>("endExtent");
- QTest::addColumn<qreal>("startExtent");
-
- QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
-
- QTest::newRow("horizontal, left to right") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
-
- QTest::newRow("horizontal, right to left") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
-
- QTest::newRow("vertical, left to right, enforce range") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
-
- QTest::newRow("horizontal, left to right, enforce range") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
-
- QTest::newRow("horizontal, right to left, enforce range") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
-}
-
-void tst_QQuickListView::snapToItem()
-{
- QFETCH(QQuickListView::Orientation, orientation);
- QFETCH(Qt::LayoutDirection, layoutDirection);
- QFETCH(int, highlightRangeMode);
- QFETCH(QPoint, flickStart);
- QFETCH(QPoint, flickEnd);
- QFETCH(qreal, snapAlignment);
- QFETCH(qreal, endExtent);
- QFETCH(qreal, startExtent);
-
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToItem.qml")));
- canvas->show();
- qApp->processEvents();
-
- QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
-
- listview->setOrientation(orientation);
- listview->setLayoutDirection(layoutDirection);
- listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
-
- QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- // confirm that a flick hits an item boundary
- flick(canvas, flickStart, flickEnd, 180);
- QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
- if (orientation == QQuickListView::Vertical)
- QCOMPARE(qreal(fmod(listview->contentY(),80.0)), snapAlignment);
- else
- QCOMPARE(qreal(fmod(listview->contentX(),80.0)), snapAlignment);
-
- // flick to end
- do {
- flick(canvas, flickStart, flickEnd, 180);
- QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
- } while (orientation == QQuickListView::Vertical
- ? !listview->isAtYEnd()
- : layoutDirection == Qt::LeftToRight ? !listview->isAtXEnd() : !listview->isAtXBeginning());
-
- if (orientation == QQuickListView::Vertical)
- QCOMPARE(listview->contentY(), endExtent);
- else
- QCOMPARE(listview->contentX(), endExtent);
-
- // flick to start
- do {
- flick(canvas, flickEnd, flickStart, 180);
- QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
- } while (orientation == QQuickListView::Vertical
- ? !listview->isAtYBeginning()
- : layoutDirection == Qt::LeftToRight ? !listview->isAtXBeginning() : !listview->isAtXEnd());
-
- if (orientation == QQuickListView::Vertical)
- QCOMPARE(listview->contentY(), startExtent);
- else
- QCOMPARE(listview->contentX(), startExtent);
-
- delete canvas;
-}
-
-void tst_QQuickListView::qListModelInterface_items()
-{
- items<TestModel>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_items()
-{
- items<TestModel2>();
-}
-
-void tst_QQuickListView::qListModelInterface_changed()
-{
- changed<TestModel>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_changed()
-{
- changed<TestModel2>();
-}
-
-void tst_QQuickListView::qListModelInterface_inserted()
-{
- inserted<TestModel>();
-}
-
-void tst_QQuickListView::qListModelInterface_inserted_more()
-{
- inserted_more<TestModel>();
-}
-
-void tst_QQuickListView::qListModelInterface_inserted_more_data()
-{
- inserted_more_data();
-}
-
-void tst_QQuickListView::qAbstractItemModel_inserted()
-{
- inserted<TestModel2>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_inserted_more()
-{
- inserted_more<TestModel2>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_inserted_more_data()
-{
- inserted_more_data();
-}
-
-void tst_QQuickListView::qListModelInterface_removed()
-{
- removed<TestModel>(false);
- removed<TestModel>(true);
-}
-
-void tst_QQuickListView::qAbstractItemModel_removed()
-{
- removed<TestModel2>(false);
- removed<TestModel2>(true);
-}
-
-void tst_QQuickListView::qListModelInterface_moved()
-{
- moved<TestModel>();
-}
-
-void tst_QQuickListView::qListModelInterface_moved_data()
-{
- moved_data();
-}
-
-void tst_QQuickListView::qAbstractItemModel_moved()
-{
- moved<TestModel2>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_moved_data()
-{
- moved_data();
-}
-
-void tst_QQuickListView::qListModelInterface_clear()
-{
- clear<TestModel>();
-}
-
-void tst_QQuickListView::qAbstractItemModel_clear()
-{
- clear<TestModel2>();
-}
-
-void tst_QQuickListView::creationContext()
-{
- QQuickView canvas;
- canvas.setGeometry(0,0,240,320);
- canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
- qApp->processEvents();
-
- QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
- QVERIFY(rootItem);
- QVERIFY(rootItem->property("count").toInt() > 0);
-
- QQuickItem *item;
- QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
- QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
- QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
- QVERIFY(item = rootItem->findChild<QQuickItem *>("section"));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
-}
-
-void tst_QQuickListView::QTBUG_21742()
-{
- QQuickView canvas;
- canvas.setGeometry(0,0,200,200);
- canvas.setSource(QUrl::fromLocalFile(TESTDATA("qtbug-21742.qml")));
- qApp->processEvents();
-
- QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
- QVERIFY(rootItem);
- QCOMPARE(rootItem->property("count").toInt(), 1);
-}
-
-QQuickView *tst_QQuickListView::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- return canvas;
-}
-
-void tst_QQuickListView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
-{
- const int pointCount = 5;
- QPoint diff = to - from;
-
- // send press, five equally spaced moves, and release.
- QTest::mousePress(canvas, Qt::LeftButton, 0, from);
-
- for (int i = 0; i < pointCount; ++i) {
- QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- QTest::qWait(duration/pointCount);
- QCoreApplication::processEvents();
- }
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
-}
-
-void tst_QQuickListView::asynchronous()
-{
- QQuickView *canvas = createView();
- canvas->show();
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- canvas->setSource(TESTDATA("asyncloader.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootObject);
-
- QQuickListView *listview = 0;
- while (!listview) {
- bool b = false;
- controller.incubateWhile(&b);
- listview = rootObject->findChild<QQuickListView*>("view");
- }
-
- // items will be created one at a time
- for (int i = 0; i < 8; ++i) {
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(listview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- // verify positioning
- QQuickItem *contentItem = listview->contentItem();
- for (int i = 0; i < 8; ++i) {
- QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_COMPARE(item->y(), i*50.0);
- }
-
- delete canvas;
-}
-
-QQuickItem *tst_QQuickListView::findVisibleChild(QQuickItem *parent, const QString &objectName)
-{
- QQuickItem *item = 0;
- QList<QQuickItem*> items = parent->findChildren<QQuickItem*>(objectName);
- for (int i = 0; i < items.count(); ++i) {
- if (items.at(i)->isVisible()) {
- item = items.at(i);
- break;
- }
- }
- return item;
-}
-/*
- Find an item with the specified objectName. If index is supplied then the
- item must also evaluate the {index} expression equal to index
-*/
-template<typename T>
-T *tst_QQuickListView::findItem(QQuickItem *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeExpression e(qmlContext(item), item, "index");
- if (e.evaluate().toInt() == index)
- return static_cast<T*>(item);
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-template<typename T>
-QList<T*> tst_QQuickListView::findItems(QQuickItem *parent, const QString &objectName)
-{
- QList<T*> items;
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item || !item->isVisible())
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
- items.append(static_cast<T*>(item));
- items += findItems<T>(item, objectName);
- }
-
- return items;
-}
-
-void tst_QQuickListView::dumpTree(QQuickItem *parent, int depth)
-{
- static QString padding(" ");
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- qDebug() << padding.left(depth*2) << item;
- dumpTree(item, depth+1);
- }
-}
-
-QTEST_MAIN(tst_QQuickListView)
-
-#include "tst_qquicklistview.moc"
-
diff --git a/tests/auto/declarative/qquickloader/qquickloader.pro b/tests/auto/declarative/qquickloader/qquickloader.pro
deleted file mode 100644
index 9ccecce478..0000000000
--- a/tests/auto/declarative/qquickloader/qquickloader.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickloader
-macx:CONFIG -= app_bundle
-
-INCLUDEPATH += ../shared/
-HEADERS += ../shared/testhttpserver.h
-SOURCES += tst_qquickloader.cpp \
- ../shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickloader/tst_qquickloader.cpp b/tests/auto/declarative/qquickloader/tst_qquickloader.cpp
deleted file mode 100644
index 96d0d88a84..0000000000
--- a/tests/auto/declarative/qquickloader/tst_qquickloader.cpp
+++ /dev/null
@@ -1,969 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-
-#include <QSignalSpy>
-
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-#include <private/qquickloader_p.h>
-#include "testhttpserver.h"
-#include "../shared/util.h"
-
-#define SERVER_PORT 14450
-
-inline QUrl TEST_FILE(const QString &filename)
-{
- return QUrl::fromLocalFile(TESTDATA(filename));
-}
-
-class PeriodicIncubationController : public QObject,
- public QDeclarativeIncubationController
-{
-public:
- PeriodicIncubationController() {
- startTimer(16);
- }
-
-protected:
- virtual void timerEvent(QTimerEvent *) {
- incubateFor(15);
- }
-};
-
-class tst_QQuickLoader : public QObject
-
-{
- Q_OBJECT
-public:
- tst_QQuickLoader();
-
-private slots:
- void sourceOrComponent();
- void sourceOrComponent_data();
- void clear();
- void urlToComponent();
- void componentToUrl();
- void anchoredLoader();
- void sizeLoaderToItem();
- void sizeItemToLoader();
- void noResize();
- void networkRequestUrl();
- void failNetworkRequest();
-// void networkComponent();
- void active();
- void initialPropertyValues_data();
- void initialPropertyValues();
- void initialPropertyValuesBinding();
- void initialPropertyValuesError_data();
- void initialPropertyValuesError();
-
- void deleteComponentCrash();
- void nonItem();
- void vmeErrors();
- void creationContext();
- void QTBUG_16928();
- void implicitSize();
- void QTBUG_17114();
- void asynchronous_data();
- void asynchronous();
- void asynchronous_clear();
-
- void parented();
-
-private:
- QDeclarativeEngine engine;
-};
-
-
-tst_QQuickLoader::tst_QQuickLoader()
-{
-}
-
-void tst_QQuickLoader::sourceOrComponent()
-{
- QFETCH(QString, sourceOrComponent);
- QFETCH(QString, sourceDefinition);
- QFETCH(QUrl, sourceUrl);
- QFETCH(QString, errorString);
-
- bool error = !errorString.isEmpty();
- if (error)
- QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData());
-
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray(
- "import QtQuick 2.0\n"
- "Loader {\n"
- " property int onItemChangedCount: 0\n"
- " property int onSourceChangedCount: 0\n"
- " property int onSourceComponentChangedCount: 0\n"
- " property int onStatusChangedCount: 0\n"
- " property int onProgressChangedCount: 0\n"
- " property int onLoadedCount: 0\n")
- + sourceDefinition.toUtf8()
- + QByteArray(
- " onItemChanged: onItemChangedCount += 1\n"
- " onSourceChanged: onSourceChangedCount += 1\n"
- " onSourceComponentChanged: onSourceComponentChangedCount += 1\n"
- " onStatusChanged: onStatusChangedCount += 1\n"
- " onProgressChanged: onProgressChangedCount += 1\n"
- " onLoaded: onLoadedCount += 1\n"
- "}")
- , TEST_FILE(""));
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
- QCOMPARE(loader->item() == 0, error);
- QCOMPARE(loader->source(), sourceUrl);
- QCOMPARE(loader->progress(), 1.0);
-
- QCOMPARE(loader->status(), error ? QQuickLoader::Error : QQuickLoader::Ready);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), error ? 0: 1);
-
- if (!error) {
- bool sourceComponentIsChildOfLoader = false;
- for (int ii = 0; ii < loader->children().size(); ++ii) {
- QDeclarativeComponent *c = qobject_cast<QDeclarativeComponent*>(loader->children().at(ii));
- if (c && c == loader->sourceComponent()) {
- sourceComponentIsChildOfLoader = true;
- }
- }
- QVERIFY(sourceComponentIsChildOfLoader);
- }
-
- if (sourceOrComponent == "component") {
- QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 1);
- QCOMPARE(loader->property("onSourceChangedCount").toInt(), 0);
- } else {
- QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 0);
- QCOMPARE(loader->property("onSourceChangedCount").toInt(), 1);
- }
- QCOMPARE(loader->property("onStatusChangedCount").toInt(), 1);
- QCOMPARE(loader->property("onProgressChangedCount").toInt(), 1);
-
- QCOMPARE(loader->property("onItemChangedCount").toInt(), error ? 0 : 1);
- QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1);
-
- delete loader;
-}
-
-void tst_QQuickLoader::sourceOrComponent_data()
-{
- QTest::addColumn<QString>("sourceOrComponent");
- QTest::addColumn<QString>("sourceDefinition");
- QTest::addColumn<QUrl>("sourceUrl");
- QTest::addColumn<QString>("errorString");
-
- QTest::newRow("source") << "source" << "source: 'Rect120x60.qml'\n" << QUrl::fromLocalFile(TESTDATA("Rect120x60.qml")) << "";
- QTest::newRow("sourceComponent") << "component" << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << "";
- QTest::newRow("invalid source") << "source" << "source: 'IDontExist.qml'\n" << QUrl::fromLocalFile(TESTDATA("IDontExist.qml"))
- << QString(QUrl::fromLocalFile(TESTDATA("IDontExist.qml")).toString() + ": File not found");
-}
-
-void tst_QQuickLoader::clear()
-{
- {
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray(
- "import QtQuick 2.0\n"
- " Loader { id: loader\n"
- " source: 'Rect120x60.qml'\n"
- " Timer { interval: 200; running: true; onTriggered: loader.source = '' }\n"
- " }")
- , TEST_FILE(""));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- QTRY_VERIFY(loader->item() == 0);
- QCOMPARE(loader->progress(), 0.0);
- QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete loader;
- }
- {
- QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
- QVERIFY(loader);
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- loader->setSourceComponent(0);
-
- QVERIFY(loader->item() == 0);
- QCOMPARE(loader->progress(), 0.0);
- QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete item;
- }
- {
- QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
- QVERIFY(loader);
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- QMetaObject::invokeMethod(item, "clear");
-
- QVERIFY(loader->item() == 0);
- QCOMPARE(loader->progress(), 0.0);
- QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete item;
- }
-}
-
-void tst_QQuickLoader::urlToComponent()
-{
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\n"
- "Loader {\n"
- " id: loader\n"
- " Component { id: myComp; Rectangle { width: 10; height: 10 } }\n"
- " source: \"Rect120x60.qml\"\n"
- " Timer { interval: 100; running: true; onTriggered: loader.sourceComponent = myComp }\n"
- "}" )
- , TEST_FILE(""));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QTest::qWait(200);
- QTRY_VERIFY(loader != 0);
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QCOMPARE(loader->width(), 10.0);
- QCOMPARE(loader->height(), 10.0);
-
- delete loader;
-}
-
-void tst_QQuickLoader::componentToUrl()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
- QVERIFY(loader);
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- loader->setSource(TEST_FILE("/Rect120x60.qml"));
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QCOMPARE(loader->width(), 120.0);
- QCOMPARE(loader->height(), 60.0);
-
- delete item;
-}
-
-void tst_QQuickLoader::anchoredLoader()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("/AnchoredLoader.qml"));
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(rootItem != 0);
- QQuickItem *loader = rootItem->findChild<QQuickItem*>("loader");
- QQuickItem *sourceElement = rootItem->findChild<QQuickItem*>("sourceElement");
-
- QVERIFY(loader != 0);
- QVERIFY(sourceElement != 0);
-
- QCOMPARE(rootItem->width(), 300.0);
- QCOMPARE(rootItem->height(), 200.0);
-
- QCOMPARE(loader->width(), 300.0);
- QCOMPARE(loader->height(), 200.0);
-
- QCOMPARE(sourceElement->width(), 300.0);
- QCOMPARE(sourceElement->height(), 200.0);
-}
-
-void tst_QQuickLoader::sizeLoaderToItem()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("/SizeToItem.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
- QCOMPARE(loader->width(), 120.0);
- QCOMPARE(loader->height(), 60.0);
-
- // Check resize
- QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
- QVERIFY(rect);
- rect->setWidth(150);
- rect->setHeight(45);
- QCOMPARE(loader->width(), 150.0);
- QCOMPARE(loader->height(), 45.0);
-
- // Check explicit width
- loader->setWidth(200.0);
- QCOMPARE(loader->width(), 200.0);
- QCOMPARE(rect->width(), 200.0);
- rect->setWidth(100.0); // when rect changes ...
- QCOMPARE(rect->width(), 100.0); // ... it changes
- QCOMPARE(loader->width(), 200.0); // ... but loader stays the same
-
- // Check explicit height
- loader->setHeight(200.0);
- QCOMPARE(loader->height(), 200.0);
- QCOMPARE(rect->height(), 200.0);
- rect->setHeight(100.0); // when rect changes ...
- QCOMPARE(rect->height(), 100.0); // ... it changes
- QCOMPARE(loader->height(), 200.0); // ... but loader stays the same
-
- // Switch mode
- loader->setWidth(180);
- loader->setHeight(30);
- QCOMPARE(rect->width(), 180.0);
- QCOMPARE(rect->height(), 30.0);
-
- delete loader;
-}
-
-void tst_QQuickLoader::sizeItemToLoader()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("/SizeToLoader.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
- QCOMPARE(loader->width(), 200.0);
- QCOMPARE(loader->height(), 80.0);
-
- QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
- QVERIFY(rect);
- QCOMPARE(rect->width(), 200.0);
- QCOMPARE(rect->height(), 80.0);
-
- // Check resize
- loader->setWidth(180);
- loader->setHeight(30);
- QCOMPARE(rect->width(), 180.0);
- QCOMPARE(rect->height(), 30.0);
-
- // Switch mode
- loader->resetWidth(); // reset explicit size
- loader->resetHeight();
- rect->setWidth(160);
- rect->setHeight(45);
- QCOMPARE(loader->width(), 160.0);
- QCOMPARE(loader->height(), 45.0);
-
- delete loader;
-}
-
-void tst_QQuickLoader::noResize()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("/NoResize.qml"));
- QQuickItem* item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != 0);
- QCOMPARE(item->width(), 200.0);
- QCOMPARE(item->height(), 80.0);
-
- delete item;
-}
-
-void tst_QQuickLoader::networkRequestUrl()
-{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nLoader { property int signalCount : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: signalCount += 1 }"), QUrl::fromLocalFile(TESTDATA("../dummy.qml")));
- if (component.isError())
- qDebug() << component.errors();
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
-
- QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
-
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(loader->property("signalCount").toInt(), 1);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- delete loader;
-}
-
-/* XXX Component waits until all dependencies are loaded. Is this actually possible?
-void tst_QQuickLoader::networkComponent()
-{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory("slowdata", TestHTTPServer::Delay);
-
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray(
- "import QtQuick 2.0\n"
- "import \"http://127.0.0.1:14450/\" as NW\n"
- "Item {\n"
- " Component { id: comp; NW.SlowRect {} }\n"
- " Loader { sourceComponent: comp } }")
- , TEST_FILE(""));
-
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::children().at(1));
- QVERIFY(loader);
- QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
-
- QVERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(loader->status(), QQuickLoader::Ready);
- QCOMPARE(static_cast<QQuickItem*>(loader)->children().count(), 1);
-
- delete loader;
-}
-*/
-
-void tst_QQuickLoader::failNetworkRequest()
-{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- QTest::ignoreMessage(QtWarningMsg, "http://127.0.0.1:14450/IDontExist.qml: File not found");
-
- QDeclarativeComponent component(&engine);
- component.setData(QByteArray("import QtQuick 2.0\nLoader { property int did_load: 123; source: \"http://127.0.0.1:14450/IDontExist.qml\"; onLoaded: did_load=456 }"), QUrl::fromLocalFile("http://127.0.0.1:14450/dummy.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
-
- QTRY_VERIFY(loader->status() == QQuickLoader::Error);
-
- QVERIFY(loader->item() == 0);
- QCOMPARE(loader->progress(), 0.0);
- QCOMPARE(loader->property("did_load").toInt(), 123);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete loader;
-}
-
-void tst_QQuickLoader::active()
-{
- // check that the item isn't instantiated until active is set to true
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == false); // set manually to false
- QVERIFY(loader->item() == 0);
- QMetaObject::invokeMethod(object, "doSetSourceComponent");
- QVERIFY(loader->item() == 0);
- QMetaObject::invokeMethod(object, "doSetSource");
- QVERIFY(loader->item() == 0);
- QMetaObject::invokeMethod(object, "doSetActive");
- QVERIFY(loader->item() != 0);
-
- delete object;
- }
-
- // check that the status is Null if active is set to false
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == true); // active is true by default
- QCOMPARE(loader->status(), QQuickLoader::Ready);
- int currStatusChangedCount = loader->property("statusChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
- QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(loader->property("statusChangedCount").toInt(), (currStatusChangedCount+1));
-
- delete object;
- }
-
- // check that the source is not cleared if active is set to false
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == true); // active is true by default
- QVERIFY(!loader->source().isEmpty());
- int currSourceChangedCount = loader->property("sourceChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
- QVERIFY(!loader->source().isEmpty());
- QCOMPARE(loader->property("sourceChangedCount").toInt(), currSourceChangedCount);
-
- delete object;
- }
-
- // check that the sourceComponent is not cleared if active is set to false
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.4.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == true); // active is true by default
- QVERIFY(loader->sourceComponent() != 0);
- int currSourceComponentChangedCount = loader->property("sourceComponentChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
- QVERIFY(loader->sourceComponent() != 0);
- QCOMPARE(loader->property("sourceComponentChangedCount").toInt(), currSourceComponentChangedCount);
-
- delete object;
- }
-
- // check that the item is released if active is set to false
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.5.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == true); // active is true by default
- QVERIFY(loader->item() != 0);
- int currItemChangedCount = loader->property("itemChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
- QVERIFY(loader->item() == 0);
- QCOMPARE(loader->property("itemChangedCount").toInt(), (currItemChangedCount+1));
-
- delete object;
- }
-
- // check that the activeChanged signal is emitted correctly
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.6.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
-
- QVERIFY(loader->active() == true); // active is true by default
- loader->setActive(true); // no effect
- QCOMPARE(loader->property("activeChangedCount").toInt(), 0);
- loader->setActive(false); // change signal should be emitted
- QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
- loader->setActive(false); // no effect
- QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
- loader->setActive(true); // change signal should be emitted
- QCOMPARE(loader->property("activeChangedCount").toInt(), 2);
- loader->setActive(false); // change signal should be emitted
- QCOMPARE(loader->property("activeChangedCount").toInt(), 3);
- QMetaObject::invokeMethod(object, "doSetActive");
- QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
- QMetaObject::invokeMethod(object, "doSetActive");
- QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
- QMetaObject::invokeMethod(object, "doSetInactive");
- QCOMPARE(loader->property("activeChangedCount").toInt(), 5);
- loader->setActive(true); // change signal should be emitted
- QCOMPARE(loader->property("activeChangedCount").toInt(), 6);
-
- delete object;
- }
-
- // check that the component isn't loaded until active is set to true
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.7.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QCOMPARE(object->property("success").toBool(), true);
- delete object;
- }
-
- // check that the component is loaded if active is not set (true by default)
- {
- QDeclarativeComponent component(&engine, TEST_FILE("active.8.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QCOMPARE(object->property("success").toBool(), true);
- delete object;
- }
-}
-
-void tst_QQuickLoader::initialPropertyValues_data()
-{
- QTest::addColumn<QUrl>("qmlFile");
- QTest::addColumn<QStringList>("expectedWarnings");
- QTest::addColumn<QStringList>("propertyNames");
- QTest::addColumn<QVariantList>("propertyValues");
-
- QTest::newRow("source url with value set in onLoaded, initially active = true") << TEST_FILE("initialPropertyValues.1.qml")
- << QStringList()
- << (QStringList() << "initialValue" << "behaviorCount")
- << (QVariantList() << 1 << 1);
-
- QTest::newRow("set source with initial property values specified, active = true") << TEST_FILE("initialPropertyValues.2.qml")
- << QStringList()
- << (QStringList() << "initialValue" << "behaviorCount")
- << (QVariantList() << 2 << 0);
-
- QTest::newRow("set source with initial property values specified, active = false") << TEST_FILE("initialPropertyValues.3.qml")
- << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("initialPropertyValues.3.qml").toLocalFile() + QLatin1String(":16: TypeError: Cannot read property 'canary' of null")))
- << (QStringList())
- << (QVariantList());
-
- QTest::newRow("set source with initial property values specified, active = false, with active set true later") << TEST_FILE("initialPropertyValues.4.qml")
- << QStringList()
- << (QStringList() << "initialValue" << "behaviorCount")
- << (QVariantList() << 4 << 0);
-
- QTest::newRow("set source without initial property values specified, active = true") << TEST_FILE("initialPropertyValues.5.qml")
- << QStringList()
- << (QStringList() << "initialValue" << "behaviorCount")
- << (QVariantList() << 0 << 0);
-
- QTest::newRow("set source with initial property values specified with binding, active = true") << TEST_FILE("initialPropertyValues.6.qml")
- << QStringList()
- << (QStringList() << "initialValue" << "behaviorCount")
- << (QVariantList() << 6 << 0);
-
- QTest::newRow("ensure initial property value semantics mimic createObject") << TEST_FILE("initialPropertyValues.7.qml")
- << QStringList()
- << (QStringList() << "loaderValue" << "createObjectValue")
- << (QVariantList() << 1 << 1);
-
- QTest::newRow("ensure initial property values aren't disposed prior to component completion") << TEST_FILE("initialPropertyValues.8.qml")
- << QStringList()
- << (QStringList() << "initialValue")
- << (QVariantList() << 6);
-}
-
-void tst_QQuickLoader::initialPropertyValues()
-{
- QFETCH(QUrl, qmlFile);
- QFETCH(QStringList, expectedWarnings);
- QFETCH(QStringList, propertyNames);
- QFETCH(QVariantList, propertyValues);
-
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
- server.serveDirectory(TESTDATA(""));
-
- foreach (const QString &warning, expectedWarnings)
- QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
-
- QDeclarativeComponent component(&engine, qmlFile);
- QObject *object = component.create();
- QVERIFY(object != 0);
- qApp->processEvents();
- QTest::qWait(50);
-
- for (int i = 0; i < propertyNames.size(); ++i)
- QCOMPARE(object->property(propertyNames.at(i).toAscii().constData()), propertyValues.at(i));
-
- delete object;
-}
-
-void tst_QQuickLoader::initialPropertyValuesBinding()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("initialPropertyValues.binding.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
-
- QVERIFY(object->setProperty("bindable", QVariant(8)));
- QCOMPARE(object->property("canaryValue").toInt(), 8);
-
- delete object;
-}
-
-void tst_QQuickLoader::initialPropertyValuesError_data()
-{
- QTest::addColumn<QUrl>("qmlFile");
- QTest::addColumn<QStringList>("expectedWarnings");
-
- QTest::newRow("invalid initial property values object") << TEST_FILE("initialPropertyValues.error.1.qml")
- << (QStringList() << QString(TEST_FILE("initialPropertyValues.error.1.qml").toString() + ":6:5: QML Loader: setSource: value is not an object"));
-
- QTest::newRow("nonexistent source url") << TEST_FILE("initialPropertyValues.error.2.qml")
- << (QStringList() << QString(TEST_FILE("NonexistentSourceComponent.qml").toString() + ": File not found"));
-
- QTest::newRow("invalid source url") << TEST_FILE("initialPropertyValues.error.3.qml")
- << (QStringList() << QString(TEST_FILE("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
-
- QTest::newRow("invalid initial property values object with invalid property access") << TEST_FILE("initialPropertyValues.error.4.qml")
- << (QStringList() << QString(TEST_FILE("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
- << QString(TEST_FILE("initialPropertyValues.error.4.qml").toString() + ":5: TypeError: Cannot read property 'canary' of null"));
-}
-
-void tst_QQuickLoader::initialPropertyValuesError()
-{
- QFETCH(QUrl, qmlFile);
- QFETCH(QStringList, expectedWarnings);
-
- foreach (const QString &warning, expectedWarnings)
- QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
-
- QDeclarativeComponent component(&engine, qmlFile);
- QObject *object = component.create();
- QVERIFY(object != 0);
- QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
- QVERIFY(loader != 0);
- QVERIFY(loader->item() == 0);
- delete object;
-}
-
-// QTBUG-9241
-void tst_QQuickLoader::deleteComponentCrash()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("crash.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- item->metaObject()->invokeMethod(item, "setLoaderSource");
-
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
- QVERIFY(loader);
- QVERIFY(loader->item());
- QCOMPARE(loader->item()->objectName(), QLatin1String("blue"));
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(loader->status(), QQuickLoader::Ready);
- qApp->processEvents(QEventLoop::DeferredDeletion);
- QTRY_COMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QVERIFY(loader->source() == QUrl::fromLocalFile(TESTDATA("BlueRect.qml")));
-
- delete item;
-}
-
-void tst_QQuickLoader::nonItem()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("nonItem.qml"));
- QString err = QUrl::fromLocalFile(TESTDATA("nonItem.qml")).toString() + ":3:1: QML Loader: Loader does not support loading non-visual elements.";
-
- QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader);
- QVERIFY(loader->item() == 0);
-
- delete loader;
-}
-
-void tst_QQuickLoader::vmeErrors()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("vmeErrors.qml"));
- QString err = QUrl::fromLocalFile(TESTDATA("VmeError.qml")).toString() + ":6: Cannot assign object type QObject with no default method";
- QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader);
- QVERIFY(loader->item() == 0);
-
- delete loader;
-}
-
-// QTBUG-13481
-void tst_QQuickLoader::creationContext()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("creationContext.qml"));
-
- QObject *o = component.create();
- QVERIFY(o != 0);
-
- QCOMPARE(o->property("test").toBool(), true);
-
- delete o;
-}
-
-void tst_QQuickLoader::QTBUG_16928()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_16928.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QCOMPARE(item->width(), 250.);
- QCOMPARE(item->height(), 250.);
-
- delete item;
-}
-
-void tst_QQuickLoader::implicitSize()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("implicitSize.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QCOMPARE(item->width(), 150.);
- QCOMPARE(item->height(), 150.);
-
- QCOMPARE(item->property("implHeight").toReal(), 100.);
- QCOMPARE(item->property("implWidth").toReal(), 100.);
-
- delete item;
-}
-
-void tst_QQuickLoader::QTBUG_17114()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_17114.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
-
- QCOMPARE(item->property("loaderWidth").toReal(), 32.);
- QCOMPARE(item->property("loaderHeight").toReal(), 32.);
-
- delete item;
-}
-
-void tst_QQuickLoader::asynchronous_data()
-{
- QTest::addColumn<QUrl>("qmlFile");
- QTest::addColumn<QStringList>("expectedWarnings");
-
- QTest::newRow("Valid component") << TEST_FILE("BigComponent.qml")
- << QStringList();
-
- QTest::newRow("Non-existant component") << TEST_FILE("IDoNotExist.qml")
- << (QStringList() << QString(TEST_FILE("IDoNotExist.qml").toString() + ": File not found"));
-
- QTest::newRow("Invalid component") << TEST_FILE("InvalidSourceComponent.qml")
- << (QStringList() << QString(TEST_FILE("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
-}
-
-void tst_QQuickLoader::asynchronous()
-{
- QFETCH(QUrl, qmlFile);
- QFETCH(QStringList, expectedWarnings);
-
- if (!engine.incubationController())
- engine.setIncubationController(new PeriodicIncubationController);
- QDeclarativeComponent component(&engine, TEST_FILE("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(root);
-
- QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
- QVERIFY(loader);
-
- foreach (const QString &warning, expectedWarnings)
- QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
-
- QVERIFY(!loader->item());
- root->setProperty("comp", qmlFile.toString());
- QMetaObject::invokeMethod(root, "loadComponent");
- QVERIFY(!loader->item());
-
- if (expectedWarnings.isEmpty()) {
- QCOMPARE(loader->status(), QQuickLoader::Loading);
- QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
-
- QTRY_VERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(loader->status(), QQuickLoader::Ready);
- } else {
- QCOMPARE(loader->progress(), 1.0);
- QTRY_COMPARE(loader->status(), QQuickLoader::Error);
- }
-
- delete root;
-}
-
-void tst_QQuickLoader::asynchronous_clear()
-{
- if (!engine.incubationController())
- engine.setIncubationController(new PeriodicIncubationController);
- QDeclarativeComponent component(&engine, TEST_FILE("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(root);
-
- QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
- QVERIFY(loader);
-
- QVERIFY(!loader->item());
- root->setProperty("comp", "BigComponent.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
- QVERIFY(!loader->item());
-
- QCOMPARE(loader->status(), QQuickLoader::Loading);
- QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
-
- // clear before component created
- root->setProperty("comp", "");
- QMetaObject::invokeMethod(root, "loadComponent");
- QVERIFY(!loader->item());
- QCOMPARE(engine.incubationController()->incubatingObjectCount(), 0);
-
- QCOMPARE(loader->progress(), 0.0);
- QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- // check loading component
- root->setProperty("comp", "Rect120x60.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
- QVERIFY(!loader->item());
-
- QCOMPARE(loader->status(), QQuickLoader::Loading);
- QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
-
- QTRY_VERIFY(loader->item());
- QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(loader->status(), QQuickLoader::Ready);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-}
-
-void tst_QQuickLoader::parented()
-{
- QDeclarativeComponent component(&engine, TEST_FILE("parented.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(root);
-
- QQuickItem *item = root->findChild<QQuickItem*>("comp");
- QVERIFY(item);
-
- QVERIFY(item->parentItem() == root);
-
- QCOMPARE(item->width(), 300.);
- QCOMPARE(item->height(), 300.);
-
- delete root;
-}
-
-
-QTEST_MAIN(tst_QQuickLoader)
-
-#include "tst_qquickloader.moc"
diff --git a/tests/auto/declarative/qquickmousearea/qquickmousearea.pro b/tests/auto/declarative/qquickmousearea/qquickmousearea.pro
deleted file mode 100644
index 3581a7b9c9..0000000000
--- a/tests/auto/declarative/qquickmousearea/qquickmousearea.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickmousearea
-macx:CONFIG -= app_bundle
-
-HEADERS += ../shared/testhttpserver.h
-SOURCES += tst_qquickmousearea.cpp ../shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/declarative/qquickmousearea/tst_qquickmousearea.cpp
deleted file mode 100644
index ac1eea7a41..0000000000
--- a/tests/auto/declarative/qquickmousearea/tst_qquickmousearea.cpp
+++ /dev/null
@@ -1,824 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <private/qquickmousearea_p.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquickflickable_p.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtOpenGL/QGLShaderProgram>
-#include "../shared/util.h"
-
-//#define OLDWAY
-
-class tst_QQuickMouseArea: public QObject
-{
- Q_OBJECT
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void dragProperties();
- void resetDrag();
- void dragging();
- void updateMouseAreaPosOnClick();
- void updateMouseAreaPosOnResize();
- void noOnClickedWithPressAndHold();
- void onMousePressRejected();
- void pressedCanceledOnWindowDeactivate();
- void doubleClick();
- void clickTwice();
- void pressedOrdering();
- void preventStealing();
- void clickThrough();
- void testQtQuick11Attributes();
- void testQtQuick11Attributes_data();
- void hoverPosition();
- void hoverPropagation();
-
-private:
- QQuickView *createView();
-};
-
-void tst_QQuickMouseArea::initTestCase()
-{
-
-}
-
-void tst_QQuickMouseArea::cleanupTestCase()
-{
-
-}
-
-void tst_QQuickMouseArea::dragProperties()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragproperties.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootItem != 0);
- QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
- drag->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
- drag->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
-
- // axis
- QCOMPARE(drag->axis(), QQuickDrag::XandYAxis);
- QSignalSpy axisSpy(drag, SIGNAL(axisChanged()));
- drag->setAxis(QQuickDrag::XAxis);
- QCOMPARE(drag->axis(), QQuickDrag::XAxis);
- QCOMPARE(axisSpy.count(),1);
- drag->setAxis(QQuickDrag::XAxis);
- QCOMPARE(axisSpy.count(),1);
-
- // minimum and maximum properties
- QSignalSpy xminSpy(drag, SIGNAL(minimumXChanged()));
- QSignalSpy xmaxSpy(drag, SIGNAL(maximumXChanged()));
- QSignalSpy yminSpy(drag, SIGNAL(minimumYChanged()));
- QSignalSpy ymaxSpy(drag, SIGNAL(maximumYChanged()));
-
- QCOMPARE(drag->xmin(), 0.0);
- QCOMPARE(drag->xmax(), rootItem->width()-blackRect->width());
- QCOMPARE(drag->ymin(), 0.0);
- QCOMPARE(drag->ymax(), rootItem->height()-blackRect->height());
-
- drag->setXmin(10);
- drag->setXmax(10);
- drag->setYmin(10);
- drag->setYmax(10);
-
- QCOMPARE(drag->xmin(), 10.0);
- QCOMPARE(drag->xmax(), 10.0);
- QCOMPARE(drag->ymin(), 10.0);
- QCOMPARE(drag->ymax(), 10.0);
-
- QCOMPARE(xminSpy.count(),1);
- QCOMPARE(xmaxSpy.count(),1);
- QCOMPARE(yminSpy.count(),1);
- QCOMPARE(ymaxSpy.count(),1);
-
- drag->setXmin(10);
- drag->setXmax(10);
- drag->setYmin(10);
- drag->setYmax(10);
-
- QCOMPARE(xminSpy.count(),1);
- QCOMPARE(xmaxSpy.count(),1);
- QCOMPARE(yminSpy.count(),1);
- QCOMPARE(ymaxSpy.count(),1);
-
- // filterChildren
- QSignalSpy filterChildrenSpy(drag, SIGNAL(filterChildrenChanged()));
-
- drag->setFilterChildren(true);
-
- QVERIFY(drag->filterChildren());
- QCOMPARE(filterChildrenSpy.count(), 1);
-
- drag->setFilterChildren(true);
- QCOMPARE(filterChildrenSpy.count(), 1);
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::resetDrag()
-{
- QQuickView *canvas = createView();
-
- canvas->rootContext()->setContextProperty("haveTarget", QVariant(true));
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragreset.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootItem != 0);
- QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
- QVERIFY(drag->target() != 0);
- canvas->rootContext()->setContextProperty("haveTarget", QVariant(false));
- QCOMPARE(targetSpy.count(),1);
- QVERIFY(drag->target() == 0);
-
- delete canvas;
-}
-
-
-void tst_QQuickMouseArea::dragging()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragging.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWait(20);
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
- QVERIFY(blackRect == drag->target());
-
- QVERIFY(!drag->active());
-
-#ifdef OLDWAY
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-#else
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
-#endif
-
- QVERIFY(!drag->active());
- QCOMPARE(blackRect->x(), 50.0);
- QCOMPARE(blackRect->y(), 50.0);
-
- // First move event triggers drag, second is acted upon.
- // This is due to possibility of higher stacked area taking precedence.
-
- QTest::mouseMove(canvas, QPoint(111,111));
- QTest::qWait(50);
- QTest::mouseMove(canvas, QPoint(122,122));
- QTest::qWait(50);
-
- QVERIFY(drag->active());
- QCOMPARE(blackRect->x(), 72.0);
- QCOMPARE(blackRect->y(), 72.0);
-
-#ifdef OLDWAY
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-#else
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
- QTest::qWait(50);
-#endif
-
- QVERIFY(!drag->active());
- QCOMPARE(blackRect->x(), 72.0);
- QCOMPARE(blackRect->y(), 72.0);
-
- delete canvas;
-}
-
-QQuickView *tst_QQuickMouseArea::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setBaseSize(QSize(240,320));
-
- return canvas;
-}
-
-void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("updateMousePosOnClick.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QVERIFY(mouseRegion != 0);
-
- QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("ball");
- QVERIFY(rect != 0);
-
- QCOMPARE(mouseRegion->mouseX(), rect->x());
- QCOMPARE(mouseRegion->mouseY(), rect->y());
-
- QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &event);
-
- QCOMPARE(mouseRegion->mouseX(), 100.0);
- QCOMPARE(mouseRegion->mouseY(), 100.0);
-
- QCOMPARE(mouseRegion->mouseX(), rect->x());
- QCOMPARE(mouseRegion->mouseY(), rect->y());
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("updateMousePosOnResize.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QVERIFY(mouseRegion != 0);
-
- QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("brother");
- QVERIFY(rect != 0);
-
- QCOMPARE(mouseRegion->mouseX(), 0.0);
- QCOMPARE(mouseRegion->mouseY(), 0.0);
-
- QMouseEvent event(QEvent::MouseButtonPress, rect->pos().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &event);
-
- QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
- QVERIFY(mouseRegion->property("mouseMatchesPos").toBool());
-
- QCOMPARE(mouseRegion->property("x1").toReal(), 0.0);
- QCOMPARE(mouseRegion->property("y1").toReal(), 0.0);
-
- QCOMPARE(mouseRegion->property("x2").toReal(), rect->x());
- QCOMPARE(mouseRegion->property("y2").toReal(), rect->y());
-
- QCOMPARE(mouseRegion->mouseX(), rect->x());
- QCOMPARE(mouseRegion->mouseY(), rect->y());
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
-{
- {
- // We handle onPressAndHold, therefore no onClicked
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickandhold.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QVERIFY(!canvas->rootObject()->property("clicked").toBool());
- QVERIFY(!canvas->rootObject()->property("held").toBool());
-
- QTest::qWait(1000);
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QVERIFY(!canvas->rootObject()->property("clicked").toBool());
- QVERIFY(canvas->rootObject()->property("held").toBool());
-
- delete canvas;
- }
-
- {
- // We do not handle onPressAndHold, therefore we get onClicked
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("noclickandhold.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QVERIFY(!canvas->rootObject()->property("clicked").toBool());
-
- QTest::qWait(1000);
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QVERIFY(canvas->rootObject()->property("clicked").toBool());
-
- delete canvas;
- }
-}
-
-void tst_QQuickMouseArea::onMousePressRejected()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("rejectEvent.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
- QVERIFY(canvas->rootObject()->property("enabled").toBool());
-
- QVERIFY(!canvas->rootObject()->property("mr1_pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
- QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("mr2_pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
- QVERIFY(!canvas->rootObject()->property("mr2_canceled").toBool());
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QVERIFY(canvas->rootObject()->property("mr1_pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
- QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
- QVERIFY(canvas->rootObject()->property("mr2_pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
- QVERIFY(canvas->rootObject()->property("mr2_canceled").toBool());
-
- QTest::qWait(200);
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QVERIFY(canvas->rootObject()->property("mr1_released").toBool());
- QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
-
- delete canvas;
-}
-void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pressedCanceled.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
- QVERIFY(!canvas->rootObject()->property("pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("released").toBool());
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QVERIFY(canvas->rootObject()->property("pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("released").toBool());
-
- QTest::qWait(200);
-
- QEvent windowDeactivateEvent(QEvent::WindowDeactivate);
- QApplication::sendEvent(canvas, &windowDeactivateEvent);
- QVERIFY(!canvas->rootObject()->property("pressed").toBool());
- QVERIFY(canvas->rootObject()->property("canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("released").toBool());
-
- QTest::qWait(200);
-
- //press again
- QApplication::sendEvent(canvas, &pressEvent);
- QVERIFY(canvas->rootObject()->property("pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("canceled").toBool());
- QVERIFY(!canvas->rootObject()->property("released").toBool());
-
- QTest::qWait(200);
-
- //release
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
- QVERIFY(!canvas->rootObject()->property("pressed").toBool());
- QVERIFY(!canvas->rootObject()->property("canceled").toBool());
- QVERIFY(canvas->rootObject()->property("released").toBool());
-
- delete canvas;
-}
-void tst_QQuickMouseArea::doubleClick()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("doubleclick.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
-
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
-
- delete canvas;
-}
-
-// QTBUG-14832
-void tst_QQuickMouseArea::clickTwice()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("clicktwice.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
-
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QApplication::sendEvent(canvas, &pressEvent);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2);
- QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
- QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2);
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::pressedOrdering()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pressedOrdering.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base"));
-
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &pressEvent);
-
- QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
-
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QApplication::sendEvent(canvas, &releaseEvent);
-
- QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled"));
-
- QApplication::sendEvent(canvas, &pressEvent);
-
- QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::preventStealing()
-{
- QQuickView *canvas = createView();
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("preventstealing.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
- QVERIFY(flickable != 0);
-
- QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mousearea");
- QVERIFY(mouseArea != 0);
-
- QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
-
- // Without preventStealing, mouse movement over MouseArea would
- // cause the Flickable to steal mouse and trigger content movement.
-
- QTest::mouseMove(canvas,QPoint(69,69));
- QTest::mouseMove(canvas,QPoint(58,58));
- QTest::mouseMove(canvas,QPoint(47,47));
-
- // We should have received all three move events
- QCOMPARE(mousePositionSpy.count(), 3);
- QVERIFY(mouseArea->pressed());
-
- // Flickable content should not have moved.
- QCOMPARE(flickable->contentX(), 0.);
- QCOMPARE(flickable->contentY(), 0.);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(47, 47));
-
- // Now allow stealing and confirm Flickable does its thing.
- canvas->rootObject()->setProperty("stealing", false);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
-
- // Without preventStealing, mouse movement over MouseArea would
- // cause the Flickable to steal mouse and trigger content movement.
-
- QTest::mouseMove(canvas,QPoint(69,69));
- QTest::mouseMove(canvas,QPoint(58,58));
- QTest::mouseMove(canvas,QPoint(47,47));
-
- // We should only have received the first move event
- QCOMPARE(mousePositionSpy.count(), 4);
- // Our press should be taken away
- QVERIFY(!mouseArea->pressed());
-
- // Flickable content should have moved.
-
- QCOMPARE(flickable->contentX(), 11.);
- QCOMPARE(flickable->contentY(), 11.);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 50));
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::clickThrough()
-{
- //With no handlers defined click, doubleClick and PressAndHold should propagate to those with handlers
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickThrough.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
-
- QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
-
- QTest::qWait(800); // to avoid generating a double click.
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(1000);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
-
- QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
- QTRY_COMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
-
- QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
- QTRY_COMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
-
- delete canvas;
-
- //With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
- canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickThrough2.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
-
- QTest::qWait(800); // to avoid generating a double click.
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(1000);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
-
- QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
-
- canvas->rootObject()->setProperty("letThrough", QVariant(true));
-
- QTest::qWait(800); // to avoid generating a double click.
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
-
- QTest::qWait(800); // to avoid generating a double click.
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(1000);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
-
- QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
- QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
-
- canvas->rootObject()->setProperty("noPropagation", QVariant(true));
-
- QTest::qWait(800); // to avoid generating a double click.
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
-
- QTest::qWait(800); // to avoid generating a double click.
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(1000);
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
- QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
- QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
- QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::testQtQuick11Attributes()
-{
- QFETCH(QString, code);
- QFETCH(QString, warning);
- QFETCH(QString, error);
-
- QDeclarativeEngine engine;
- QObject *obj;
-
- QDeclarativeComponent valid(&engine);
- valid.setData("import QtQuick 1.1; MouseArea { " + code.toUtf8() + " }", QUrl(""));
- obj = valid.create();
- QVERIFY(obj);
- QVERIFY(valid.errorString().isEmpty());
- delete obj;
-
- QDeclarativeComponent invalid(&engine);
- invalid.setData("import QtQuick 1.0; MouseArea { " + code.toUtf8() + " }", QUrl(""));
- QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
- obj = invalid.create();
- QCOMPARE(invalid.errorString(), error);
- delete obj;
-}
-
-void tst_QQuickMouseArea::testQtQuick11Attributes_data()
-{
- QTest::addColumn<QString>("code");
- QTest::addColumn<QString>("warning");
- QTest::addColumn<QString>("error");
-
- QTest::newRow("preventStealing") << "preventStealing: true"
- << "QDeclarativeComponent: Component is not ready"
- << ":1 \"MouseArea.preventStealing\" is not available in QtQuick 1.0.\n";
-}
-
-void tst_QQuickMouseArea::hoverPosition()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("hoverPosition.qml")));
-
- QQuickItem *root = canvas->rootObject();
- QVERIFY(root != 0);
-
- QCOMPARE(root->property("mouseX").toReal(), qreal(0));
- QCOMPARE(root->property("mouseY").toReal(), qreal(0));
-
- QTest::mouseMove(canvas,QPoint(10,32));
-
-
- QCOMPARE(root->property("mouseX").toReal(), qreal(10));
- QCOMPARE(root->property("mouseY").toReal(), qreal(32));
-
- delete canvas;
-}
-
-void tst_QQuickMouseArea::hoverPropagation()
-{
- //QTBUG-18175, to behave like GV did.
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("hoverPropagation.qml")));
-
- QQuickItem *root = canvas->rootObject();
- QVERIFY(root != 0);
-
- QCOMPARE(root->property("point1").toBool(), false);
- QCOMPARE(root->property("point2").toBool(), false);
-
- QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
- QApplication::sendEvent(canvas, &moveEvent);
-
- QCOMPARE(root->property("point1").toBool(), true);
- QCOMPARE(root->property("point2").toBool(), false);
-
- QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
- QApplication::sendEvent(canvas, &moveEvent2);
- QCOMPARE(root->property("point1").toBool(), false);
- QCOMPARE(root->property("point2").toBool(), true);
-
- delete canvas;
-}
-
-QTEST_MAIN(tst_QQuickMouseArea)
-
-#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/qquickmultipointtoucharea.pro b/tests/auto/declarative/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
deleted file mode 100644
index 8be4b1f1fd..0000000000
--- a/tests/auto/declarative/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-TARGET = tst_qquickmultipointtoucharea
-CONFIG += testcase
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickmultipointtoucharea.cpp
-
-importFiles.files = data
-importFiles.path = .
-DEPLOYMENT += importFiles
-
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/declarative/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
deleted file mode 100644
index 9acef50645..0000000000
--- a/tests/auto/declarative/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ /dev/null
@@ -1,586 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <private/qquickmultipointtoucharea_p.h>
-#include <private/qquickflickable_p.h>
-#include <QtDeclarative/qquickview.h>
-
-class tst_QQuickMultiPointTouchArea: public QObject
-{
- Q_OBJECT
-private slots:
- void initTestCase() {}
- void cleanupTestCase() {}
-
- void properties();
- void signalTest();
- void nonOverlapping();
- void nested();
- void inFlickable();
-
-private:
- QQuickView *createAndShowView(const QString &file);
-};
-
-void tst_QQuickMultiPointTouchArea::properties()
-{
- QQuickView *canvas = createAndShowView("properties.qml");
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(canvas->rootObject());
- QVERIFY(area != 0);
-
- QCOMPARE(area->minimumTouchPoints(), 2);
- QCOMPARE(area->maximumTouchPoints(), 4);
-
- QDeclarativeListReference ref(area, "touchPoints");
- QCOMPARE(ref.count(), 4);
-
- delete canvas;
-}
-
-void tst_QQuickMultiPointTouchArea::signalTest()
-{
- QQuickView *canvas = createAndShowView("signalTest.qml");
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(canvas->rootObject());
- QVERIFY(area != 0);
-
- QPoint p1(20,100);
- QPoint p2(40,100);
- QPoint p3(60,100);
- QPoint p4(80,100);
- QPoint p5(100,100);
-
- QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
-
- sequence.press(0, p1).press(1, p2).commit();
-
- QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
- QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
- QCOMPARE(area->property("touchCount").toInt(), 2);
- QMetaObject::invokeMethod(area, "clearCounts");
-
- sequence.stationary(0).stationary(1).press(2, p3).commit();
-
- QCOMPARE(area->property("touchPointPressCount").toInt(), 1);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
- QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
- QCOMPARE(area->property("touchCount").toInt(), 3);
- QMetaObject::invokeMethod(area, "clearCounts");
-
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- sequence.move(0, p1).move(1, p2).stationary(2).commit();
-
- QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
- QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
- QCOMPARE(area->property("touchCount").toInt(), 3);
- QMetaObject::invokeMethod(area, "clearCounts");
-
- p3 += QPoint(10,10);
- sequence.release(0, p1).release(1, p2)
- .move(2, p3).press(3, p4).press(4, p5).commit();
-
- QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 1);
- QCOMPARE(area->property("touchPointReleaseCount").toInt(), 2);
- QCOMPARE(area->property("touchCount").toInt(), 3);
- QMetaObject::invokeMethod(area, "clearCounts");
-
- sequence.release(2, p3).release(3, p4).release(4, p5).commit();
-
- QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
- QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
- QCOMPARE(area->property("touchPointReleaseCount").toInt(), 3);
- QCOMPARE(area->property("touchCount").toInt(), 0);
- QMetaObject::invokeMethod(area, "clearCounts");
-
- delete canvas;
-}
-
-void tst_QQuickMultiPointTouchArea::nonOverlapping()
-{
- QQuickView *canvas = createAndShowView("nonOverlapping.qml");
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point11");
- QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point12");
- QQuickTouchPoint *point21 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point21");
- QQuickTouchPoint *point22 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point22");
- QQuickTouchPoint *point23 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point23");
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QPoint p1(20,100);
- QPoint p2(40,100);
- QPoint p3(60,180);
- QPoint p4(80,180);
- QPoint p5(100,180);
-
- QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
-
- sequence.press(0, p1).commit();
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- sequence.stationary(0).press(1, p2).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(100));
- QCOMPARE(point12->x(), qreal(40)); QCOMPARE(point12->y(), qreal(100));
-
- p1 += QPoint(0,10);
- p2 += QPoint(5,0);
- sequence.move(0, p1).move(1, p2).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
-
- sequence.stationary(0).stationary(1).press(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- sequence.stationary(0).stationary(1).stationary(2).press(3, p4).press(4, p5).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
- QCOMPARE(point21->x(), qreal(60)); QCOMPARE(point21->y(), qreal(20));
- QCOMPARE(point22->x(), qreal(80)); QCOMPARE(point22->y(), qreal(20));
- QCOMPARE(point23->x(), qreal(100)); QCOMPARE(point23->y(), qreal(20));
-
- p1 += QPoint(4,10);
- p2 += QPoint(17,17);
- p3 += QPoint(3,0);
- p4 += QPoint(1,-1);
- p5 += QPoint(-7,10);
- sequence.move(0, p1).move(1, p2).move(2, p3).move(3, p4).move(4, p5).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- QCOMPARE(point11->x(), qreal(24)); QCOMPARE(point11->y(), qreal(120));
- QCOMPARE(point12->x(), qreal(62)); QCOMPARE(point12->y(), qreal(117));
- QCOMPARE(point21->x(), qreal(63)); QCOMPARE(point21->y(), qreal(20));
- QCOMPARE(point22->x(), qreal(81)); QCOMPARE(point22->y(), qreal(19));
- QCOMPARE(point23->x(), qreal(93)); QCOMPARE(point23->y(), qreal(30));
-
- sequence.release(0, p1).release(1, p2).release(2, p3).release(3, p4).release(4, p5).commit();
-
- //points remain valid immediately after release
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- delete canvas;
-}
-
-void tst_QQuickMultiPointTouchArea::nested()
-{
- QQuickView *canvas = createAndShowView("nested.qml");
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point11");
- QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point12");
- QQuickTouchPoint *point21 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point21");
- QQuickTouchPoint *point22 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point22");
- QQuickTouchPoint *point23 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point23");
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QPoint p1(20,100);
- QPoint p2(40,100);
- QPoint p3(60,180);
-
- QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
-
- sequence.press(0, p1).commit();
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- sequence.stationary(0).press(1, p2).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(100));
- QCOMPARE(point12->x(), qreal(40)); QCOMPARE(point12->y(), qreal(100));
-
- p1 += QPoint(0,10);
- p2 += QPoint(5,0);
- sequence.move(0, p1).move(1, p2).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
-
- sequence.stationary(0).stationary(1).press(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- //point11 should be same as point21, point12 same as point22
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
- QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
- QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
- QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
-
- sequence.stationary(0).stationary(1).stationary(2).press(3, QPoint(80,180)).press(4, QPoint(100,180)).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- //new touch points should be ignored (have no impact on our existing touch points)
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
- QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
- QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
- QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
-
- sequence.stationary(0).stationary(1).stationary(2).release(3, QPoint(80,180)).release(4, QPoint(100,180)).commit();
-
- p1 += QPoint(4,10);
- p2 += QPoint(17,17);
- p3 += QPoint(3,0);
- sequence.move(0, p1).move(1, p2).move(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
- QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
- QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
- QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
- QCOMPARE(point23->x(), qreal(63)); QCOMPARE(point23->y(), qreal(180));
-
- p1 += QPoint(4,10);
- p2 += QPoint(17,17);
- p3 += QPoint(3,0);
- sequence.move(0, p1).move(1, p2).move(2, p3).commit();
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- //first two remain the same (touches now grabbed by inner touch area)
- QCOMPARE(point11->x(), qreal(24)); QCOMPARE(point11->y(), qreal(120));
- QCOMPARE(point12->x(), qreal(62)); QCOMPARE(point12->y(), qreal(117));
- QCOMPARE(point21->x(), qreal(28)); QCOMPARE(point21->y(), qreal(130));
- QCOMPARE(point22->x(), qreal(79)); QCOMPARE(point22->y(), qreal(134));
- QCOMPARE(point23->x(), qreal(66)); QCOMPARE(point23->y(), qreal(180));
-
- sequence.release(0, p1).release(1, p2).release(2, p3).commit();
-
- sequence.press(0, p1).commit();
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
- QCOMPARE(point21->isValid(), false);
- QCOMPARE(point22->isValid(), false);
- QCOMPARE(point23->isValid(), false);
-
- sequence.release(0, p1).commit();
-
- //test with grabbing turned off
- canvas->rootObject()->setProperty("grabInnerArea", false);
-
- sequence.press(0, p1).press(1, p2).press(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- p1 -= QPoint(4,10);
- p2 -= QPoint(17,17);
- p3 -= QPoint(3,0);
- sequence.move(0, p1).move(1, p2).move(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
- QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
- QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
- QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
- QCOMPARE(point23->x(), qreal(63)); QCOMPARE(point23->y(), qreal(180));
-
- p1 -= QPoint(4,10);
- p2 -= QPoint(17,17);
- p3 -= QPoint(3,0);
- sequence.move(0, p1).move(1, p2).move(2, p3).commit();
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
- QCOMPARE(point21->isValid(), true);
- QCOMPARE(point22->isValid(), true);
- QCOMPARE(point23->isValid(), true);
-
- //all change (touches not grabbed by inner touch area)
- QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
- QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
- QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
- QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
- QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
-
- sequence.release(0, p1).release(1, p2).release(2, p3).commit();
-
- delete canvas;
-}
-
-void tst_QQuickMultiPointTouchArea::inFlickable()
-{
- QQuickView *canvas = createAndShowView("inFlickable.qml");
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(canvas->rootObject());
- QVERIFY(flickable != 0);
-
- QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point1");
- QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point2");
-
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
-
- QPoint p1(20,100);
- QPoint p2(40,100);
-
- //moving one point vertically
- QTest::touchEvent(canvas).press(0, p1);
- QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
-
- p1 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1);
- QTest::mouseMove(canvas, p1);
-
- QVERIFY(flickable->contentY() < 0);
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
-
- QTest::touchEvent(canvas).release(0, p1);
- QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
- QTest::qWait(50);
-
- QTRY_VERIFY(!flickable->isMoving());
-
- //moving two points vertically
- p1 = QPoint(20,100);
- QTest::touchEvent(canvas).press(0, p1).press(1, p2);
- QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- QVERIFY(flickable->contentY() < 0);
- QCOMPARE(point11->isValid(), false);
- QCOMPARE(point12->isValid(), false);
-
- QTest::touchEvent(canvas).release(0, p1).release(1, p2);
- QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
- QTest::qWait(50);
-
- QTRY_VERIFY(!flickable->isMoving());
-
- //moving two points horizontally, then one point vertically
- p1 = QPoint(20,100);
- p2 = QPoint(40,100);
- QTest::touchEvent(canvas).press(0, p1).press(1, p2);
- QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
-
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
-
- p1 += QPoint(15,0); p2 += QPoint(15,0);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(15,0); p2 += QPoint(15,0);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(15,0); p2 += QPoint(15,0);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(15,0); p2 += QPoint(15,0);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- p1 += QPoint(0,15); p2 += QPoint(0,15);
- QTest::touchEvent(canvas).move(0, p1).move(1, p2);
- QTest::mouseMove(canvas, p1);
-
- QVERIFY(flickable->contentY() == 0);
- QCOMPARE(point11->isValid(), true);
- QCOMPARE(point12->isValid(), true);
-
- QTest::touchEvent(canvas).release(0, p1).release(1, p2);
- QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
- QTest::qWait(50);
-
- delete canvas;
-}
-
-QQuickView *tst_QQuickMultiPointTouchArea::createAndShowView(const QString &file)
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QLatin1String("/data/") + file));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
-
- return canvas;
-}
-
-QTEST_MAIN(tst_QQuickMultiPointTouchArea)
-
-#include "tst_qquickmultipointtoucharea.moc"
diff --git a/tests/auto/declarative/qquickpathview/qquickpathview.pro b/tests/auto/declarative/qquickpathview/qquickpathview.pro
deleted file mode 100644
index d03cd4eec7..0000000000
--- a/tests/auto/declarative/qquickpathview/qquickpathview.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickpathview
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickpathview.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private widgets testlib
diff --git a/tests/auto/declarative/qquickpathview/tst_qquickpathview.cpp b/tests/auto/declarative/qquickpathview/tst_qquickpathview.cpp
deleted file mode 100644
index b0efc5838d..0000000000
--- a/tests/auto/declarative/qquickpathview/tst_qquickpathview.cpp
+++ /dev/null
@@ -1,1629 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-#include <QtDeclarative/private/qquickpathview_p.h>
-#include <QtDeclarative/private/qdeclarativepath_p.h>
-#include <QtDeclarative/private/qquicktext_p.h>
-#include <QtDeclarative/private/qquickrectangle_p.h>
-#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
-#include <QtDeclarative/private/qdeclarativevaluetype_p.h>
-#include <QAbstractListModel>
-#include <QStringListModel>
-#include <QStandardItemModel>
-#include <QFile>
-
-#include "../shared/util.h"
-
-static void initStandardTreeModel(QStandardItemModel *model)
-{
- QStandardItem *item;
- item = new QStandardItem(QLatin1String("Row 1 Item"));
- model->insertRow(0, item);
-
- item = new QStandardItem(QLatin1String("Row 2 Item"));
- item->setCheckable(true);
- model->insertRow(1, item);
-
- QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
- item->setChild(0, childItem);
-
- item = new QStandardItem(QLatin1String("Row 3 Item"));
- item->setIcon(QIcon());
- model->insertRow(2, item);
-}
-
-
-class tst_QQuickPathView : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickPathView();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void initValues();
- void items();
- void dataModel();
- void pathview2();
- void pathview3();
- void insertModel_data();
- void insertModel();
- void removeModel_data();
- void removeModel();
- void moveModel_data();
- void moveModel();
- void path();
- void pathMoved();
- void setCurrentIndex();
- void resetModel();
- void propertyChanges();
- void pathChanges();
- void componentChanges();
- void modelChanges();
- void pathUpdateOnStartChanged();
- void package();
- void emptyModel();
- void closed();
- void pathUpdate();
- void visualDataModel();
- void undefinedPath();
- void mouseDrag();
- void treeModel();
- void changePreferredHighlight();
- void missingPercent();
- void creationContext();
- void currentOffsetOnInsertion();
- void asynchronous();
-
-private:
- QQuickView *createView();
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &objectName, int index=-1);
- template<typename T>
- QList<T*> findItems(QQuickItem *parent, const QString &objectName);
-};
-
-void tst_QQuickPathView::initTestCase()
-{
-}
-
-void tst_QQuickPathView::cleanupTestCase()
-{
-
-}
-
-class TestObject : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool error READ error WRITE setError)
- Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
- Q_PROPERTY(int pathItemCount READ pathItemCount NOTIFY pathItemCountChanged)
-
-public:
- TestObject() : QObject(), mError(true), mUseModel(true), mPathItemCount(-1) {}
-
- bool error() const { return mError; }
- void setError(bool err) { mError = err; }
-
- bool useModel() const { return mUseModel; }
- void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
-
- int pathItemCount() const { return mPathItemCount; }
- void setPathItemCount(int count) { mPathItemCount = count; emit pathItemCountChanged(); }
-
-signals:
- void useModelChanged();
- void pathItemCountChanged();
-
-private:
- bool mError;
- bool mUseModel;
- int mPathItemCount;
-};
-
-class TestModel : public QAbstractListModel
-{
-public:
- enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
-
- TestModel(QObject *parent=0) : QAbstractListModel(parent) {
- QHash<int, QByteArray> roles;
- roles[Name] = "name";
- roles[Number] = "number";
- setRoleNames(roles);
- }
-
- int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
- QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
- QVariant rv;
- if (role == Name)
- rv = list.at(index.row()).first;
- else if (role == Number)
- rv = list.at(index.row()).second;
-
- return rv;
- }
-
- int count() const { return rowCount(); }
- QString name(int index) const { return list.at(index).first; }
- QString number(int index) const { return list.at(index).second; }
-
- void addItem(const QString &name, const QString &number) {
- beginInsertRows(QModelIndex(), list.count(), list.count());
- list.append(QPair<QString,QString>(name, number));
- endInsertRows();
- }
-
- void insertItem(int index, const QString &name, const QString &number) {
- beginInsertRows(QModelIndex(), index, index);
- list.insert(index, QPair<QString,QString>(name, number));
- endInsertRows();
- }
-
- void insertItems(int index, const QList<QPair<QString, QString> > &items) {
- beginInsertRows(QModelIndex(), index, index+items.count()-1);
- for (int i=0; i<items.count(); i++)
- list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
- endInsertRows();
- }
-
- void removeItem(int index) {
- beginRemoveRows(QModelIndex(), index, index);
- list.removeAt(index);
- endRemoveRows();
- }
-
- void removeItems(int index, int count) {
- emit beginRemoveRows(QModelIndex(), index, index+count-1);
- while (count--)
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void moveItem(int from, int to) {
- beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
- list.move(from, to);
- endMoveRows();
- }
-
- void moveItems(int from, int to, int count) {
- beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
- move(from, to, count);
- endMoveRows();
- }
-
- void modifyItem(int idx, const QString &name, const QString &number) {
- list[idx] = QPair<QString,QString>(name, number);
- emit dataChanged(index(idx,0), index(idx,0));
- }
-
- void move(int from, int to, int n)
- {
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
- if (n == 1) {
- list.move(from, to);
- } else {
- QList<QPair<QString,QString> > replaced;
- int i=0;
- QList<QPair<QString,QString> >::ConstIterator it=list.begin(); it += from+n;
- for (; i<to-from; ++i,++it)
- replaced.append(*it);
- i=0;
- it=list.begin(); it += from;
- for (; i<n; ++i,++it)
- replaced.append(*it);
- QList<QPair<QString,QString> >::ConstIterator f=replaced.begin();
- QList<QPair<QString,QString> >::Iterator t=list.begin(); t += from;
- for (; f != replaced.end(); ++f, ++t)
- *t = *f;
- }
- }
-
-private:
- QList<QPair<QString,QString> > list;
-};
-
-
-tst_QQuickPathView::tst_QQuickPathView()
-{
-}
-
-void tst_QQuickPathView::initValues()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview1.qml")));
- QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
-
- QVERIFY(obj != 0);
- QVERIFY(obj->path() == 0);
- QVERIFY(obj->delegate() == 0);
- QCOMPARE(obj->model(), QVariant());
- QCOMPARE(obj->currentIndex(), 0);
- QCOMPARE(obj->offset(), 0.);
- QCOMPARE(obj->preferredHighlightBegin(), 0.);
- QCOMPARE(obj->dragMargin(), 0.);
- QCOMPARE(obj->count(), 0);
- QCOMPARE(obj->pathItemCount(), -1);
-
- delete obj;
-}
-
-void tst_QQuickPathView::items()
-{
- QQuickView *canvas = createView();
-
- TestModel model;
- model.addItem("Fred", "12345");
- model.addItem("John", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- QCOMPARE(pathview->count(), model.count());
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
- QCOMPARE(pathview->childItems().count(), model.count()+1); // assumes all are visible, including highlight
-
- for (int i = 0; i < model.count(); ++i) {
- QQuickText *name = findItem<QQuickText>(pathview, "textName", i);
- QVERIFY(name != 0);
- QCOMPARE(name->text(), model.name(i));
- QQuickText *number = findItem<QQuickText>(pathview, "textNumber", i);
- QVERIFY(number != 0);
- QCOMPARE(number->text(), model.number(i));
- }
-
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
-
- QVERIFY(pathview->highlightItem());
- QPointF start = path->pointAt(0.0);
- QPointF offset;
- offset.setX(pathview->highlightItem()->width()/2);
- offset.setY(pathview->highlightItem()->height()/2);
- QCOMPARE(pathview->highlightItem()->pos() + offset, start);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::pathview2()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview2.qml")));
- QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
-
- QVERIFY(obj != 0);
- QVERIFY(obj->path() != 0);
- QVERIFY(obj->delegate() != 0);
- QVERIFY(obj->model() != QVariant());
- QCOMPARE(obj->currentIndex(), 0);
- QCOMPARE(obj->offset(), 0.);
- QCOMPARE(obj->preferredHighlightBegin(), 0.);
- QCOMPARE(obj->dragMargin(), 0.);
- QCOMPARE(obj->count(), 8);
- QCOMPARE(obj->pathItemCount(), 10);
-
- delete obj;
-}
-
-void tst_QQuickPathView::pathview3()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview3.qml")));
- QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
-
- QVERIFY(obj != 0);
- QVERIFY(obj->path() != 0);
- QVERIFY(obj->delegate() != 0);
- QVERIFY(obj->model() != QVariant());
- QCOMPARE(obj->currentIndex(), 0);
- QCOMPARE(obj->offset(), 1.0);
- QCOMPARE(obj->preferredHighlightBegin(), 0.5);
- QCOMPARE(obj->dragMargin(), 24.);
- QCOMPARE(obj->count(), 8);
- QCOMPARE(obj->pathItemCount(), 4);
-
- delete obj;
-}
-
-void tst_QQuickPathView::insertModel_data()
-{
- QTest::addColumn<int>("mode");
- QTest::addColumn<int>("idx");
- QTest::addColumn<int>("count");
- QTest::addColumn<qreal>("offset");
-
- // We have 8 items, with currentIndex == 4
- QTest::newRow("insert after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 5.;
- QTest::newRow("insert before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4.;
- QTest::newRow("insert multiple after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 6.;
- QTest::newRow("insert multiple before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4.;
- QTest::newRow("insert at end")
- << int(QQuickPathView::StrictlyEnforceRange) << 8 << 1 << 5.;
- QTest::newRow("insert at beginning")
- << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4.;
- QTest::newRow("insert at current")
- << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 4.;
-
- QTest::newRow("no range - insert after current")
- << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 5.;
- QTest::newRow("no range - insert before current")
- << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4.;
- QTest::newRow("no range - insert multiple after current")
- << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 6.;
- QTest::newRow("no range - insert multiple before current")
- << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4.;
- QTest::newRow("no range - insert at end")
- << int(QQuickPathView::NoHighlightRange) << 8 << 1 << 5.;
- QTest::newRow("no range - insert at beginning")
- << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4.;
- QTest::newRow("no range - insert at current")
- << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4.;
-}
-
-void tst_QQuickPathView::insertModel()
-{
- QFETCH(int, mode);
- QFETCH(int, idx);
- QFETCH(int, count);
- QFETCH(qreal, offset);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Ben", "12345");
- model.addItem("Bohn", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
- model.addItem("Jinny", "679");
- model.addItem("Milly", "73378");
- model.addItem("Jimmy", "3535");
- model.addItem("Barb", "9039");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
-
- pathview->setCurrentIndex(4);
- if (mode == QQuickPathView::StrictlyEnforceRange)
- QTRY_COMPARE(pathview->offset(), 4.0);
- else
- pathview->setOffset(4);
-
- QList<QPair<QString, QString> > items;
- for (int i = 0; i < count; ++i)
- items.append(qMakePair(QString("New"), QString::number(i)));
-
- model.insertItems(idx, items);
- QTRY_COMPARE(pathview->offset(), offset);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::removeModel_data()
-{
- QTest::addColumn<int>("mode");
- QTest::addColumn<int>("idx");
- QTest::addColumn<int>("count");
- QTest::addColumn<qreal>("offset");
-
- // We have 8 items, with currentIndex == 4
- QTest::newRow("remove after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 3.;
- QTest::newRow("remove before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4.;
- QTest::newRow("remove multiple after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 2.;
- QTest::newRow("remove multiple before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4.;
- QTest::newRow("remove last")
- << int(QQuickPathView::StrictlyEnforceRange) << 7 << 1 << 3.;
- QTest::newRow("remove first")
- << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4.;
- QTest::newRow("remove current")
- << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 3.;
-
- QTest::newRow("no range - remove after current")
- << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 3.;
- QTest::newRow("no range - remove before current")
- << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4.;
- QTest::newRow("no range - remove multiple after current")
- << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 2.;
- QTest::newRow("no range - remove multiple before current")
- << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4.;
- QTest::newRow("no range - remove last")
- << int(QQuickPathView::NoHighlightRange) << 7 << 1 << 3.;
- QTest::newRow("no range - remove first")
- << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4.;
- QTest::newRow("no range - remove current offset")
- << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4.;
-}
-
-void tst_QQuickPathView::removeModel()
-{
- QFETCH(int, mode);
- QFETCH(int, idx);
- QFETCH(int, count);
- QFETCH(qreal, offset);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Ben", "12345");
- model.addItem("Bohn", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
- model.addItem("Jinny", "679");
- model.addItem("Milly", "73378");
- model.addItem("Jimmy", "3535");
- model.addItem("Barb", "9039");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
-
- pathview->setCurrentIndex(4);
- if (mode == QQuickPathView::StrictlyEnforceRange)
- QTRY_COMPARE(pathview->offset(), 4.0);
- else
- pathview->setOffset(4);
-
- model.removeItems(idx, count);
- QTRY_COMPARE(pathview->offset(), offset);
-
- delete canvas;
-}
-
-
-void tst_QQuickPathView::moveModel_data()
-{
- QTest::addColumn<int>("mode");
- QTest::addColumn<int>("from");
- QTest::addColumn<int>("to");
- QTest::addColumn<int>("count");
- QTest::addColumn<qreal>("offset");
-
- // We have 8 items, with currentIndex == 4
- QTest::newRow("move after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 1 << 4.;
- QTest::newRow("move before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 2 << 3 << 1 << 4.;
- QTest::newRow("move before current to after")
- << int(QQuickPathView::StrictlyEnforceRange) << 2 << 6 << 1 << 5.;
- QTest::newRow("move multiple after current")
- << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 2 << 4.;
- QTest::newRow("move multiple before current")
- << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 2 << 4.;
- QTest::newRow("move before current to end")
- << int(QQuickPathView::StrictlyEnforceRange) << 2 << 7 << 1 << 5.;
- QTest::newRow("move last to beginning")
- << int(QQuickPathView::StrictlyEnforceRange) << 7 << 0 << 1 << 3.;
- QTest::newRow("move current")
- << int(QQuickPathView::StrictlyEnforceRange) << 4 << 6 << 1 << 2.;
-
- QTest::newRow("no range - move after current")
- << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 1 << 4.;
- QTest::newRow("no range - move before current")
- << int(QQuickPathView::NoHighlightRange) << 2 << 3 << 1 << 4.;
- QTest::newRow("no range - move before current to after")
- << int(QQuickPathView::NoHighlightRange) << 2 << 6 << 1 << 5.;
- QTest::newRow("no range - move multiple after current")
- << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 2 << 4.;
- QTest::newRow("no range - move multiple before current")
- << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 2 << 4.;
- QTest::newRow("no range - move before current to end")
- << int(QQuickPathView::NoHighlightRange) << 2 << 7 << 1 << 5.;
- QTest::newRow("no range - move last to beginning")
- << int(QQuickPathView::NoHighlightRange) << 7 << 0 << 1 << 3.;
- QTest::newRow("no range - move current")
- << int(QQuickPathView::NoHighlightRange) << 4 << 6 << 1 << 4.;
- QTest::newRow("no range - move multiple incl. current")
- << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 5 << 4.;
-}
-
-void tst_QQuickPathView::moveModel()
-{
- QFETCH(int, mode);
- QFETCH(int, from);
- QFETCH(int, to);
- QFETCH(int, count);
- QFETCH(qreal, offset);
-
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Ben", "12345");
- model.addItem("Bohn", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
- model.addItem("Jinny", "679");
- model.addItem("Milly", "73378");
- model.addItem("Jimmy", "3535");
- model.addItem("Barb", "9039");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
-
- pathview->setCurrentIndex(4);
- if (mode == QQuickPathView::StrictlyEnforceRange)
- QTRY_COMPARE(pathview->offset(), 4.0);
- else
- pathview->setOffset(4);
-
- model.moveItems(from, to, count);
- QTRY_COMPARE(pathview->offset(), offset);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::path()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathtest.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
-
- QVERIFY(obj != 0);
- QCOMPARE(obj->startX(), 120.);
- QCOMPARE(obj->startY(), 100.);
- QVERIFY(obj->path() != QPainterPath());
-
- QDeclarativeListReference list(obj, "pathElements");
- QCOMPARE(list.count(), 5);
-
- QDeclarativePathAttribute* attr = qobject_cast<QDeclarativePathAttribute*>(list.at(0));
- QVERIFY(attr != 0);
- QCOMPARE(attr->name(), QString("scale"));
- QCOMPARE(attr->value(), 1.0);
-
- QDeclarativePathQuad* quad = qobject_cast<QDeclarativePathQuad*>(list.at(1));
- QVERIFY(quad != 0);
- QCOMPARE(quad->x(), 120.);
- QCOMPARE(quad->y(), 25.);
- QCOMPARE(quad->controlX(), 260.);
- QCOMPARE(quad->controlY(), 75.);
-
- QDeclarativePathPercent* perc = qobject_cast<QDeclarativePathPercent*>(list.at(2));
- QVERIFY(perc != 0);
- QCOMPARE(perc->value(), 0.3);
-
- QDeclarativePathLine* line = qobject_cast<QDeclarativePathLine*>(list.at(3));
- QVERIFY(line != 0);
- QCOMPARE(line->x(), 120.);
- QCOMPARE(line->y(), 100.);
-
- QDeclarativePathCubic* cubic = qobject_cast<QDeclarativePathCubic*>(list.at(4));
- QVERIFY(cubic != 0);
- QCOMPARE(cubic->x(), 180.);
- QCOMPARE(cubic->y(), 0.);
- QCOMPARE(cubic->control1X(), -10.);
- QCOMPARE(cubic->control1Y(), 90.);
- QCOMPARE(cubic->control2X(), 210.);
- QCOMPARE(cubic->control2Y(), 90.);
-
- delete obj;
-}
-
-void tst_QQuickPathView::dataModel()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- TestModel model;
- model.addItem("red", "1");
- model.addItem("green", "2");
- model.addItem("blue", "3");
- model.addItem("purple", "4");
- model.addItem("gray", "5");
- model.addItem("brown", "6");
- model.addItem("yellow", "7");
- model.addItem("thistle", "8");
- model.addItem("cyan", "9");
- model.addItem("peachpuff", "10");
- model.addItem("powderblue", "11");
- model.addItem("gold", "12");
- model.addItem("sandybrown", "13");
-
- ctxt->setContextProperty("testData", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("datamodel.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
- QVERIFY(pathview != 0);
-
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
-
- QQuickItem *item = findItem<QQuickItem>(pathview, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->x(), 110.0);
- QCOMPARE(item->y(), 10.0);
-
- model.insertItem(4, "orange", "10");
- QTest::qWait(100);
-
- QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
- QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 14);
-
- QVERIFY(pathview->currentIndex() == 0);
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
-
- QQuickText *text = findItem<QQuickText>(pathview, "myText", 4);
- QVERIFY(text);
- QCOMPARE(text->text(), model.name(4));
-
- model.removeItem(2);
- QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
- text = findItem<QQuickText>(pathview, "myText", 2);
- QVERIFY(text);
- QCOMPARE(text->text(), model.name(2));
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
-
- testObject->setPathItemCount(5);
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
-
- QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
-
- QQuickRectangle *testItem = findItem<QQuickRectangle>(pathview, "wrapper", 4);
- QVERIFY(testItem != 0);
- testItem = findItem<QQuickRectangle>(pathview, "wrapper", 5);
- QVERIFY(testItem == 0);
-
- pathview->setCurrentIndex(1);
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
- QTest::qWait(100);
-
- model.insertItem(2, "pink", "2");
- QTest::qWait(100);
-
- QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
- QVERIFY(pathview->currentIndex() == 1);
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
-
- text = findItem<QQuickText>(pathview, "myText", 2);
- QVERIFY(text);
- QCOMPARE(text->text(), model.name(2));
-
- model.removeItem(3);
- QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
- text = findItem<QQuickText>(pathview, "myText", 3);
- QVERIFY(text);
- QCOMPARE(text->text(), model.name(3));
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
-
- model.moveItem(3, 5);
- QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
- QList<QQuickItem*> items = findItems<QQuickItem>(pathview, "wrapper");
- foreach (QQuickItem *item, items) {
- QVERIFY(item->property("onPath").toBool());
- }
- QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
-
- // QTBUG-14199
- pathview->setOffset(7);
- pathview->setOffset(0);
- QCOMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
-
- pathview->setCurrentIndex(model.count()-1);
- model.removeItem(model.count()-1);
- QCOMPARE(pathview->currentIndex(), model.count()-1);
-
- delete canvas;
- delete testObject;
-}
-
-void tst_QQuickPathView::pathMoved()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Ben", "12345");
- model.addItem("Bohn", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
- QPointF start = path->pointAt(0.0);
- QPointF offset;//Center of item is at point, but pos is from corner
- offset.setX(firstItem->width()/2);
- offset.setY(firstItem->height()/2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- pathview->setOffset(1.0);
-
- for (int i=0; i<model.count(); i++) {
- QQuickRectangle *curItem = findItem<QQuickRectangle>(pathview, "wrapper", i);
- QPointF itemPos(path->pointAt(0.25 + i*0.25));
- QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
- }
-
- pathview->setOffset(0.0);
- QCOMPARE(firstItem->pos() + offset, start);
-
- // Change delegate size
- pathview->setOffset(0.1);
- pathview->setOffset(0.0);
- canvas->rootObject()->setProperty("delegateWidth", 30);
- QCOMPARE(firstItem->width(), 30.0);
- offset.setX(firstItem->width()/2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
-
- // Change delegate scale
- pathview->setOffset(0.1);
- pathview->setOffset(0.0);
- canvas->rootObject()->setProperty("delegateScale", 1.2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::setCurrentIndex()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
- model.addItem("Ben", "12345");
- model.addItem("Bohn", "2345");
- model.addItem("Bob", "54321");
- model.addItem("Bill", "4321");
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
- QPointF start = path->pointAt(0.0);
- QPointF offset;//Center of item is at point, but pos is from corner
- offset.setX(firstItem->width()/2);
- offset.setY(firstItem->height()/2);
- QCOMPARE(firstItem->pos() + offset, start);
- QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 0);
- QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 0);
-
- pathview->setCurrentIndex(2);
-
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 2);
- QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 2);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 1);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
- QVERIFY(firstItem);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 0);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 3);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
- QVERIFY(firstItem);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->incrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 0);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- // move an item, set move duration to 0, and change currentIndex to moved item. QTBUG-22786
- model.moveItem(0, 3);
- pathview->setHighlightMoveDuration(0);
- pathview->setCurrentIndex(3);
- QCOMPARE(pathview->currentIndex(), 3);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
- QVERIFY(firstItem);
- QCOMPARE(pathview->currentItem(), firstItem);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- model.moveItem(3, 0);
- pathview->setCurrentIndex(0);
- pathview->setHighlightMoveDuration(300);
-
- // Check the current item is still created when outside the bounds of pathItemCount.
- pathview->setPathItemCount(2);
- pathview->setHighlightRangeMode(QQuickPathView::NoHighlightRange);
- QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 0));
- QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 1));
- QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 2));
- QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 3));
-
- pathview->setCurrentIndex(2);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(false));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 1);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
- QVERIFY(firstItem);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 0);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- pathview->decrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 3);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
- QVERIFY(firstItem);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(false));
-
- pathview->incrementCurrentIndex();
- QTRY_COMPARE(pathview->currentIndex(), 0);
- firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QCOMPARE(pathview->currentItem(), firstItem);
- QCOMPARE(firstItem->property("onPath"), QVariant(true));
-
- delete canvas;
-}
-
-void tst_QQuickPathView::resetModel()
-{
- QQuickView *canvas = createView();
-
- QStringList strings;
- strings << "one" << "two" << "three";
- QStringListModel model(strings);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaypath.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- QCOMPARE(pathview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
- QVERIFY(display != 0);
- QCOMPARE(display->text(), strings.at(i));
- }
-
- strings.clear();
- strings << "four" << "five" << "six" << "seven";
- model.setStringList(strings);
-
- QCOMPARE(pathview->count(), model.rowCount());
-
- for (int i = 0; i < model.rowCount(); ++i) {
- QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
- QVERIFY(display != 0);
- QCOMPARE(display->text(), strings.at(i));
- }
-
- delete canvas;
-}
-
-void tst_QQuickPathView::propertyChanges()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QSignalSpy snapPositionSpy(pathView, SIGNAL(preferredHighlightBeginChanged()));
- QSignalSpy dragMarginSpy(pathView, SIGNAL(dragMarginChanged()));
-
- QCOMPARE(pathView->preferredHighlightBegin(), 0.1);
- QCOMPARE(pathView->dragMargin(), 5.0);
-
- pathView->setPreferredHighlightBegin(0.4);
- pathView->setPreferredHighlightEnd(0.4);
- pathView->setDragMargin(20.0);
-
- QCOMPARE(pathView->preferredHighlightBegin(), 0.4);
- QCOMPARE(pathView->preferredHighlightEnd(), 0.4);
- QCOMPARE(pathView->dragMargin(), 20.0);
-
- QCOMPARE(snapPositionSpy.count(), 1);
- QCOMPARE(dragMarginSpy.count(), 1);
-
- pathView->setPreferredHighlightBegin(0.4);
- pathView->setPreferredHighlightEnd(0.4);
- pathView->setDragMargin(20.0);
-
- QCOMPARE(snapPositionSpy.count(), 1);
- QCOMPARE(dragMarginSpy.count(), 1);
- delete canvas;
-}
-
-void tst_QQuickPathView::pathChanges()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
- QVERIFY(path);
-
- QSignalSpy startXSpy(path, SIGNAL(startXChanged()));
- QSignalSpy startYSpy(path, SIGNAL(startYChanged()));
-
- QCOMPARE(path->startX(), 220.0);
- QCOMPARE(path->startY(), 200.0);
-
- path->setStartX(240.0);
- path->setStartY(220.0);
-
- QCOMPARE(path->startX(), 240.0);
- QCOMPARE(path->startY(), 220.0);
-
- QCOMPARE(startXSpy.count(),1);
- QCOMPARE(startYSpy.count(),1);
-
- path->setStartX(240);
- path->setStartY(220);
-
- QCOMPARE(startXSpy.count(),1);
- QCOMPARE(startYSpy.count(),1);
-
- QDeclarativePath *alternatePath = canvas->rootObject()->findChild<QDeclarativePath*>("alternatePath");
- QVERIFY(alternatePath);
-
- QSignalSpy pathSpy(pathView, SIGNAL(pathChanged()));
-
- QCOMPARE(pathView->path(), path);
-
- pathView->setPath(alternatePath);
- QCOMPARE(pathView->path(), alternatePath);
- QCOMPARE(pathSpy.count(),1);
-
- pathView->setPath(alternatePath);
- QCOMPARE(pathSpy.count(),1);
-
- QDeclarativePathAttribute *pathAttribute = canvas->rootObject()->findChild<QDeclarativePathAttribute*>("pathAttribute");
- QVERIFY(pathAttribute);
-
- QSignalSpy nameSpy(pathAttribute, SIGNAL(nameChanged()));
- QCOMPARE(pathAttribute->name(), QString("opacity"));
-
- pathAttribute->setName("scale");
- QCOMPARE(pathAttribute->name(), QString("scale"));
- QCOMPARE(nameSpy.count(),1);
-
- pathAttribute->setName("scale");
- QCOMPARE(nameSpy.count(),1);
- delete canvas;
-}
-
-void tst_QQuickPathView::componentChanges()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QDeclarativeComponent delegateComponent(canvas->engine());
- delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
-
- QSignalSpy delegateSpy(pathView, SIGNAL(delegateChanged()));
-
- pathView->setDelegate(&delegateComponent);
- QCOMPARE(pathView->delegate(), &delegateComponent);
- QCOMPARE(delegateSpy.count(),1);
-
- pathView->setDelegate(&delegateComponent);
- QCOMPARE(delegateSpy.count(),1);
- delete canvas;
-}
-
-void tst_QQuickPathView::modelChanges()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
- QVERIFY(alternateModel);
- QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
- QSignalSpy modelSpy(pathView, SIGNAL(modelChanged()));
-
- pathView->setModel(modelVariant);
- QCOMPARE(pathView->model(), modelVariant);
- QCOMPARE(modelSpy.count(),1);
-
- pathView->setModel(modelVariant);
- QCOMPARE(modelSpy.count(),1);
-
- pathView->setModel(QVariant());
- QCOMPARE(modelSpy.count(),2);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::pathUpdateOnStartChanged()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathUpdateOnStartChanged.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
- QVERIFY(path);
- QCOMPARE(path->startX(), 400.0);
- QCOMPARE(path->startY(), 300.0);
-
- QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->x(), path->startX() - item->width() / 2.0);
- QCOMPARE(item->y(), path->startY() - item->height() / 2.0);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::package()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview_package.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("photoPathView");
- QVERIFY(pathView);
-
- QQuickItem *item = findItem<QQuickItem>(pathView, "pathItem");
- QVERIFY(item);
- QVERIFY(item->scale() != 1.0);
-
- delete canvas;
-}
-
-//QTBUG-13017
-void tst_QQuickPathView::emptyModel()
-{
- QQuickView *canvas = createView();
-
- QStringListModel model;
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("emptyModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("emptymodel.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
- QVERIFY(pathview != 0);
-
- QCOMPARE(pathview->offset(), qreal(0.0));
-
- delete canvas;
-}
-
-void tst_QQuickPathView::closed()
-{
- QDeclarativeEngine engine;
-
- {
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("openPath.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj);
- QCOMPARE(obj->isClosed(), false);
- delete obj;
- }
-
- {
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("closedPath.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj);
- QCOMPARE(obj->isClosed(), true);
- delete obj;
- }
-}
-
-// QTBUG-14239
-void tst_QQuickPathView::pathUpdate()
-{
- QQuickView *canvas = createView();
- QVERIFY(canvas);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathUpdate.qml")));
-
- QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
- QVERIFY(pathView);
-
- QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->x(), 150.0);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::visualDataModel()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("vdm.qml")));
-
- QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->count(), 3);
-
- delete obj;
-}
-
-void tst_QQuickPathView::undefinedPath()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("undefinedpath.qml")));
-
- QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
-
- QCOMPARE(obj->count(), 3);
-
- delete obj;
-}
-
-void tst_QQuickPathView::mouseDrag()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragpath.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_COMPARE(canvas, qGuiApp->focusWindow());
-
- QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
- QVERIFY(pathview != 0);
-
- int current = pathview->currentIndex();
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10,100));
- QTest::qWait(100);
-
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(30,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- }
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(90,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(canvas, &mv);
- }
-
- QVERIFY(pathview->currentIndex() != current);
-
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(40,100));
-
- delete canvas;
-}
-
-void tst_QQuickPathView::treeModel()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
- canvas->engine()->rootContext()->setContextProperty("myModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("treemodel.qml")));
-
- QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
- QVERIFY(pathview != 0);
- QCOMPARE(pathview->count(), 3);
-
- QQuickText *item = findItem<QQuickText>(pathview, "wrapper", 0);
- QVERIFY(item);
- QCOMPARE(item->text(), QLatin1String("Row 1 Item"));
-
- QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1)));
- QCOMPARE(pathview->count(), 1);
-
- QTRY_VERIFY(item = findItem<QQuickText>(pathview, "wrapper", 0));
- QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item"));
-
- delete canvas;
-}
-
-void tst_QQuickPathView::changePreferredHighlight()
-{
- QQuickView *canvas = createView();
- canvas->setGeometry(0,0,400,200);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragpath.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QTRY_COMPARE(canvas, qGuiApp->focusWindow());
-
- QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
- QVERIFY(pathview != 0);
-
- int current = pathview->currentIndex();
- QCOMPARE(current, 0);
-
- QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
- QPointF start = path->pointAt(0.5);
- start.setX(qRound(start.x()));
- start.setY(qRound(start.y()));
- QPointF offset;//Center of item is at point, but pos is from corner
- offset.setX(firstItem->width()/2);
- offset.setY(firstItem->height()/2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
-
- pathview->setPreferredHighlightBegin(0.8);
- pathview->setPreferredHighlightEnd(0.8);
- start = path->pointAt(0.8);
- start.setX(qRound(start.x()));
- start.setY(qRound(start.y()));
- QTRY_COMPARE(firstItem->pos() + offset, start);
- QCOMPARE(pathview->currentIndex(), 0);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::creationContext()
-{
- QQuickView canvas;
- canvas.setGeometry(0,0,240,320);
- canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
-
- QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
- QVERIFY(rootItem);
- QVERIFY(rootItem->property("count").toInt() > 0);
-
- QQuickItem *item;
- QVERIFY(item = findItem<QQuickItem>(rootItem, "listItem", 0));
- QCOMPARE(item->property("text").toString(), QString("Hello!"));
-}
-
-// QTBUG-21320
-void tst_QQuickPathView::currentOffsetOnInsertion()
-{
- QQuickView *canvas = createView();
- canvas->show();
-
- TestModel model;
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathline.qml")));
- qApp->processEvents();
-
- QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
- QVERIFY(pathview != 0);
-
- pathview->setPreferredHighlightBegin(0.5);
- pathview->setPreferredHighlightEnd(0.5);
-
- QCOMPARE(pathview->count(), model.count());
-
- model.addItem("item0", "0");
-
- QCOMPARE(pathview->count(), model.count());
-
- QQuickRectangle *item = 0;
- QTRY_VERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 0));
-
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
-
- QPointF start = path->pointAt(0.5);
- start = QPointF(qRound(start.x()), qRound(start.y()));
- QPointF offset;//Center of item is at point, but pos is from corner
- offset.setX(item->width()/2);
- offset.setY(item->height()/2);
- QCOMPARE(item->pos() + offset, start);
-
- QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged()));
-
- // insert an item at the beginning
- model.insertItem(0, "item1", "1");
- qApp->processEvents();
-
- QCOMPARE(currentIndexSpy.count(), 1);
-
- // currentIndex is now 1
- QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
-
- // verify that current item (item 1) is still at offset 0.5
- QCOMPARE(item->pos() + offset, start);
-
- // insert another item at the beginning
- model.insertItem(0, "item2", "2");
- qApp->processEvents();
-
- QCOMPARE(currentIndexSpy.count(), 2);
-
- // currentIndex is now 2
- QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 2));
-
- // verify that current item (item 2) is still at offset 0.5
- QCOMPARE(item->pos() + offset, start);
-
- // verify that remove before current maintains current item
- model.removeItem(0);
- qApp->processEvents();
-
- QCOMPARE(currentIndexSpy.count(), 3);
-
- // currentIndex is now 1
- QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
-
- // verify that current item (item 1) is still at offset 0.5
- QCOMPARE(item->pos() + offset, start);
-
- delete canvas;
-}
-
-void tst_QQuickPathView::asynchronous()
-{
- QQuickView *canvas = createView();
- canvas->show();
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- canvas->setSource(TESTDATA("asyncloader.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootObject);
-
- QQuickPathView *pathview = 0;
- while (!pathview) {
- bool b = false;
- controller.incubateWhile(&b);
- pathview = rootObject->findChild<QQuickPathView*>("view");
- }
-
- // items will be created one at a time
- for (int i = 0; i < 5; ++i) {
- QVERIFY(findItem<QQuickItem>(pathview, "wrapper", i) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(pathview, "wrapper", i);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- // verify positioning
- QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
- QVERIFY(firstItem);
- QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
- QVERIFY(path);
- QPointF start = path->pointAt(0.0);
- QPointF offset;//Center of item is at point, but pos is from corner
- offset.setX(firstItem->width()/2);
- offset.setY(firstItem->height()/2);
- QTRY_COMPARE(firstItem->pos() + offset, start);
- pathview->setOffset(1.0);
-
- for (int i=0; i<5; i++) {
- QQuickItem *curItem = findItem<QQuickItem>(pathview, "wrapper", i);
- QPointF itemPos(path->pointAt(0.2 + i*0.2));
- QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
- }
-
- delete canvas;
-}
-
-QQuickView *tst_QQuickPathView::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- return canvas;
-}
-
-/*
- Find an item with the specified objectName. If index is supplied then the
- item must also evaluate the {index} expression equal to index
- */
-template<typename T>
-T *tst_QQuickPathView::findItem(QQuickItem *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeExpression e(qmlContext(item), item, "index");
- if (e.evaluate().toInt() == index)
- return static_cast<T*>(item);
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-template<typename T>
-QList<T*> tst_QQuickPathView::findItems(QQuickItem *parent, const QString &objectName)
-{
- QList<T*> items;
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->QQuickItem::children().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
- items.append(static_cast<T*>(item));
- items += findItems<T>(item, objectName);
- }
-
- return items;
-}
-
-void tst_QQuickPathView::missingPercent()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("missingPercent.qml")));
- QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
- QVERIFY(obj);
- QCOMPARE(obj->attributeAt("_qfx_percent", 1.0), qreal(1.0));
- delete obj;
-}
-
-
-QTEST_MAIN(tst_QQuickPathView)
-
-#include "tst_qquickpathview.moc"
diff --git a/tests/auto/declarative/qquickpincharea/qquickpincharea.pro b/tests/auto/declarative/qquickpincharea/qquickpincharea.pro
deleted file mode 100644
index df750fb2f6..0000000000
--- a/tests/auto/declarative/qquickpincharea/qquickpincharea.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickpincharea
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickpincharea.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/declarative/qquickpincharea/tst_qquickpincharea.cpp
deleted file mode 100644
index 0d6126e671..0000000000
--- a/tests/auto/declarative/qquickpincharea/tst_qquickpincharea.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <private/qquickpincharea_p.h>
-#include <private/qquickrectangle_p.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include "../shared/util.h"
-
-class tst_QQuickPinchArea: public QObject
-{
- Q_OBJECT
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void pinchProperties();
- void scale();
- void pan();
- void retouch();
-
-private:
- QQuickView *createView();
-};
-void tst_QQuickPinchArea::initTestCase()
-{
-}
-
-void tst_QQuickPinchArea::cleanupTestCase()
-{
-
-}
-void tst_QQuickPinchArea::pinchProperties()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
- QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
- QVERIFY(blackRect == pinch->target());
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootItem != 0);
- QSignalSpy targetSpy(pinch, SIGNAL(targetChanged()));
- pinch->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
- pinch->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
-
- // axis
- QCOMPARE(pinch->axis(), QQuickPinch::XandYAxis);
- QSignalSpy axisSpy(pinch, SIGNAL(dragAxisChanged()));
- pinch->setAxis(QQuickPinch::XAxis);
- QCOMPARE(pinch->axis(), QQuickPinch::XAxis);
- QCOMPARE(axisSpy.count(),1);
- pinch->setAxis(QQuickPinch::XAxis);
- QCOMPARE(axisSpy.count(),1);
-
- // minimum and maximum drag properties
- QSignalSpy xminSpy(pinch, SIGNAL(minimumXChanged()));
- QSignalSpy xmaxSpy(pinch, SIGNAL(maximumXChanged()));
- QSignalSpy yminSpy(pinch, SIGNAL(minimumYChanged()));
- QSignalSpy ymaxSpy(pinch, SIGNAL(maximumYChanged()));
-
- QCOMPARE(pinch->xmin(), 0.0);
- QCOMPARE(pinch->xmax(), rootItem->width()-blackRect->width());
- QCOMPARE(pinch->ymin(), 0.0);
- QCOMPARE(pinch->ymax(), rootItem->height()-blackRect->height());
-
- pinch->setXmin(10);
- pinch->setXmax(10);
- pinch->setYmin(10);
- pinch->setYmax(10);
-
- QCOMPARE(pinch->xmin(), 10.0);
- QCOMPARE(pinch->xmax(), 10.0);
- QCOMPARE(pinch->ymin(), 10.0);
- QCOMPARE(pinch->ymax(), 10.0);
-
- QCOMPARE(xminSpy.count(),1);
- QCOMPARE(xmaxSpy.count(),1);
- QCOMPARE(yminSpy.count(),1);
- QCOMPARE(ymaxSpy.count(),1);
-
- pinch->setXmin(10);
- pinch->setXmax(10);
- pinch->setYmin(10);
- pinch->setYmax(10);
-
- QCOMPARE(xminSpy.count(),1);
- QCOMPARE(xmaxSpy.count(),1);
- QCOMPARE(yminSpy.count(),1);
- QCOMPARE(ymaxSpy.count(),1);
-
- // minimum and maximum scale properties
- QSignalSpy scaleMinSpy(pinch, SIGNAL(minimumScaleChanged()));
- QSignalSpy scaleMaxSpy(pinch, SIGNAL(maximumScaleChanged()));
-
- QCOMPARE(pinch->minimumScale(), 1.0);
- QCOMPARE(pinch->maximumScale(), 2.0);
-
- pinch->setMinimumScale(0.5);
- pinch->setMaximumScale(1.5);
-
- QCOMPARE(pinch->minimumScale(), 0.5);
- QCOMPARE(pinch->maximumScale(), 1.5);
-
- QCOMPARE(scaleMinSpy.count(),1);
- QCOMPARE(scaleMaxSpy.count(),1);
-
- pinch->setMinimumScale(0.5);
- pinch->setMaximumScale(1.5);
-
- QCOMPARE(scaleMinSpy.count(),1);
- QCOMPARE(scaleMaxSpy.count(),1);
-
- // minimum and maximum rotation properties
- QSignalSpy rotMinSpy(pinch, SIGNAL(minimumRotationChanged()));
- QSignalSpy rotMaxSpy(pinch, SIGNAL(maximumRotationChanged()));
-
- QCOMPARE(pinch->minimumRotation(), 0.0);
- QCOMPARE(pinch->maximumRotation(), 90.0);
-
- pinch->setMinimumRotation(-90.0);
- pinch->setMaximumRotation(45.0);
-
- QCOMPARE(pinch->minimumRotation(), -90.0);
- QCOMPARE(pinch->maximumRotation(), 45.0);
-
- QCOMPARE(rotMinSpy.count(),1);
- QCOMPARE(rotMaxSpy.count(),1);
-
- pinch->setMinimumRotation(-90.0);
- pinch->setMaximumRotation(45.0);
-
- QCOMPARE(rotMinSpy.count(),1);
- QCOMPARE(rotMaxSpy.count(),1);
-
- delete canvas;
-}
-
-QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
-{
- QTouchEvent::TouchPoint touchPoint(id);
- touchPoint.setPos(i->mapFromScene(p));
- touchPoint.setScreenPos(v->mapToGlobal(p));
- touchPoint.setScenePos(p);
- return touchPoint;
-}
-
-void tst_QQuickPinchArea::scale()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QVERIFY(canvas->rootObject() != 0);
- qApp->processEvents();
-
- QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
- QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
-
- QPoint p1(80, 80);
- QPoint p2(100, 100);
-
- QTest::touchEvent(canvas).press(0, p1, canvas);
- QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1,canvas).move(1, p2,canvas);
-
- QCOMPARE(root->property("scale").toReal(), 1.0);
-
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1,canvas).move(1, p2,canvas);
-
- QCOMPARE(root->property("scale").toReal(), 1.5);
- QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
- QCOMPARE(blackRect->scale(), 1.5);
-
- // scale beyond bound
- p1 -= QPoint(50,50);
- p2 += QPoint(50,50);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(blackRect->scale(), 2.0);
-
- QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
-
- delete canvas;
-}
-
-void tst_QQuickPinchArea::pan()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QVERIFY(canvas->rootObject() != 0);
- qApp->processEvents();
-
- QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
- QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root != 0);
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
-
- QPoint p1(80, 80);
- QPoint p2(100, 100);
-
- QTest::touchEvent(canvas).press(0, p1, canvas);
- QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
- p1 += QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(root->property("scale").toReal(), 1.0);
-
- p1 += QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50
-
- QCOMPARE(blackRect->x(), 60.0);
- QCOMPARE(blackRect->y(), 60.0);
-
- // pan x beyond bound
- p1 += QPoint(100,100);
- p2 += QPoint(100,100);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(blackRect->x(), 140.0);
- QCOMPARE(blackRect->y(), 160.0);
-
- QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
-
- delete canvas;
-}
-
-// test pinch, release one point, touch again to continue pinch
-void tst_QQuickPinchArea::retouch()
-{
- QQuickView *canvas = createView();
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
- QVERIFY(canvas->rootObject() != 0);
- qApp->processEvents();
-
- QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
- QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root != 0);
-
- QSignalSpy startedSpy(pinchArea, SIGNAL(pinchStarted(QQuickPinchEvent *)));
- QSignalSpy finishedSpy(pinchArea, SIGNAL(pinchFinished(QQuickPinchEvent *)));
-
- // target
- QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
-
- QPoint p1(80, 80);
- QPoint p2(100, 100);
-
- QTest::touchEvent(canvas).press(0, p1, canvas);
- QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(root->property("scale").toReal(), 1.0);
-
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- QCOMPARE(startedSpy.count(), 1);
-
- QCOMPARE(root->property("scale").toReal(), 1.5);
- QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
- QCOMPARE(blackRect->scale(), 1.5);
-
- QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2);
-
- QCOMPARE(startedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
-
- QTest::touchEvent(canvas).stationary(0).release(1, p2, canvas);
-
- QCOMPARE(startedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
-
- QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 1);
-
- QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
- p1 -= QPoint(10,10);
- p2 += QPoint(10,10);
- QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
-
- // Lifting and retouching results in onPinchStarted being called again
- QCOMPARE(startedSpy.count(), 2);
- QCOMPARE(finishedSpy.count(), 0);
-
- QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2);
-
- QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
-
- QCOMPARE(startedSpy.count(), 2);
- QCOMPARE(finishedSpy.count(), 1);
-
- delete canvas;
-}
-
-
-QQuickView *tst_QQuickPinchArea::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- return canvas;
-}
-
-QTEST_MAIN(tst_QQuickPinchArea)
-
-#include "tst_qquickpincharea.moc"
diff --git a/tests/auto/declarative/qquickpositioners/qquickpositioners.pro b/tests/auto/declarative/qquickpositioners/qquickpositioners.pro
deleted file mode 100644
index eee9eca97a..0000000000
--- a/tests/auto/declarative/qquickpositioners/qquickpositioners.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickpositioners
-SOURCES += tst_qquickpositioners.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/declarative/qquickpositioners/tst_qquickpositioners.cpp
deleted file mode 100644
index ebfd394b0e..0000000000
--- a/tests/auto/declarative/qquickpositioners/tst_qquickpositioners.cpp
+++ /dev/null
@@ -1,1473 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <private/qlistmodelinterface_p.h>
-#include <qquickview.h>
-#include <qdeclarativeengine.h>
-#include <private/qquickrectangle_p.h>
-#include <private/qquickpositioners_p.h>
-#include <private/qdeclarativetransition_p.h>
-#include <private/qquickitem_p.h>
-#include <qdeclarativeexpression.h>
-#include "../shared/util.h"
-
-class tst_qquickpositioners : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickpositioners();
-
-private slots:
- void test_horizontal();
- void test_horizontal_rtl();
- void test_horizontal_spacing();
- void test_horizontal_spacing_rightToLeft();
- void test_horizontal_animated();
- void test_horizontal_animated_rightToLeft();
- void test_horizontal_animated_disabled();
- void test_vertical();
- void test_vertical_spacing();
- void test_vertical_animated();
- void test_grid();
- void test_grid_topToBottom();
- void test_grid_rightToLeft();
- void test_grid_spacing();
- void test_grid_row_column_spacing();
- void test_grid_animated();
- void test_grid_animated_rightToLeft();
- void test_grid_zero_columns();
- void test_propertychanges();
- void test_repeater();
- void test_flow();
- void test_flow_rightToLeft();
- void test_flow_topToBottom();
- void test_flow_resize();
- void test_flow_resize_rightToLeft();
- void test_flow_implicit_resize();
- void test_conflictinganchors();
- void test_mirroring();
- void test_allInvisible();
- void test_attachedproperties();
- void test_attachedproperties_data();
- void test_attachedproperties_dynamic();
-
-private:
- QQuickView *createView(const QString &filename, bool wait=true);
-};
-
-tst_qquickpositioners::tst_qquickpositioners()
-{
-}
-
-void tst_qquickpositioners::test_horizontal()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 70.0);
- QCOMPARE(three->y(), 0.0);
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QCOMPARE(row->width(), 110.0);
- QCOMPARE(row->height(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_rtl()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 60.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 40.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 0.0);
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QCOMPARE(row->width(), 110.0);
- QCOMPARE(row->height(), 50.0);
-
- // Change the width of the row and check that items stay to the right
- row->setWidth(200);
- QTRY_COMPARE(one->x(), 150.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 130.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 90.0);
- QCOMPARE(three->y(), 0.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_spacing()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal-spacing.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 60.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 90.0);
- QCOMPARE(three->y(), 0.0);
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QCOMPARE(row->width(), 130.0);
- QCOMPARE(row->height(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal-spacing.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 80.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 00.0);
- QCOMPARE(three->y(), 0.0);
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QCOMPARE(row->width(), 130.0);
- QCOMPARE(row->height(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_animated()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal-animated.qml"), false);
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- //Note that they animate in
- QCOMPARE(one->x(), -100.0);
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(three->x(), -100.0);
-
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QVERIFY(row);
- QCOMPARE(row->width(), 100.0);
- QCOMPARE(row->height(), 50.0);
-
- //QTRY_COMPARE used instead of waiting for the expected time of animation completion
- //Note that this means the duration of the animation is NOT tested
-
- QTRY_COMPARE(one->x(), 0.0);
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(two->isVisible(), false);
- QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
- QTRY_COMPARE(two->y(), 0.0);
- QTRY_COMPARE(three->x(), 50.0);
- QTRY_COMPARE(three->y(), 0.0);
-
- //Add 'two'
- two->setVisible(true);
- QTRY_COMPARE(two->isVisible(), true);
- QTRY_COMPARE(row->width(), 150.0);
- QTRY_COMPARE(row->height(), 50.0);
-
- QTest::qWait(0);//Let the animation start
- QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
- QVERIFY(three->x() >= 50.0 && three->x() < 100.0);
-
- QTRY_COMPARE(two->x(), 50.0);
- QTRY_COMPARE(three->x(), 100.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal-animated.qml"), false);
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- //Note that they animate in
- QCOMPARE(one->x(), -100.0);
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(three->x(), -100.0);
-
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QVERIFY(row);
- QCOMPARE(row->width(), 100.0);
- QCOMPARE(row->height(), 50.0);
-
- //QTRY_COMPARE used instead of waiting for the expected time of animation completion
- //Note that this means the duration of the animation is NOT tested
-
- QTRY_COMPARE(one->x(), 50.0);
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(two->isVisible(), false);
- QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
- QTRY_COMPARE(two->y(), 0.0);
- QTRY_COMPARE(three->x(), 0.0);
- QTRY_COMPARE(three->y(), 0.0);
-
- //Add 'two'
- two->setVisible(true);
- QTRY_COMPARE(two->isVisible(), true);
-
- // New size should propagate after visible change
- QTRY_COMPARE(row->width(), 150.0);
- QTRY_COMPARE(row->height(), 50.0);
-
- QTest::qWait(0);//Let the animation start
- QVERIFY(one->x() >= 50.0 && one->x() < 100);
- QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
-
- QTRY_COMPARE(one->x(), 100.0);
- QTRY_COMPARE(two->x(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_horizontal_animated_disabled()
-{
- QQuickView *canvas = createView(TESTDATA("horizontal-animated-disabled.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
- QVERIFY(row);
-
- qApp->processEvents();
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->isVisible(), false);
- QCOMPARE(two->x(), -100.0);//Not 'in' yet
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 50.0);
- QCOMPARE(three->y(), 0.0);
-
- //Add 'two'
- two->setVisible(true);
- QCOMPARE(two->isVisible(), true);
- QTRY_COMPARE(row->width(), 150.0);
- QTRY_COMPARE(row->height(), 50.0);
-
- QTRY_COMPARE(two->x(), 50.0);
- QTRY_COMPARE(three->x(), 100.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_vertical()
-{
- QQuickView *canvas = createView(TESTDATA("vertical.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 0.0);
- QCOMPARE(two->y(), 50.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 60.0);
-
- QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
- QVERIFY(column);
- QCOMPARE(column->height(), 80.0);
- QCOMPARE(column->width(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_vertical_spacing()
-{
- QQuickView *canvas = createView(TESTDATA("vertical-spacing.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 0.0);
- QCOMPARE(two->y(), 60.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 80.0);
-
- QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
- QCOMPARE(column->height(), 100.0);
- QCOMPARE(column->width(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_vertical_animated()
-{
- QQuickView *canvas = createView(TESTDATA("vertical-animated.qml"), false);
-
- //Note that they animate in
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QCOMPARE(one->y(), -100.0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QCOMPARE(two->y(), -100.0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QCOMPARE(three->y(), -100.0);
-
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
- QVERIFY(column);
- QCOMPARE(column->height(), 100.0);
- QCOMPARE(column->width(), 50.0);
-
- //QTRY_COMPARE used instead of waiting for the expected time of animation completion
- //Note that this means the duration of the animation is NOT tested
-
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(one->x(), 0.0);
- QTRY_COMPARE(two->isVisible(), false);
- QTRY_COMPARE(two->y(), -100.0);//Not 'in' yet
- QTRY_COMPARE(two->x(), 0.0);
- QTRY_COMPARE(three->y(), 50.0);
- QTRY_COMPARE(three->x(), 0.0);
-
- //Add 'two'
- two->setVisible(true);
- QTRY_COMPARE(two->isVisible(), true);
- QTRY_COMPARE(column->height(), 150.0);
- QTRY_COMPARE(column->width(), 50.0);
- QTest::qWait(0);//Let the animation start
- QVERIFY(two->y() >= -100.0 && two->y() < 50.0);
- QVERIFY(three->y() >= 50.0 && three->y() < 100.0);
-
- QTRY_COMPARE(two->y(), 50.0);
- QTRY_COMPARE(three->y(), 100.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid()
-{
- QQuickView *canvas = createView(TESTDATA("gridtest.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 70.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 50.0);
- QCOMPARE(five->x(), 50.0);
- QCOMPARE(five->y(), 50.0);
-
- QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
- QCOMPARE(grid->flow(), QQuickGrid::LeftToRight);
- QCOMPARE(grid->width(), 100.0);
- QCOMPARE(grid->height(), 100.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_topToBottom()
-{
- QQuickView *canvas = createView(TESTDATA("grid-toptobottom.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 0.0);
- QCOMPARE(two->y(), 50.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 100.0);
- QCOMPARE(four->x(), 50.0);
- QCOMPARE(four->y(), 0.0);
- QCOMPARE(five->x(), 50.0);
- QCOMPARE(five->y(), 50.0);
-
- QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
- QCOMPARE(grid->flow(), QQuickGrid::TopToBottom);
- QCOMPARE(grid->width(), 100.0);
- QCOMPARE(grid->height(), 120.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("gridtest.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 50.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 30.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 50.0);
- QCOMPARE(four->y(), 50.0);
- QCOMPARE(five->x(), 40.0);
- QCOMPARE(five->y(), 50.0);
-
- QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
- QCOMPARE(grid->layoutDirection(), Qt::RightToLeft);
- QCOMPARE(grid->width(), 100.0);
- QCOMPARE(grid->height(), 100.0);
-
- // Change the width of the grid and check that items stay to the right
- grid->setWidth(200);
- QTRY_COMPARE(one->x(), 150.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 130.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 100.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 150.0);
- QCOMPARE(four->y(), 50.0);
- QCOMPARE(five->x(), 140.0);
- QCOMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_spacing()
-{
- QQuickView *canvas = createView(TESTDATA("grid-spacing.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 54.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 78.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 54.0);
- QCOMPARE(five->x(), 54.0);
- QCOMPARE(five->y(), 54.0);
-
- QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
- QCOMPARE(grid->width(), 128.0);
- QCOMPARE(grid->height(), 104.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_row_column_spacing()
-{
- QQuickView *canvas = createView(TESTDATA("grid-row-column-spacing.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 61.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 92.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 57.0);
- QCOMPARE(five->x(), 61.0);
- QCOMPARE(five->y(), 57.0);
-
- QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
- QCOMPARE(grid->width(), 142.0);
- QCOMPARE(grid->height(), 107.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_animated()
-{
- QQuickView *canvas = createView(TESTDATA("grid-animated.qml"), false);
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- //Note that all animate in
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QCOMPARE(one->x(), -100.0);
- QCOMPARE(one->y(), -100.0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(two->y(), -100.0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QCOMPARE(three->x(), -100.0);
- QCOMPARE(three->y(), -100.0);
-
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QCOMPARE(four->x(), -100.0);
- QCOMPARE(four->y(), -100.0);
-
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
- QCOMPARE(five->x(), -100.0);
- QCOMPARE(five->y(), -100.0);
-
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
- QVERIFY(grid);
- QCOMPARE(grid->width(), 150.0);
- QCOMPARE(grid->height(), 100.0);
-
- //QTRY_COMPARE used instead of waiting for the expected time of animation completion
- //Note that this means the duration of the animation is NOT tested
-
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(one->x(), 0.0);
- QTRY_COMPARE(two->isVisible(), false);
- QTRY_COMPARE(two->y(), -100.0);
- QTRY_COMPARE(two->x(), -100.0);
- QTRY_COMPARE(three->y(), 0.0);
- QTRY_COMPARE(three->x(), 50.0);
- QTRY_COMPARE(four->y(), 0.0);
- QTRY_COMPARE(four->x(), 100.0);
- QTRY_COMPARE(five->y(), 50.0);
- QTRY_COMPARE(five->x(), 0.0);
-
- //Add 'two'
- two->setVisible(true);
- QCOMPARE(two->isVisible(), true);
- QCOMPARE(grid->width(), 150.0);
- QCOMPARE(grid->height(), 100.0);
- QTest::qWait(0);//Let the animation start
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(two->y(), -100.0);
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(three->x(), 50.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 100.0);
- QCOMPARE(four->y(), 0.0);
- QCOMPARE(five->x(), 0.0);
- QCOMPARE(five->y(), 50.0);
- //Let the animation complete
- QTRY_COMPARE(two->x(), 50.0);
- QTRY_COMPARE(two->y(), 0.0);
- QTRY_COMPARE(one->x(), 0.0);
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(three->x(), 100.0);
- QTRY_COMPARE(three->y(), 0.0);
- QTRY_COMPARE(four->x(), 0.0);
- QTRY_COMPARE(four->y(), 50.0);
- QTRY_COMPARE(five->x(), 50.0);
- QTRY_COMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_animated_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("grid-animated.qml"), false);
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- //Note that all animate in
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QCOMPARE(one->x(), -100.0);
- QCOMPARE(one->y(), -100.0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(two->y(), -100.0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QCOMPARE(three->x(), -100.0);
- QCOMPARE(three->y(), -100.0);
-
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QCOMPARE(four->x(), -100.0);
- QCOMPARE(four->y(), -100.0);
-
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
- QCOMPARE(five->x(), -100.0);
- QCOMPARE(five->y(), -100.0);
-
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
- QVERIFY(grid);
- QCOMPARE(grid->width(), 150.0);
- QCOMPARE(grid->height(), 100.0);
-
- //QTRY_COMPARE used instead of waiting for the expected time of animation completion
- //Note that this means the duration of the animation is NOT tested
-
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(one->x(), 100.0);
- QTRY_COMPARE(two->isVisible(), false);
- QTRY_COMPARE(two->y(), -100.0);
- QTRY_COMPARE(two->x(), -100.0);
- QTRY_COMPARE(three->y(), 0.0);
- QTRY_COMPARE(three->x(), 50.0);
- QTRY_COMPARE(four->y(), 0.0);
- QTRY_COMPARE(four->x(), 0.0);
- QTRY_COMPARE(five->y(), 50.0);
- QTRY_COMPARE(five->x(), 100.0);
-
- //Add 'two'
- two->setVisible(true);
- QCOMPARE(two->isVisible(), true);
- QCOMPARE(grid->width(), 150.0);
- QCOMPARE(grid->height(), 100.0);
- QTest::qWait(0);//Let the animation start
- QCOMPARE(two->x(), -100.0);
- QCOMPARE(two->y(), -100.0);
- QCOMPARE(one->x(), 100.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(three->x(), 50.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 0.0);
- QCOMPARE(five->x(), 100.0);
- QCOMPARE(five->y(), 50.0);
- //Let the animation complete
- QTRY_COMPARE(two->x(), 50.0);
- QTRY_COMPARE(two->y(), 0.0);
- QTRY_COMPARE(one->x(), 100.0);
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(three->x(), 0.0);
- QTRY_COMPARE(three->y(), 0.0);
- QTRY_COMPARE(four->x(), 100.0);
- QTRY_COMPARE(four->y(), 50.0);
- QTRY_COMPARE(five->x(), 50.0);
- QTRY_COMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_grid_zero_columns()
-{
- QQuickView *canvas = createView(TESTDATA("gridzerocolumns.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 70.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 120.0);
- QCOMPARE(four->y(), 0.0);
- QCOMPARE(five->x(), 0.0);
- QCOMPARE(five->y(), 50.0);
-
- QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
- QCOMPARE(grid->width(), 170.0);
- QCOMPARE(grid->height(), 60.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_propertychanges()
-{
- QQuickView *canvas = createView(TESTDATA("propertychangestest.qml"));
-
- QQuickGrid *grid = qobject_cast<QQuickGrid*>(canvas->rootObject());
- QVERIFY(grid != 0);
- QDeclarativeTransition *rowTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("rowTransition");
- QDeclarativeTransition *columnTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("columnTransition");
-
- QSignalSpy addSpy(grid, SIGNAL(addChanged()));
- QSignalSpy moveSpy(grid, SIGNAL(moveChanged()));
- QSignalSpy columnsSpy(grid, SIGNAL(columnsChanged()));
- QSignalSpy rowsSpy(grid, SIGNAL(rowsChanged()));
-
- QVERIFY(grid);
- QVERIFY(rowTransition);
- QVERIFY(columnTransition);
- QCOMPARE(grid->add(), columnTransition);
- QCOMPARE(grid->move(), columnTransition);
- QCOMPARE(grid->columns(), 4);
- QCOMPARE(grid->rows(), -1);
-
- grid->setAdd(rowTransition);
- grid->setMove(rowTransition);
- QCOMPARE(grid->add(), rowTransition);
- QCOMPARE(grid->move(), rowTransition);
- QCOMPARE(addSpy.count(),1);
- QCOMPARE(moveSpy.count(),1);
-
- grid->setAdd(rowTransition);
- grid->setMove(rowTransition);
- QCOMPARE(addSpy.count(),1);
- QCOMPARE(moveSpy.count(),1);
-
- grid->setAdd(0);
- grid->setMove(0);
- QCOMPARE(addSpy.count(),2);
- QCOMPARE(moveSpy.count(),2);
-
- grid->setColumns(-1);
- grid->setRows(3);
- QCOMPARE(grid->columns(), -1);
- QCOMPARE(grid->rows(), 3);
- QCOMPARE(columnsSpy.count(),1);
- QCOMPARE(rowsSpy.count(),1);
-
- grid->setColumns(-1);
- grid->setRows(3);
- QCOMPARE(columnsSpy.count(),1);
- QCOMPARE(rowsSpy.count(),1);
-
- grid->setColumns(2);
- grid->setRows(2);
- QCOMPARE(columnsSpy.count(),2);
- QCOMPARE(rowsSpy.count(),2);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_repeater()
-{
- QQuickView *canvas = createView(TESTDATA("repeatertest.qml"));
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
-
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
-
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 100.0);
- QCOMPARE(three->y(), 0.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow()
-{
- QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 0.0);
- QCOMPARE(three->y(), 50.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 70.0);
- QCOMPARE(five->x(), 50.0);
- QCOMPARE(five->y(), 70.0);
-
- QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
- QVERIFY(flow);
- QCOMPARE(flow->width(), 90.0);
- QCOMPARE(flow->height(), 120.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 40.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 20.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 40.0);
- QCOMPARE(three->y(), 50.0);
- QCOMPARE(four->x(), 40.0);
- QCOMPARE(four->y(), 70.0);
- QCOMPARE(five->x(), 30.0);
- QCOMPARE(five->y(), 70.0);
-
- QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
- QVERIFY(flow);
- QCOMPARE(flow->width(), 90.0);
- QCOMPARE(flow->height(), 120.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow_topToBottom()
-{
- QQuickView *canvas = createView(TESTDATA("flowtest-toptobottom.qml"));
-
- canvas->rootObject()->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 50.0);
- QCOMPARE(three->y(), 50.0);
- QCOMPARE(four->x(), 100.0);
- QCOMPARE(four->y(), 00.0);
- QCOMPARE(five->x(), 100.0);
- QCOMPARE(five->y(), 50.0);
-
- QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
- QVERIFY(flow);
- QCOMPARE(flow->height(), 90.0);
- QCOMPARE(flow->width(), 150.0);
-
- canvas->rootObject()->setProperty("testRightToLeft", true);
-
- QVERIFY(flow);
- QCOMPARE(flow->height(), 90.0);
- QCOMPARE(flow->width(), 150.0);
-
- QCOMPARE(one->x(), 100.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 80.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 50.0);
- QCOMPARE(three->y(), 50.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 0.0);
- QCOMPARE(five->x(), 40.0);
- QCOMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow_resize()
-{
- QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root);
- root->setWidth(125);
- root->setProperty("testRightToLeft", false);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QTRY_COMPARE(one->x(), 0.0);
- QTRY_COMPARE(one->y(), 0.0);
- QTRY_COMPARE(two->x(), 50.0);
- QTRY_COMPARE(two->y(), 0.0);
- QTRY_COMPARE(three->x(), 70.0);
- QTRY_COMPARE(three->y(), 0.0);
- QTRY_COMPARE(four->x(), 0.0);
- QTRY_COMPARE(four->y(), 50.0);
- QTRY_COMPARE(five->x(), 50.0);
- QTRY_COMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow_resize_rightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root);
- root->setWidth(125);
- root->setProperty("testRightToLeft", true);
-
- QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
- QTRY_VERIFY(one != 0);
- QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
- QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
- QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
- QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
-
- QCOMPARE(one->x(), 75.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 55.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 5.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 75.0);
- QCOMPARE(four->y(), 50.0);
- QCOMPARE(five->x(), 65.0);
- QCOMPARE(five->y(), 50.0);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_flow_implicit_resize()
-{
- QQuickView *canvas = createView(TESTDATA("flow-testimplicitsize.qml"));
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickFlow *flow = canvas->rootObject()->findChild<QQuickFlow*>("flow");
- QVERIFY(flow != 0);
-
- QCOMPARE(flow->width(), 100.0);
- QCOMPARE(flow->height(), 120.0);
-
- canvas->rootObject()->setProperty("flowLayout", 0);
- QCOMPARE(flow->flow(), QQuickFlow::LeftToRight);
- QCOMPARE(flow->width(), 220.0);
- QCOMPARE(flow->height(), 50.0);
-
- canvas->rootObject()->setProperty("flowLayout", 1);
- QCOMPARE(flow->flow(), QQuickFlow::TopToBottom);
- QCOMPARE(flow->width(), 100.0);
- QCOMPARE(flow->height(), 120.0);
-
- canvas->rootObject()->setProperty("flowLayout", 2);
- QCOMPARE(flow->layoutDirection(), Qt::RightToLeft);
- QCOMPARE(flow->width(), 220.0);
- QCOMPARE(flow->height(), 50.0);
-
- delete canvas;
-}
-
-QString warningMessage;
-
-void interceptWarnings(QtMsgType type, const char *msg)
-{
- Q_UNUSED( type );
- warningMessage = msg;
-}
-
-void tst_qquickpositioners::test_conflictinganchors()
-{
- QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings);
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine);
-
- component.setData("import QtQuick 2.0\nColumn { Item {} }", QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- delete item;
-
- component.setData("import QtQuick 2.0\nRow { Item {} }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- delete item;
-
- component.setData("import QtQuick 2.0\nGrid { Item {} }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- delete item;
-
- component.setData("import QtQuick 2.0\nFlow { Item {} }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- delete item;
-
- component.setData("import QtQuick 2.0\nColumn { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nColumn { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nColumn { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nRow { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nRow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nRow { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QVERIFY(warningMessage.isEmpty());
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nGrid { Item { anchors.horizontalCenter: parent.horizontalCenter } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nGrid { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
- warningMessage.clear();
- delete item;
-
- component.setData("import QtQuick 2.0\nFlow { Item { anchors.verticalCenter: parent.verticalCenter } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
- delete item;
-
- component.setData("import QtQuick 2.0\nFlow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
- item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item);
- QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
- qInstallMsgHandler(oldMsgHandler);
- delete item;
-}
-
-void tst_qquickpositioners::test_mirroring()
-{
- QList<QString> qmlFiles;
- qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
- QList<QString> objectNames;
- objectNames << "one" << "two" << "three" << "four" << "five";
-
- foreach (const QString qmlFile, qmlFiles) {
- QQuickView *canvasA = createView(TESTDATA(qmlFile));
- QQuickItem *rootA = qobject_cast<QQuickItem*>(canvasA->rootObject());
-
- QQuickView *canvasB = createView(TESTDATA(qmlFile));
- QQuickItem *rootB = qobject_cast<QQuickItem*>(canvasB->rootObject());
-
- rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
-
- // LTR != RTL
- foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
- break;
- QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
- QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
- QTRY_VERIFY(itemA->x() != itemB->x());
- }
-
- QQuickItemPrivate* rootPrivateB = QQuickItemPrivate::get(rootB);
-
- rootPrivateB->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
- rootPrivateB->isMirrorImplicit = false;
- rootPrivateB->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
- rootPrivateB->resolveLayoutMirror();
-
- // RTL == mirror
- foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
- break;
- QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
- QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
- QTRY_COMPARE(itemA->x(), itemB->x());
- }
-
- rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
- rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
-
- // LTR == RTL + mirror
- foreach (const QString objectName, objectNames) {
- // horizontal.qml only has three items
- if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
- break;
- QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
- QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
- QTRY_COMPARE(itemA->x(), itemB->x());
- }
- delete canvasA;
- delete canvasB;
- }
-}
-
-void tst_qquickpositioners::test_allInvisible()
-{
- //QTBUG-19361
- QQuickView *canvas = createView(TESTDATA("allInvisible.qml"));
-
- QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(root);
-
- QQuickRow *row = canvas->rootObject()->findChild<QQuickRow*>("row");
- QVERIFY(row != 0);
- QVERIFY(row->width() == 0);
- QVERIFY(row->height() == 0);
- QQuickColumn *column = canvas->rootObject()->findChild<QQuickColumn*>("column");
- QVERIFY(column != 0);
- QVERIFY(column->width() == 0);
- QVERIFY(column->height() == 0);
-}
-
-void tst_qquickpositioners::test_attachedproperties()
-{
- QFETCH(QString, filename);
-
- QQuickView *canvas = createView(filename);
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickRectangle *greenRect = canvas->rootObject()->findChild<QQuickRectangle *>("greenRect");
- QVERIFY(greenRect != 0);
-
- int posIndex = greenRect->property("posIndex").toInt();
- QVERIFY(posIndex == 0);
- bool isFirst = greenRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == true);
- bool isLast = greenRect->property("isLastItem").toBool();
- QVERIFY(isLast == false);
-
- QQuickRectangle *yellowRect = canvas->rootObject()->findChild<QQuickRectangle *>("yellowRect");
- QVERIFY(yellowRect != 0);
-
- posIndex = yellowRect->property("posIndex").toInt();
- QVERIFY(posIndex == -1);
- isFirst = yellowRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == false);
- isLast = yellowRect->property("isLastItem").toBool();
- QVERIFY(isLast == false);
-
- yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
-
- posIndex = yellowRect->property("posIndex").toInt();
- QVERIFY(posIndex == 1);
- isFirst = yellowRect->property("isFirstItem").toBool();
- QVERIFY(isFirst == false);
- isLast = yellowRect->property("isLastItem").toBool();
- QVERIFY(isLast == true);
-
- delete canvas;
-}
-
-void tst_qquickpositioners::test_attachedproperties_data()
-{
- QTest::addColumn<QString>("filename");
-
- QTest::newRow("column") << TESTDATA("attachedproperties-column.qml");
- QTest::newRow("row") << TESTDATA("attachedproperties-row.qml");
- QTest::newRow("grid") << TESTDATA("attachedproperties-grid.qml");
- QTest::newRow("flow") << TESTDATA("attachedproperties-flow.qml");
-}
-
-void tst_qquickpositioners::test_attachedproperties_dynamic()
-{
- QQuickView *canvas = createView(TESTDATA("attachedproperties-dynamic.qml"));
- QVERIFY(canvas->rootObject() != 0);
-
- QQuickRow *row = canvas->rootObject()->findChild<QQuickRow *>("pos");
- QVERIFY(row != 0);
-
- QQuickRectangle *rect0 = canvas->rootObject()->findChild<QQuickRectangle *>("rect0");
- QVERIFY(rect0 != 0);
-
- int posIndex = rect0->property("index").toInt();
- QVERIFY(posIndex == 0);
- bool isFirst = rect0->property("firstItem").toBool();
- QVERIFY(isFirst == true);
- bool isLast = rect0->property("lastItem").toBool();
- QVERIFY(isLast == false);
-
- QQuickRectangle *rect1 = canvas->rootObject()->findChild<QQuickRectangle *>("rect1");
- QVERIFY(rect1 != 0);
-
- posIndex = rect1->property("index").toInt();
- QVERIFY(posIndex == 1);
- isFirst = rect1->property("firstItem").toBool();
- QVERIFY(isFirst == false);
- isLast = rect1->property("lastItem").toBool();
- QVERIFY(isLast == true);
-
- row->metaObject()->invokeMethod(row, "createSubRect");
-
- QTRY_VERIFY(rect1->property("index").toInt() == 1);
- QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
- QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
-
- QQuickRectangle *rect2 = canvas->rootObject()->findChild<QQuickRectangle *>("rect2");
- QVERIFY(rect2 != 0);
-
- posIndex = rect2->property("index").toInt();
- QVERIFY(posIndex == 2);
- isFirst = rect2->property("firstItem").toBool();
- QVERIFY(isFirst == false);
- isLast = rect2->property("lastItem").toBool();
- QVERIFY(isLast == true);
-
- row->metaObject()->invokeMethod(row, "destroySubRect");
-
- qApp->processEvents(QEventLoop::DeferredDeletion);
-
- QTRY_VERIFY(rect1->property("index").toInt() == 1);
- QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
- QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
-
- delete canvas;
-}
-
-QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait)
-{
- QQuickView *canvas = new QQuickView(0);
-
- canvas->setSource(QUrl::fromLocalFile(filename));
- canvas->show();
- if (wait)
- QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
-
- return canvas;
-}
-
-
-QTEST_MAIN(tst_qquickpositioners)
-
-#include "tst_qquickpositioners.moc"
diff --git a/tests/auto/declarative/qquickrepeater/qquickrepeater.pro b/tests/auto/declarative/qquickrepeater/qquickrepeater.pro
deleted file mode 100644
index 9cdb9c2c53..0000000000
--- a/tests/auto/declarative/qquickrepeater/qquickrepeater.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickrepeater
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickrepeater.cpp
-
-testFiles.files = data
-testFiles.path = .
-DEPLOYMENT += testFiles
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/declarative/qquickrepeater/tst_qquickrepeater.cpp
deleted file mode 100644
index 6024d1307a..0000000000
--- a/tests/auto/declarative/qquickrepeater/tst_qquickrepeater.cpp
+++ /dev/null
@@ -1,765 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include <QtTest/QSignalSpy>
-#include <private/qlistmodelinterface_p.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativeincubator.h>
-#include <private/qquickrepeater_p.h>
-#include <private/qquicktext_p.h>
-
-#include "../shared/util.h"
-#include "../../../shared/util.h"
-
-inline QUrl TEST_FILE(const QString &filename)
-{
- return QUrl::fromLocalFile(TESTDATA(filename));
-}
-
-class tst_QQuickRepeater : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickRepeater();
-
-private slots:
- void numberModel();
- void objectList();
- void stringList();
- void dataModel_adding();
- void dataModel_removing();
- void dataModel_changes();
- void itemModel();
- void resetModel();
- void modelChanged();
- void properties();
- void asynchronous();
- void initParent();
-
-private:
- QQuickView *createView();
- template<typename T>
- T *findItem(QObject *parent, const QString &objectName, int index);
- template<typename T>
- T *findItem(QObject *parent, const QString &id);
-};
-
-class TestObject : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool error READ error WRITE setError)
- Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
-
-public:
- TestObject() : QObject(), mError(true), mUseModel(false) {}
-
- bool error() const { return mError; }
- void setError(bool err) { mError = err; }
-
- bool useModel() const { return mUseModel; }
- void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
-
-signals:
- void useModelChanged();
-
-private:
- bool mError;
- bool mUseModel;
-};
-
-class TestModel : public QAbstractListModel
-{
-public:
- enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
-
- TestModel(QObject *parent=0) : QAbstractListModel(parent) {
- QHash<int, QByteArray> roles;
- roles[Name] = "name";
- roles[Number] = "number";
- setRoleNames(roles);
- }
-
- int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
- QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
- QVariant rv;
- if (role == Name)
- rv = list.at(index.row()).first;
- else if (role == Number)
- rv = list.at(index.row()).second;
-
- return rv;
- }
-
- int count() const { return rowCount(); }
- QString name(int index) const { return list.at(index).first; }
- QString number(int index) const { return list.at(index).second; }
-
- void addItem(const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), list.count(), list.count());
- list.append(QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void insertItem(int index, const QString &name, const QString &number) {
- emit beginInsertRows(QModelIndex(), index, index);
- list.insert(index, QPair<QString,QString>(name, number));
- emit endInsertRows();
- }
-
- void removeItem(int index) {
- emit beginRemoveRows(QModelIndex(), index, index);
- list.removeAt(index);
- emit endRemoveRows();
- }
-
- void moveItem(int from, int to) {
- emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
- list.move(from, to);
- emit endMoveRows();
- }
-
- void modifyItem(int idx, const QString &name, const QString &number) {
- list[idx] = QPair<QString,QString>(name, number);
- emit dataChanged(index(idx,0), index(idx,0));
- }
-
-private:
- QList<QPair<QString,QString> > list;
-};
-
-
-tst_QQuickRepeater::tst_QQuickRepeater()
-{
-}
-
-void tst_QQuickRepeater::numberModel()
-{
- QQuickView *canvas = createView();
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testData", 5);
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(TEST_FILE("intmodel.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
-
- QVERIFY(!repeater->itemAt(-1));
- for (int i=0; i<repeater->count(); i++)
- QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
- QVERIFY(!repeater->itemAt(repeater->count()));
-
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
-
- delete testObject;
- delete canvas;
-}
-
-class MyObject : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int idx READ idx CONSTANT)
-public:
- MyObject(int i) : QObject(), m_idx(i) {}
-
- int idx() const { return m_idx; }
-
- int m_idx;
-};
-
-void tst_QQuickRepeater::objectList()
-{
- QQuickView *canvas = createView();
- QObjectList data;
- for (int i=0; i<100; i++)
- data << new MyObject(i);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testData", QVariant::fromValue(data));
-
- canvas->setSource(TEST_FILE("objlist.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
- QCOMPARE(repeater->property("instantiated").toInt(), 100);
-
- QVERIFY(!repeater->itemAt(-1));
- for (int i=0; i<data.count(); i++)
- QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
- QVERIFY(!repeater->itemAt(data.count()));
-
- QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
- QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
- ctxt->setContextProperty("testData", QVariant::fromValue(data));
- QCOMPARE(addedSpy.count(), data.count());
- QCOMPARE(removedSpy.count(), data.count());
-
- qDeleteAll(data);
- delete canvas;
-}
-
-/*
-The Repeater element creates children at its own position in its parent's
-stacking order. In this test we insert a repeater between two other Text
-elements to test this.
-*/
-void tst_QQuickRepeater::stringList()
-{
- QQuickView *canvas = createView();
-
- QStringList data;
- data << "One";
- data << "Two";
- data << "Three";
- data << "Four";
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testData", data);
-
- canvas->setSource(TEST_FILE("repeater1.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
-
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
-
- QCOMPARE(container->childItems().count(), data.count() + 3);
-
- bool saw_repeater = false;
- for (int i = 0; i < container->childItems().count(); ++i) {
-
- if (i == 0) {
- QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
- QCOMPARE(name->text(), QLatin1String("Zero"));
- } else if (i == container->childItems().count() - 2) {
- // The repeater itself
- QQuickRepeater *rep = qobject_cast<QQuickRepeater*>(container->childItems().at(i));
- QCOMPARE(rep, repeater);
- saw_repeater = true;
- continue;
- } else if (i == container->childItems().count() - 1) {
- QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
- QCOMPARE(name->text(), QLatin1String("Last"));
- } else {
- QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
- QCOMPARE(name->text(), data.at(i-1));
- }
- }
- QVERIFY(saw_repeater);
-
- delete canvas;
-}
-
-void tst_QQuickRepeater::dataModel_adding()
-{
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- TestModel testModel;
- ctxt->setContextProperty("testData", &testModel);
- canvas->setSource(TEST_FILE("repeater2.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
-
- QVERIFY(!repeater->itemAt(0));
-
- QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
- QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
-
- // add to empty model
- testModel.addItem("two", "2");
- QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(addedSpy.count(), 1);
- QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
- QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
- addedSpy.clear();
-
- // insert at start
- testModel.insertItem(0, "one", "1");
- QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(addedSpy.count(), 1);
- QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
- QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
- addedSpy.clear();
-
- // insert at end
- testModel.insertItem(2, "four", "4");
- QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(addedSpy.count(), 1);
- QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
- QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
- addedSpy.clear();
-
- // insert in middle
- testModel.insertItem(2, "three", "3");
- QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(addedSpy.count(), 1);
- QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
- QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
- addedSpy.clear();
-
- delete testObject;
- addedSpy.clear();
- countSpy.clear();
- delete canvas;
-}
-
-void tst_QQuickRepeater::dataModel_removing()
-{
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- TestModel testModel;
- testModel.addItem("one", "1");
- testModel.addItem("two", "2");
- testModel.addItem("three", "3");
- testModel.addItem("four", "4");
- testModel.addItem("five", "5");
-
- ctxt->setContextProperty("testData", &testModel);
- canvas->setSource(TEST_FILE("repeater2.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
- QCOMPARE(container->childItems().count(), repeater->count()+1);
-
- QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
- QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
-
- // remove at start
- QQuickItem *item = repeater->itemAt(0);
- QCOMPARE(item, container->childItems().at(0));
-
- testModel.removeItem(0);
- QVERIFY(repeater->itemAt(0) != item);
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(removedSpy.count(), 1);
- QCOMPARE(removedSpy.at(0).at(0).toInt(), 0);
- QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
- removedSpy.clear();
-
- // remove at end
- int lastIndex = testModel.count()-1;
- item = repeater->itemAt(lastIndex);
- QCOMPARE(item, container->childItems().at(lastIndex));
-
- testModel.removeItem(lastIndex);
- QVERIFY(repeater->itemAt(lastIndex) != item);
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(removedSpy.count(), 1);
- QCOMPARE(removedSpy.at(0).at(0).toInt(), lastIndex);
- QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
- removedSpy.clear();
-
- // remove from middle
- item = repeater->itemAt(1);
- QCOMPARE(item, container->childItems().at(1));
-
- testModel.removeItem(1);
- QVERIFY(repeater->itemAt(lastIndex) != item);
- QCOMPARE(countSpy.count(), 1); countSpy.clear();
- QCOMPARE(removedSpy.count(), 1);
- QCOMPARE(removedSpy.at(0).at(0).toInt(), 1);
- QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
- removedSpy.clear();
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickRepeater::dataModel_changes()
-{
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- TestModel testModel;
- testModel.addItem("one", "1");
- testModel.addItem("two", "2");
- testModel.addItem("three", "3");
-
- ctxt->setContextProperty("testData", &testModel);
- canvas->setSource(TEST_FILE("repeater2.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
- QCOMPARE(container->childItems().count(), repeater->count()+1);
-
- // Check that model changes are propagated
- QQuickText *text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
- QVERIFY(text);
- QCOMPARE(text->text(), QString("two"));
-
- testModel.modifyItem(1, "Item two", "_2");
- text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
- QVERIFY(text);
- QCOMPARE(text->text(), QString("Item two"));
-
- text = findItem<QQuickText>(canvas->rootObject(), "myNumber", 1);
- QVERIFY(text);
- QCOMPARE(text->text(), QString("_2"));
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickRepeater::itemModel()
-{
- QQuickView *canvas = createView();
- QDeclarativeContext *ctxt = canvas->rootContext();
- TestObject *testObject = new TestObject;
- ctxt->setContextProperty("testObject", testObject);
-
- canvas->setSource(TEST_FILE("itemlist.qml"));
- qApp->processEvents();
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
-
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
-
- QCOMPARE(container->childItems().count(), 1);
-
- testObject->setUseModel(true);
- QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
- QVERIFY(testObject->error() == false);
-
- QCOMPARE(container->childItems().count(), 4);
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
- QVERIFY(container->childItems().at(3) == repeater);
-
- QMetaObject::invokeMethod(canvas->rootObject(), "switchModel");
- QCOMPARE(container->childItems().count(), 3);
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item4");
- QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item5");
- QVERIFY(container->childItems().at(2) == repeater);
-
- testObject->setUseModel(false);
- QCOMPARE(container->childItems().count(), 1);
-
- delete testObject;
- delete canvas;
-}
-
-void tst_QQuickRepeater::resetModel()
-{
- QQuickView *canvas = createView();
-
- QStringList dataA;
- for (int i=0; i<10; i++)
- dataA << QString::number(i);
-
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testData", dataA);
- canvas->setSource(TEST_FILE("repeater1.qml"));
- qApp->processEvents();
- QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
- QVERIFY(repeater != 0);
- QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
- QVERIFY(container != 0);
-
- QCOMPARE(repeater->count(), dataA.count());
- for (int i=0; i<repeater->count(); i++)
- QCOMPARE(repeater->itemAt(i), container->childItems().at(i+1)); // +1 to skip first Text object
-
- QSignalSpy modelChangedSpy(repeater, SIGNAL(modelChanged()));
- QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
- QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
- QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
-
- QStringList dataB;
- for (int i=0; i<20; i++)
- dataB << QString::number(i);
-
- // reset context property
- ctxt->setContextProperty("testData", dataB);
- QCOMPARE(repeater->count(), dataB.count());
-
- QCOMPARE(modelChangedSpy.count(), 1);
- QCOMPARE(countSpy.count(), 1);
- QCOMPARE(removedSpy.count(), dataA.count());
- QCOMPARE(addedSpy.count(), dataB.count());
- for (int i=0; i<dataB.count(); i++) {
- QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
- QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
- }
- modelChangedSpy.clear();
- countSpy.clear();
- removedSpy.clear();
- addedSpy.clear();
-
- // reset via setModel()
- repeater->setModel(dataA);
- QCOMPARE(repeater->count(), dataA.count());
-
- QCOMPARE(modelChangedSpy.count(), 1);
- QCOMPARE(countSpy.count(), 1);
- QCOMPARE(removedSpy.count(), dataB.count());
- QCOMPARE(addedSpy.count(), dataA.count());
- for (int i=0; i<dataA.count(); i++) {
- QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
- QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
- }
-
- modelChangedSpy.clear();
- countSpy.clear();
- removedSpy.clear();
- addedSpy.clear();
-
- delete canvas;
-}
-
-// QTBUG-17156
-void tst_QQuickRepeater::modelChanged()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, TEST_FILE("modelChanged.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(rootObject);
- QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
- QVERIFY(repeater);
-
- repeater->setModel(4);
- QCOMPARE(repeater->count(), 4);
- QCOMPARE(repeater->property("itemsCount").toInt(), 4);
- QCOMPARE(repeater->property("itemsFound").toList().count(), 4);
-
- repeater->setModel(10);
- QCOMPARE(repeater->count(), 10);
- QCOMPARE(repeater->property("itemsCount").toInt(), 10);
- QCOMPARE(repeater->property("itemsFound").toList().count(), 10);
-
- delete rootObject;
-}
-
-void tst_QQuickRepeater::properties()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, TEST_FILE("properties.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(rootObject);
-
- QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
- QVERIFY(repeater);
-
- QSignalSpy modelSpy(repeater, SIGNAL(modelChanged()));
- repeater->setModel(3);
- QCOMPARE(modelSpy.count(),1);
- repeater->setModel(3);
- QCOMPARE(modelSpy.count(),1);
-
- QSignalSpy delegateSpy(repeater, SIGNAL(delegateChanged()));
-
- QDeclarativeComponent rectComponent(&engine);
- rectComponent.setData("import QtQuick 2.0; Rectangle {}", QUrl::fromLocalFile(""));
-
- repeater->setDelegate(&rectComponent);
- QCOMPARE(delegateSpy.count(),1);
- repeater->setDelegate(&rectComponent);
- QCOMPARE(delegateSpy.count(),1);
-
- delete rootObject;
-}
-
-void tst_QQuickRepeater::asynchronous()
-{
- QQuickView *canvas = createView();
- canvas->show();
- QDeclarativeIncubationController controller;
- canvas->engine()->setIncubationController(&controller);
-
- canvas->setSource(TEST_FILE("asyncloader.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(rootObject);
-
- QQuickItem *container = findItem<QQuickItem>(rootObject, "container");
- QVERIFY(!container);
- while (!container) {
- bool b = false;
- controller.incubateWhile(&b);
- container = findItem<QQuickItem>(rootObject, "container");
- }
-
- QQuickRepeater *repeater = 0;
- while (!repeater) {
- bool b = false;
- controller.incubateWhile(&b);
- repeater = findItem<QQuickRepeater>(rootObject, "repeater");
- }
-
- // items will be created one at a time
- for (int i = 0; i < 10; ++i) {
- QString name("delegate");
- name += QString::number(i);
- QVERIFY(findItem<QQuickItem>(container, name) == 0);
- QQuickItem *item = 0;
- while (!item) {
- bool b = false;
- controller.incubateWhile(&b);
- item = findItem<QQuickItem>(container, name);
- }
- }
-
- {
- bool b = true;
- controller.incubateWhile(&b);
- }
-
- // verify positioning
- for (int i = 0; i < 10; ++i) {
- QString name("delegate");
- name += QString::number(i);
- QQuickItem *item = findItem<QQuickItem>(container, name);
- QTRY_COMPARE(item->y(), i * 50.0);
- }
-
- delete canvas;
-}
-
-void tst_QQuickRepeater::initParent()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent component(&engine, TEST_FILE("initparent.qml"));
-
- QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(rootObject);
-
- QCOMPARE(qvariant_cast<QQuickItem*>(rootObject->property("parentItem")), rootObject);
-}
-
-QQuickView *tst_QQuickRepeater::createView()
-{
- QQuickView *canvas = new QQuickView(0);
- canvas->setGeometry(0,0,240,320);
-
- return canvas;
-}
-
-template<typename T>
-T *tst_QQuickRepeater::findItem(QObject *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->children().count() << "children";
- for (int i = 0; i < parent->children().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->children().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeExpression e(qmlContext(item), item, "index");
- if (e.evaluate().toInt() == index)
- return static_cast<T*>(item);
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-template<typename T>
-T *tst_QQuickRepeater::findItem(QObject *parent, const QString &objectName)
-{
- const QMetaObject &mo = T::staticMetaObject;
- if (mo.cast(parent) && (objectName.isEmpty() || parent->objectName() == objectName))
- return static_cast<T*>(parent);
- for (int i = 0; i < parent->children().count(); ++i) {
- QQuickItem *child = qobject_cast<QQuickItem*>(parent->children().at(i));
- if (!child)
- continue;
- QQuickItem *item = findItem<T>(child, objectName);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-QTEST_MAIN(tst_QQuickRepeater)
-
-#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/declarative/qquickshadereffect/qquickshadereffect.pro b/tests/auto/declarative/qquickshadereffect/qquickshadereffect.pro
deleted file mode 100644
index 540bbe1515..0000000000
--- a/tests/auto/declarative/qquickshadereffect/qquickshadereffect.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickshadereffect
-SOURCES += tst_qquickshadereffect.cpp
-
-macx:CONFIG -= app_bundle
-
-CONFIG += parallel_test
-QT += core-private gui-private declarative-private widgets testlib
diff --git a/tests/auto/declarative/qquickspriteimage/qquickspriteimage.pro b/tests/auto/declarative/qquickspriteimage/qquickspriteimage.pro
deleted file mode 100644
index db5c45da8a..0000000000
--- a/tests/auto/declarative/qquickspriteimage/qquickspriteimage.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickspriteimage
-SOURCES += tst_qquickspriteimage.cpp
-macx:CONFIG -= app_bundle
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private declarative-private network testlib
diff --git a/tests/auto/declarative/qquickspriteimage/tst_qquickspriteimage.cpp b/tests/auto/declarative/qquickspriteimage/tst_qquickspriteimage.cpp
deleted file mode 100644
index 1b8c58b873..0000000000
--- a/tests/auto/declarative/qquickspriteimage/tst_qquickspriteimage.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <QtTest/QtTest>
-#include "../shared/util.h"
-#include <qquickview.h>
-#include <private/qquickspriteimage_p.h>
-
-class tst_qquickspriteimage : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickspriteimage(){}
-
-private slots:
- void test_properties();
-};
-
-void tst_qquickspriteimage::test_properties()
-{
- QQuickView *canvas = new QQuickView(0);
-
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("basic.qml")));
- canvas->show();
- QTest::qWaitForWindowShown(canvas);
-
- QVERIFY(canvas->rootObject());
- QQuickSpriteImage* sprite = canvas->rootObject()->findChild<QQuickSpriteImage*>("sprite");
- QVERIFY(sprite);
-
- QVERIFY(sprite->running());
- QVERIFY(sprite->interpolate());
-
- sprite->setRunning(false);
- QVERIFY(!sprite->running());
- sprite->setInterpolate(false);
- QVERIFY(!sprite->interpolate());
-
- delete canvas;
-}
-
-QTEST_MAIN(tst_qquickspriteimage)
-
-#include "tst_qquickspriteimage.moc"
diff --git a/tests/auto/declarative/qquicktext/qquicktext.pro b/tests/auto/declarative/qquicktext/qquicktext.pro
deleted file mode 100644
index fe69f75746..0000000000
--- a/tests/auto/declarative/qquicktext/qquicktext.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquicktext
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquicktext.cpp
-
-INCLUDEPATH += ../shared/
-HEADERS += ../shared/testhttpserver.h
-SOURCES += ../shared/testhttpserver.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private widgets-private opengl-private network testlib
diff --git a/tests/auto/declarative/qquicktext/tst_qquicktext.cpp b/tests/auto/declarative/qquicktext/tst_qquicktext.cpp
deleted file mode 100644
index fb37357608..0000000000
--- a/tests/auto/declarative/qquicktext/tst_qquicktext.cpp
+++ /dev/null
@@ -1,1460 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QTextDocument>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <private/qquicktext_p.h>
-#include <private/qquicktext_p_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include <QFontMetrics>
-#include <QGraphicsSceneMouseEvent>
-#include <qmath.h>
-#include <QQuickView>
-#include <private/qapplication_p.h>
-#include <limits.h>
-#include <QtGui/QMouseEvent>
-#include "../shared/util.h"
-#include "testhttpserver.h"
-
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-class tst_qquicktext : public QObject
-{
- Q_OBJECT
-public:
- tst_qquicktext();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void text();
- void width();
- void wrap();
- void elide();
- void multilineElide();
- void textFormat();
-
- void alignments_data();
- void alignments();
-
- void embeddedImages_data();
- void embeddedImages();
-
- void lineCount();
- void lineHeight();
-
- // ### these tests may be trivial
- void horizontalAlignment();
- void horizontalAlignment_RightToLeft();
- void verticalAlignment();
- void font();
- void style();
- void color();
- void smooth();
-
- // QDeclarativeFontValueType
- void weight();
- void underline();
- void overline();
- void strikeout();
- void capitalization();
- void letterSpacing();
- void wordSpacing();
-
- void clickLink();
-
- void implicitSize_data();
- void implicitSize();
-
- void lineLaidOut();
-
-
-private:
- QStringList standard;
- QStringList richText;
-
- QStringList horizontalAlignmentmentStrings;
- QStringList verticalAlignmentmentStrings;
-
- QList<Qt::Alignment> verticalAlignmentments;
- QList<Qt::Alignment> horizontalAlignmentments;
-
- QStringList styleStrings;
- QList<QQuickText::TextStyle> styles;
-
- QStringList colorStrings;
-
- QDeclarativeEngine engine;
-
- QQuickView *createView(const QString &filename);
-};
-void tst_qquicktext::initTestCase()
-{
-}
-
-void tst_qquicktext::cleanupTestCase()
-{
-
-}
-tst_qquicktext::tst_qquicktext()
-{
- standard << "the quick brown fox jumped over the lazy dog"
- << "the quick brown fox\n jumped over the lazy dog";
-
- richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
- << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
-
- horizontalAlignmentmentStrings << "AlignLeft"
- << "AlignRight"
- << "AlignHCenter";
-
- verticalAlignmentmentStrings << "AlignTop"
- << "AlignBottom"
- << "AlignVCenter";
-
- horizontalAlignmentments << Qt::AlignLeft
- << Qt::AlignRight
- << Qt::AlignHCenter;
-
- verticalAlignmentments << Qt::AlignTop
- << Qt::AlignBottom
- << Qt::AlignVCenter;
-
- styleStrings << "Normal"
- << "Outline"
- << "Raised"
- << "Sunken";
-
- styles << QQuickText::Normal
- << QQuickText::Outline
- << QQuickText::Raised
- << QQuickText::Sunken;
-
- colorStrings << "aliceblue"
- << "antiquewhite"
- << "aqua"
- << "darkkhaki"
- << "darkolivegreen"
- << "dimgray"
- << "palevioletred"
- << "lightsteelblue"
- << "#000000"
- << "#AAAAAA"
- << "#FFFFFF"
- << "#2AC05F";
- //
- // need a different test to do alpha channel test
- // << "#AA0011DD"
- // << "#00F16B11";
- //
-}
-
-QQuickView *tst_qquicktext::createView(const QString &filename)
-{
- QQuickView *canvas = new QQuickView(0);
-
- canvas->setSource(QUrl::fromLocalFile(filename));
- return canvas;
-}
-
-void tst_qquicktext::text()
-{
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->text(), QString(""));
- QVERIFY(textObject->width() == 0);
-
- delete textObject;
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
-
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->text(), standard.at(i));
- QVERIFY(textObject->width() > 0);
-
- delete textObject;
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QString expected = richText.at(i);
- QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
- QVERIFY(textObject->width() > 0);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::width()
-{
- // uses Font metrics to find the width for standard and document to find the width for rich
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->width(), 0.);
-
- delete textObject;
- }
-
- bool requiresUnhintedMetrics = !qmlDisableDistanceField();
-
- for (int i = 0; i < standard.size(); i++)
- {
- QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
-
- QFont f;
- qreal metricWidth = 0.0;
-
- if (requiresUnhintedMetrics) {
- QString s = standard.at(i);
- s.replace(QLatin1Char('\n'), QChar::LineSeparator);
-
- QTextLayout layout(s);
- layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
- {
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
- }
-
- layout.beginLayout();
- forever {
- QTextLine line = layout.createLine();
- if (!line.isValid())
- break;
- }
-
- layout.endLayout();
-
- metricWidth = qCeil(layout.boundingRect().width());
- } else {
- QFontMetricsF fm(f);
- qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
- metricWidth = qCeil(metricWidth);
- }
-
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->boundingRect().width() > 0);
- QCOMPARE(textObject->width(), qreal(metricWidth));
- QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
-
- delete textObject;
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
-
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
-
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
-
- QTextDocument *doc = textPrivate->textDocument();
- QVERIFY(doc != 0);
-
- QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
- QVERIFY(textObject->textFormat() == QQuickText::RichText);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::wrap()
-{
- int textHeight = 0;
- // for specified width and wrap set true
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- textHeight = textObject->height();
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
- QCOMPARE(textObject->width(), 300.);
-
- delete textObject;
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->width(), 30.);
- QVERIFY(textObject->height() > textHeight);
-
- int oldHeight = textObject->height();
- textObject->setWidth(100);
- QVERIFY(textObject->height() < oldHeight);
-
- delete textObject;
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->width(), 30.);
- QVERIFY(textObject->height() > textHeight);
-
- qreal oldHeight = textObject->height();
- textObject->setWidth(100);
- QVERIFY(textObject->height() < oldHeight);
-
- delete textObject;
- }
-
- // richtext again with a fixed height
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->width(), 30.);
- QVERIFY(textObject->implicitHeight() > textHeight);
-
- qreal oldHeight = textObject->implicitHeight();
- textObject->setWidth(100);
- QVERIFY(textObject->implicitHeight() < oldHeight);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::elide()
-{
- for (QQuickText::TextElideMode m = QQuickText::ElideLeft; m<=QQuickText::ElideNone; m=QQuickText::TextElideMode(int(m)+1)) {
- const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
- QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
-
- // XXX Poor coverage.
-
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->elideMode(), m);
- QCOMPARE(textObject->width(), 100.);
-
- delete textObject;
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->elideMode(), m);
- QCOMPARE(textObject->width(), 100.);
-
- delete textObject;
- }
-
- // richtext - does nothing
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->elideMode(), m);
- QCOMPARE(textObject->width(), 100.);
-
- delete textObject;
- }
- }
-}
-
-void tst_qquicktext::multilineElide()
-{
- QQuickView *canvas = createView(TESTDATA("multilineelide.qml"));
-
- QQuickText *myText = qobject_cast<QQuickText*>(canvas->rootObject());
- QVERIFY(myText != 0);
-
- QCOMPARE(myText->lineCount(), 3);
- QCOMPARE(myText->truncated(), true);
-
- qreal lineHeight = myText->paintedHeight() / 3.;
-
- // reduce size and ensure fewer lines are drawn
- myText->setHeight(lineHeight * 2);
- QCOMPARE(myText->lineCount(), 2);
-
- myText->setHeight(lineHeight);
- QCOMPARE(myText->lineCount(), 1);
-
- myText->setHeight(5);
- QCOMPARE(myText->lineCount(), 1);
-
- myText->setHeight(lineHeight * 3);
- QCOMPARE(myText->lineCount(), 3);
-
- // remove max count and show all lines.
- myText->setHeight(1000);
- myText->resetMaximumLineCount();
-
- QCOMPARE(myText->truncated(), false);
-
- // reduce size again
- myText->setHeight(lineHeight * 2);
- QCOMPARE(myText->lineCount(), 2);
- QCOMPARE(myText->truncated(), true);
-
- // change line height
- myText->setLineHeight(1.1);
- QCOMPARE(myText->lineCount(), 1);
-
- delete canvas;
-}
-
-void tst_qquicktext::textFormat()
-{
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::RichText);
-
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->richText == true);
-
- delete textObject;
- }
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::AutoText);
-
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
- QVERIFY(textPrivate->styledText == true);
-
- delete textObject;
- }
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickText::PlainText);
-
- delete textObject;
- }
-}
-
-
-void tst_qquicktext::alignments_data()
-{
- QTest::addColumn<int>("hAlign");
- QTest::addColumn<int>("vAlign");
- QTest::addColumn<QString>("expectfile");
-
- QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << TESTDATA("alignments_lt.png");
- QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << TESTDATA("alignments_rt.png");
- QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << TESTDATA("alignments_ct.png");
-
- QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << TESTDATA("alignments_lb.png");
- QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << TESTDATA("alignments_rb.png");
- QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << TESTDATA("alignments_cb.png");
-
- QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << TESTDATA("alignments_lc.png");
- QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << TESTDATA("alignments_rc.png");
- QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << TESTDATA("alignments_cc.png");
-}
-
-
-void tst_qquicktext::alignments()
-{
- QSKIP("Text alignment pixmap comparison tests will not work with scenegraph");
-#if (0)// No widgets in scenegraph
- QFETCH(int, hAlign);
- QFETCH(int, vAlign);
- QFETCH(QString, expectfile);
-
- QQuickView *canvas = createView(TESTDATA("alignments.qml"));
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWait(50);
- QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
-
- QObject *ob = canvas->rootObject();
- QVERIFY(ob != 0);
- ob->setProperty("horizontalAlignment",hAlign);
- ob->setProperty("verticalAlignment",vAlign);
- QTRY_COMPARE(ob->property("running").toBool(),false);
- QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
- actual.fill(qRgb(255,255,255));
- QPainter p(&actual);
- canvas->render(&p);
-
- QImage expect(expectfile);
- if (QApplicationPrivate::graphics_system_name == "raster" || QApplicationPrivate::graphics_system_name == "") {
- QCOMPARE(actual,expect);
- }
- delete canvas;
-#endif
-}
-
-//the alignment tests may be trivial o.oa
-void tst_qquicktext::horizontalAlignment()
-{
- //test one align each, and then test if two align fails.
-
- for (int i = 0; i < standard.size(); i++)
- {
- for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
-
- delete textObject;
- }
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
-
- delete textObject;
- }
- }
-
-}
-
-void tst_qquicktext::horizontalAlignment_RightToLeft()
-{
- QQuickView *canvas = createView(TESTDATA("horizontalAlignment_RightToLeft.qml"));
- QQuickText *text = canvas->rootObject()->findChild<QQuickText*>("text");
- QVERIFY(text != 0);
- canvas->show();
-
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
- QVERIFY(textPrivate != 0);
-
- // implicit alignment should follow the reading direction of RTL text
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
-
- // explicitly left aligned text
- text->setHAlign(QQuickText::AlignLeft);
- QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
-
- // explicitly right aligned text
- text->setHAlign(QQuickText::AlignRight);
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
-
- // change to rich text
- QString textString = text->text();
- text->setText(QString("<i>") + textString + QString("</i>"));
- text->setTextFormat(QQuickText::RichText);
- text->resetHAlign();
-
- // implicitly aligned rich text should follow the reading direction of text
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
-
- // explicitly left aligned rich text
- text->setHAlign(QQuickText::AlignLeft);
- QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight);
-
- // explicitly right aligned rich text
- text->setHAlign(QQuickText::AlignRight);
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
-
- text->setText(textString);
- text->setTextFormat(QQuickText::PlainText);
-
- // explicitly center aligned
- text->setHAlign(QQuickText::AlignHCenter);
- QCOMPARE(text->hAlign(), QQuickText::AlignHCenter);
- QCOMPARE(text->effectiveHAlign(), text->hAlign());
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2);
-
- // reseted alignment should go back to following the text reading direction
- text->resetHAlign();
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
-
- // mirror the text item
- QQuickItemPrivate::get(text)->setLayoutMirror(true);
-
- // mirrored implicit alignment should continue to follow the reading direction of the text
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
-
- // mirrored explicitly right aligned behaves as left aligned
- text->setHAlign(QQuickText::AlignRight);
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
- QCOMPARE(text->effectiveHAlign(), QQuickText::AlignLeft);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
-
- // mirrored explicitly left aligned behaves as right aligned
- text->setHAlign(QQuickText::AlignLeft);
- QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
- QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
-
- // disable mirroring
- QQuickItemPrivate::get(text)->setLayoutMirror(false);
- text->resetHAlign();
-
- // English text should be implicitly left aligned
- text->setText("Hello world!");
- QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
- QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
-
-#ifndef Q_OS_MAC // QTBUG-18040
- // empty text with implicit alignment follows the system locale-based
- // keyboard input direction from QApplication::keyboardInputDirection
- text->setText("");
- QCOMPARE(text->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickText::AlignLeft : QQuickText::AlignRight);
- text->setHAlign(QQuickText::AlignRight);
- QCOMPARE(text->hAlign(), QQuickText::AlignRight);
-#endif
-
- delete canvas;
-
-#ifndef Q_OS_MAC // QTBUG-18040
- // alignment of Text with no text set to it
- QString componentStr = "import QtQuick 2.0\nText {}";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickText::AlignLeft : QQuickText::AlignRight);
- delete textObject;
-#endif
-}
-
-void tst_qquicktext::verticalAlignment()
-{
- //test one align each, and then test if two align fails.
-
- for (int i = 0; i < standard.size(); i++)
- {
- for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
-
- delete textObject;
- }
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
-
- delete textObject;
- }
- }
-
-}
-
-void tst_qquicktext::font()
-{
- //test size, then bold, then italic, then family
- {
- QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().pointSize(), 40);
- QCOMPARE(textObject->font().bold(), false);
- QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().pixelSize(), 40);
- QCOMPARE(textObject->font().bold(), false);
- QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().bold(), true);
- QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().italic(), true);
- QCOMPARE(textObject->font().bold(), false);
-
- delete textObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().family(), QString("Helvetica"));
- QCOMPARE(textObject->font().bold(), false);
- QCOMPARE(textObject->font().italic(), false);
-
- delete textObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->font().family(), QString(""));
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::style()
-{
- //test style
- for (int i = 0; i < styles.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE((int)textObject->style(), (int)styles.at(i));
- QCOMPARE(textObject->styleColor(), QColor("white"));
-
- delete textObject;
- }
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QRectF brPre = textObject->boundingRect();
- textObject->setStyle(QQuickText::Outline);
- QRectF brPost = textObject->boundingRect();
-
- QVERIFY(brPre.width() < brPost.width());
- QVERIFY(brPre.height() < brPost.height());
-
- delete textObject;
-}
-
-void tst_qquicktext::color()
-{
- //test style
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
- QCOMPARE(textObject->styleColor(), QColor());
-
- delete textObject;
- }
-
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
- // default color to black?
- QCOMPARE(textObject->color(), QColor("black"));
-
- delete textObject;
- }
-
- for (int i = 0; i < colorStrings.size(); i++)
- {
- for (int j = 0; j < colorStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
- QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
-
- delete textObject;
- }
- }
- {
- QString colorStr = "#AA001234";
- QColor testColor("#001234");
- testColor.setAlpha(170);
-
- QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QCOMPARE(textObject->color(), testColor);
-
- delete textObject;
- }
-}
-
-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) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), true);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), false);
-
- delete textObject;
- }
- }
- for (int i = 0; i < richText.size(); i++)
- {
- {
- QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), true);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QCOMPARE(textObject->smooth(), false);
-
- delete textObject;
- }
- }
-}
-
-void tst_qquicktext::weight()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Normal);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Bold);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::underline()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().underline(), false);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { font.underline: true; text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().underline(), true);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::overline()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().overline(), false);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { font.overline: true; text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().overline(), true);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::strikeout()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().strikeOut(), false);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { font.strikeout: true; text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().strikeOut(), true);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::capitalization()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::MixedCase);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllUppercase);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllLowercase);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::SmallCaps);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::Capitalize);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::letterSpacing()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().letterSpacing(), 0.0);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().letterSpacing(), -2.);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().letterSpacing(), 3.);
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::wordSpacing()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().wordSpacing(), 0.0);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().wordSpacing(), -50.);
-
- delete textObject;
- }
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QCOMPARE(textObject->font().wordSpacing(), 200.);
-
- delete textObject;
- }
-}
-
-
-
-
-class EventSender : public QQuickItem
-{
-public:
- void sendEvent(QMouseEvent *event) {
- if (event->type() == QEvent::MouseButtonPress)
- mousePressEvent(event);
- else if (event->type() == QEvent::MouseButtonRelease)
- mouseReleaseEvent(event);
- else
- qWarning() << "Trying to send unsupported event type";
- }
-};
-
-class LinkTest : public QObject
-{
- Q_OBJECT
-public:
- LinkTest() {}
-
- QString link;
-
-public slots:
- void linkClicked(QString l) { link = l; }
-};
-
-void tst_qquicktext::clickLink()
-{
- {
- QString componentStr = "import QtQuick 2.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
-
- LinkTest test;
- QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
-
- {
- QMouseEvent me(QEvent::MouseButtonPress,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
- static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
-
- }
-
- {
- QMouseEvent me(QEvent::MouseButtonRelease,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
- static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
-
- }
-
-
- QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
-
- delete textObject;
- }
-}
-
-void tst_qquicktext::embeddedImages_data()
-{
- QTest::addColumn<QUrl>("qmlfile");
- QTest::addColumn<QString>("error");
- QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocal.qml")) << "";
- QTest::newRow("local-error") << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocalError.qml"))
- << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocalError.qml")).toString()+":3:1: QML Text: Cannot open: " + QUrl::fromLocalFile(TESTDATA("http/notexists.png")).toString();
- QTest::newRow("remote") << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemote.qml")) << "";
- QTest::newRow("remote-error") << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemoteError.qml"))
- << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemoteError.qml")).toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found";
-}
-
-void tst_qquicktext::embeddedImages()
-{
- // Tests QTBUG-9900
-
- QFETCH(QUrl, qmlfile);
- QFETCH(QString, error);
-
- TestHTTPServer server(14453);
- server.serveDirectory(TESTDATA("http"));
-
- if (!error.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
-
- QDeclarativeComponent textComponent(&engine, qmlfile);
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject != 0);
-
- QTRY_COMPARE(textObject->resourcesLoading(), 0);
-
- QPixmap pm(TESTDATA("http/exists.png"));
- if (error.isEmpty()) {
- QCOMPARE(textObject->width(), double(pm.width()));
- QCOMPARE(textObject->height(), double(pm.height()));
- } else {
- QVERIFY(16 != pm.width()); // check test is effective
- QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
- QCOMPARE(textObject->height(), 16.0);
- }
-
- delete textObject;
-}
-
-void tst_qquicktext::lineCount()
-{
- QQuickView *canvas = createView(TESTDATA("lineCount.qml"));
-
- QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
-
- QVERIFY(myText->lineCount() > 1);
- QVERIFY(!myText->truncated());
- QCOMPARE(myText->maximumLineCount(), INT_MAX);
-
- myText->setMaximumLineCount(2);
- QCOMPARE(myText->lineCount(), 2);
- QCOMPARE(myText->truncated(), true);
- QCOMPARE(myText->maximumLineCount(), 2);
-
- myText->resetMaximumLineCount();
- QCOMPARE(myText->maximumLineCount(), INT_MAX);
- QCOMPARE(myText->truncated(), false);
-
- myText->setElideMode(QQuickText::ElideRight);
- myText->setMaximumLineCount(2);
- QCOMPARE(myText->lineCount(), 2);
- QCOMPARE(myText->truncated(), true);
- QCOMPARE(myText->maximumLineCount(), 2);
-
- delete canvas;
-}
-
-void tst_qquicktext::lineHeight()
-{
- QQuickView *canvas = createView(TESTDATA("lineHeight.qml"));
-
- QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
-
- QVERIFY(myText->lineHeight() == 1);
- QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
-
- qreal h = myText->height();
- myText->setLineHeight(1.5);
- QVERIFY(myText->height() == qCeil(h * 1.5));
-
- myText->setLineHeightMode(QQuickText::FixedHeight);
- myText->setLineHeight(20);
- QCOMPARE(myText->height(), myText->lineCount() * 20.0);
-
- myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum.");
- myText->setLineHeightMode(QQuickText::ProportionalHeight);
- myText->setLineHeight(1.0);
-
- qreal h2 = myText->height();
- myText->setLineHeight(2.0);
- QVERIFY(myText->height() == h2 * 2.0);
-
- myText->setLineHeightMode(QQuickText::FixedHeight);
- myText->setLineHeight(10);
- QCOMPARE(myText->height(), myText->lineCount() * 10.0);
-
- delete canvas;
-}
-
-void tst_qquicktext::implicitSize_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QString>("wrap");
- QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap";
- QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.NoWrap";
- QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap";
- QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.Wrap";
-}
-
-void tst_qquicktext::implicitSize()
-{
- QFETCH(QString, text);
- QFETCH(QString, wrap);
- QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
-
- QVERIFY(textObject->width() < textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
-
- textObject->resetWidth();
- QVERIFY(textObject->width() == textObject->implicitWidth());
- QVERIFY(textObject->height() == textObject->implicitHeight());
-
- delete textObject;
-}
-
-void tst_qquicktext::lineLaidOut()
-{
- QQuickView *canvas = createView(TESTDATA("lineLayout.qml"));
-
- QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
-
- QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
-
- QTextDocument *doc = textPrivate->textDocument();
- QVERIFY(doc == 0);
-
- QVERIFY(myText->lineCount() == textPrivate->linesRects.count());
-
- for (int i = 0; i < textPrivate->linesRects.count(); ++i) {
- QRectF r = textPrivate->linesRects.at(i);
- QVERIFY(r.width() == i * 15);
- if (i >= 30)
- QVERIFY(r.x() == r.width() + 30);
- if (i >= 60) {
- QVERIFY(r.x() == r.width() * 2 + 60);
- QVERIFY(r.height() == 20);
- }
- }
-}
-
-QTEST_MAIN(tst_qquicktext)
-
-#include "tst_qquicktext.moc"
diff --git a/tests/auto/declarative/qquicktextedit/qquicktextedit.pro b/tests/auto/declarative/qquicktextedit/qquicktextedit.pro
deleted file mode 100644
index ae2233dafc..0000000000
--- a/tests/auto/declarative/qquicktextedit/qquicktextedit.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquicktextedit
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquicktextedit.cpp ../shared/testhttpserver.cpp
-HEADERS += ../shared/testhttpserver.h
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-QT += core-private gui-private v8-private declarative-private opengl-private network widgets-private testlib
diff --git a/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp
deleted file mode 100644
index 6bcad83c52..0000000000
--- a/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp
+++ /dev/null
@@ -1,3555 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include "../shared/testhttpserver.h"
-#include <math.h>
-#include <QFile>
-#include <QTextDocument>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtGui/qguiapplication.h>
-#include <private/qquicktextedit_p.h>
-#include <private/qquicktextedit_p_p.h>
-#include <QFontMetrics>
-#include <QQuickView>
-#include <QDir>
-#include <QStyle>
-#include <QInputPanel>
-#include <QClipboard>
-#include <QMimeData>
-#include <private/qtextcontrol_p.h>
-#include "../shared/util.h"
-#include <qplatforminputcontext_qpa.h>
-#include <private/qinputpanel_p.h>
-
-#ifdef Q_OS_MAC
-#include <Carbon/Carbon.h>
-#endif
-
-
-Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
-{
- // XXX This will be replaced by some clever persistent platform image store.
- QString persistent_dir = TESTDATA("");
- QString arch = "unknown-architecture"; // QTest needs to help with this.
-
- QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
-
- if (!QFile::exists(expectfile)) {
- actual.save(expectfile);
- qWarning() << "created" << expectfile;
- }
-
- return expectfile;
-}
-
-typedef QPair<int, QChar> Key;
-
-class tst_qquicktextedit : public QObject
-
-{
- Q_OBJECT
-public:
- tst_qquicktextedit();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void text();
- void width();
- void wrap();
- void textFormat();
- void alignments();
- void alignments_data();
-
- // ### these tests may be trivial
- void hAlign();
- void hAlign_RightToLeft();
- void vAlign();
- void font();
- void color();
- void textMargin();
- void persistentSelection();
- void focusOnPress();
- void selection();
- void isRightToLeft_data();
- void isRightToLeft();
- void keySelection();
- void moveCursorSelection_data();
- void moveCursorSelection();
- void moveCursorSelectionSequence_data();
- void moveCursorSelectionSequence();
- void mouseSelection_data();
- void mouseSelection();
- void mouseSelectionMode_data();
- void mouseSelectionMode();
- void dragMouseSelection();
- void inputMethodHints();
-
- void positionAt();
-
- void cursorDelegate();
- void cursorVisible();
- void delegateLoading_data();
- void delegateLoading();
- void navigation();
- void readOnly();
- void copyAndPaste();
- void canPaste();
- void canPasteEmpty();
- void textInput();
- void openInputPanel();
- void geometrySignals();
- void pastingRichText_QTBUG_14003();
- void implicitSize_data();
- void implicitSize();
- void testQtQuick11Attributes();
- void testQtQuick11Attributes_data();
-
- void preeditCursorRectangle();
- void inputMethodComposing();
- void cursorRectangleSize();
-
- void getText_data();
- void getText();
- void getFormattedText_data();
- void getFormattedText();
- void insert_data();
- void insert();
- void remove_data();
- void remove();
-
- void keySequence_data();
- void keySequence();
-
- void undo_data();
- void undo();
- void redo_data();
- void redo();
- void undo_keypressevents_data();
- void undo_keypressevents();
-
- void emptytags_QTBUG_22058();
-
-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);
-
- QStringList standard;
- QStringList richText;
-
- QStringList hAlignmentStrings;
- QStringList vAlignmentStrings;
-
- QList<Qt::Alignment> vAlignments;
- QList<Qt::Alignment> hAlignments;
-
- QStringList colorStrings;
-
- QDeclarativeEngine engine;
-};
-
-typedef QList<int> IntList;
-Q_DECLARE_METATYPE(IntList)
-
-typedef QList<Key> KeyList;
-Q_DECLARE_METATYPE(KeyList)
-
-Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
-
-void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
-{
- for (int i = 0; i < keys.count(); ++i) {
- const int key = keys.at(i).first;
- const int modifiers = key & Qt::KeyboardModifierMask;
- const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
-
- QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
- QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
-
- QGuiApplication::sendEvent(window, &press);
- QGuiApplication::sendEvent(window, &release);
- }
-}
-
-void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &sequence)
-{
- for (uint i = 0; i < sequence.count(); ++i) {
- const int key = sequence[i];
- const int modifiers = key & Qt::KeyboardModifierMask;
-
- QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
- }
-}
-
-QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
-{
- for (uint i = 0; i < sequence.count(); ++i)
- keys << Key(sequence[i], QChar());
- return keys;
-}
-
-template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
-{
- for (int i = 0; i < N - 1; ++i) {
- int key = QTest::asciiToKey(characters[i]);
- QChar character = QLatin1Char(characters[i]);
- keys << Key(key, character);
- }
- return keys;
-}
-
-QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
-{
- keys << Key(key, QChar());
- return keys;
-}
-
-
-void tst_qquicktextedit::initTestCase()
-{
-}
-
-void tst_qquicktextedit::cleanupTestCase()
-{
-
-}
-tst_qquicktextedit::tst_qquicktextedit()
-{
- standard << "the quick brown fox jumped over the lazy dog"
- << "the quick brown fox\n jumped over the lazy dog"
- << "Hello, world!"
- << "!dlrow ,olleH";
-
- richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
- << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
-
- hAlignmentStrings << "AlignLeft"
- << "AlignRight"
- << "AlignHCenter";
-
- vAlignmentStrings << "AlignTop"
- << "AlignBottom"
- << "AlignVCenter";
-
- hAlignments << Qt::AlignLeft
- << Qt::AlignRight
- << Qt::AlignHCenter;
-
- vAlignments << Qt::AlignTop
- << Qt::AlignBottom
- << Qt::AlignVCenter;
-
- colorStrings << "aliceblue"
- << "antiquewhite"
- << "aqua"
- << "darkkhaki"
- << "darkolivegreen"
- << "dimgray"
- << "palevioletred"
- << "lightsteelblue"
- << "#000000"
- << "#AAAAAA"
- << "#FFFFFF"
- << "#2AC05F";
- //
- // need a different test to do alpha channel test
- // << "#AA0011DD"
- // << "#00F16B11";
- //
-}
-
-void tst_qquicktextedit::text()
-{
- {
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->text(), QString(""));
- QCOMPARE(textEditObject->length(), 0);
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->text(), standard.at(i));
- QCOMPARE(textEditObject->length(), standard.at(i).length());
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QString actual = textEditObject->text();
- QString expected = richText.at(i);
- actual.replace(QRegExp(".*<body[^>]*>"),"");
- actual.replace(QRegExp("(<[^>]*>)+"),"<>");
- expected.replace(QRegExp("(<[^>]*>)+"),"<>");
- QCOMPARE(actual.simplified(),expected.simplified());
-
- expected.replace("<>", " ");
- QCOMPARE(textEditObject->length(), expected.simplified().length());
- }
-}
-
-void tst_qquicktextedit::width()
-{
- // uses Font metrics to find the width for standard and document to find the width for rich
- {
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), 0.0);
- }
-
- bool requiresUnhintedMetrics = !qmlDisableDistanceField();
-
- for (int i = 0; i < standard.size(); i++)
- {
- QFont f;
- qreal metricWidth = 0.0;
-
- if (requiresUnhintedMetrics) {
- QString s = standard.at(i);
- s.replace(QLatin1Char('\n'), QChar::LineSeparator);
-
- QTextLayout layout(s);
- layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
- {
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
- }
-
- layout.beginLayout();
- forever {
- QTextLine line = layout.createLine();
- if (!line.isValid())
- break;
- }
-
- layout.endLayout();
-
- metricWidth = ceil(layout.boundingRect().width());
- } else {
- QFontMetricsF fm(f);
- metricWidth = fm.size(Qt::TextExpandTabs | Qt::TextShowMnemonic, standard.at(i)).width();
- metricWidth = ceil(metricWidth);
- }
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), qreal(metricWidth));
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QTextDocument document;
- document.setHtml(richText.at(i));
- document.setDocumentMargin(0);
- if (requiresUnhintedMetrics)
- document.setUseDesignMetrics(true);
-
- int documentWidth = ceil(document.idealWidth());
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), qreal(documentWidth));
- }
-}
-
-void tst_qquicktextedit::wrap()
-{
- // for specified width and wrap set true
- {
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), 300.);
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), 300.);
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->width(), 300.);
- }
-
-}
-
-void tst_qquicktextedit::textFormat()
-{
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
- QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickTextEdit::RichText);
- }
- {
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
- QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
-
- QVERIFY(textObject != 0);
- QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
- }
-}
-
-void tst_qquicktextedit::alignments_data()
-{
- QTest::addColumn<int>("hAlign");
- QTest::addColumn<int>("vAlign");
- QTest::addColumn<QString>("expectfile");
-
- QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
- QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
- QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
-
- QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
- QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
- QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
-
- QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
- QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
- QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
-}
-
-
-void tst_qquicktextedit::alignments()
-{
- QSKIP("Image comparison of text is almost guaranteed to fail during development");
-
- QFETCH(int, hAlign);
- QFETCH(int, vAlign);
- QFETCH(QString, expectfile);
-
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("alignments.qml")));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QObject *ob = canvas.rootObject();
- QVERIFY(ob != 0);
- ob->setProperty("horizontalAlignment",hAlign);
- ob->setProperty("verticalAlignment",vAlign);
- QTRY_COMPARE(ob->property("running").toBool(),false);
- QImage actual = canvas.grabFrameBuffer();
-
- expectfile = createExpectedFileIfNotFound(expectfile, actual);
-
- QImage expect(expectfile);
-
- QCOMPARE(actual,expect);
-}
-
-
-//the alignment tests may be trivial o.oa
-void tst_qquicktextedit::hAlign()
-{
- //test one align each, and then test if two align fails.
-
- for (int i = 0; i < standard.size(); i++)
- {
- for (int j=0; j < hAlignmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
- }
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- for (int j=0; j < hAlignmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
- }
- }
-
-}
-
-void tst_qquicktextedit::hAlign_RightToLeft()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment_RightToLeft.qml")));
- QQuickTextEdit *textEdit = canvas.rootObject()->findChild<QQuickTextEdit*>("text");
- QVERIFY(textEdit != 0);
- canvas.show();
-
- const QString rtlText = textEdit->text();
-
- // implicit alignment should follow the reading direction of text
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // explicitly left aligned
- textEdit->setHAlign(QQuickTextEdit::AlignLeft);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
-
- // explicitly right aligned
- textEdit->setHAlign(QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- QString textString = textEdit->text();
- textEdit->setText(QString("<i>") + textString + QString("</i>"));
- textEdit->resetHAlign();
-
- // implicitly aligned rich text should follow the reading direction of RTL text
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // explicitly left aligned rich text
- textEdit->setHAlign(QQuickTextEdit::AlignLeft);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
-
- // explicitly right aligned rich text
- textEdit->setHAlign(QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- textEdit->setText(textString);
-
- // explicitly center aligned
- textEdit->setHAlign(QQuickTextEdit::AlignHCenter);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignHCenter);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // reseted alignment should go back to following the text reading direction
- textEdit->resetHAlign();
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // mirror the text item
- QQuickItemPrivate::get(textEdit)->setLayoutMirror(true);
-
- // mirrored implicit alignment should continue to follow the reading direction of the text
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // mirrored explicitly right aligned behaves as left aligned
- textEdit->setHAlign(QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
-
- // mirrored explicitly left aligned behaves as right aligned
- textEdit->setHAlign(QQuickTextEdit::AlignLeft);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-
- // disable mirroring
- QQuickItemPrivate::get(textEdit)->setLayoutMirror(false);
- textEdit->resetHAlign();
-
- // English text should be implicitly left aligned
- textEdit->setText("Hello world!");
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
-
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- textEdit->setText(QString());
- { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
-
- // Clear pre-edit text. TextEdit should maybe do this itself on setText, but that may be
- // redundant as an actual input method may take care of it.
- { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
-
-#ifndef Q_OS_MAC // QTBUG-18040
- // empty text with implicit alignment follows the system locale-based
- // keyboard input direction from QGuiApplication::keyboardInputDirection
- textEdit->setText("");
- QCOMPARE(textEdit->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickTextEdit::AlignLeft : QQuickTextEdit::AlignRight);
- if (QGuiApplication::keyboardInputDirection() == Qt::LeftToRight)
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
- else
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
- textEdit->setHAlign(QQuickTextEdit::AlignRight);
- QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
-#endif
-
-#ifndef Q_OS_MAC // QTBUG-18040
- // alignment of TextEdit with no text set to it
- QString componentStr = "import QtQuick 2.0\nTextEdit {}";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
- QCOMPARE(textObject->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickTextEdit::AlignLeft : QQuickTextEdit::AlignRight);
- delete textObject;
-#endif
-}
-
-void tst_qquicktextedit::vAlign()
-{
- //test one align each, and then test if two align fails.
-
- for (int i = 0; i < standard.size(); i++)
- {
- for (int j=0; j < vAlignmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
- }
- }
-
- for (int i = 0; i < richText.size(); i++)
- {
- for (int j=0; j < vAlignmentStrings.size(); j++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
- }
- }
-
-}
-
-void tst_qquicktextedit::font()
-{
- //test size, then bold, then italic, then family
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { font.pointSize: 40; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->font().pointSize(), 40);
- QCOMPARE(textEditObject->font().bold(), false);
- QCOMPARE(textEditObject->font().italic(), false);
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { font.bold: true; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->font().bold(), true);
- QCOMPARE(textEditObject->font().italic(), false);
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { font.italic: true; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->font().italic(), true);
- QCOMPARE(textEditObject->font().bold(), false);
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
- QCOMPARE(textEditObject->font().bold(), false);
- QCOMPARE(textEditObject->font().italic(), false);
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { font.family: \"\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->font().family(), QString(""));
- }
-}
-
-void tst_qquicktextedit::color()
-{
- //test initial color
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QQuickTextEditPrivate *textEditPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(textEditObject));
-
- QVERIFY(textEditObject);
- QVERIFY(textEditPrivate);
- QVERIFY(textEditPrivate->control);
-
- QPalette pal = textEditPrivate->control->palette();
- QCOMPARE(textEditPrivate->color, QColor("black"));
- QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text));
- }
- //test normal
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
- }
-
- //test selection
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
- }
-
- //test selected text
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
- }
-
- {
- QString colorStr = "#AA001234";
- QColor testColor("#001234");
- testColor.setAlpha(170);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
-
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->color(), testColor);
- }
-}
-
-void tst_qquicktextedit::textMargin()
-{
- for (qreal i=0; i<=10; i+=0.3) {
- QString componentStr = "import QtQuick 2.0\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->textMargin(), i);
- }
-}
-
-void tst_qquicktextedit::persistentSelection()
-{
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { persistentSelection: true; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->persistentSelection(), true);
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { persistentSelection: false; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->persistentSelection(), false);
- }
-}
-
-void tst_qquicktextedit::focusOnPress()
-{
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
- QDeclarativeComponent 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\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->focusOnPress(), false);
- }
-}
-
-void tst_qquicktextedit::selection()
-{
- QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
-
-
- //Test selection follows cursor
- for (int i=0; i<= testStr.size(); i++) {
- textEditObject->setCursorPosition(i);
- QCOMPARE(textEditObject->cursorPosition(), i);
- QCOMPARE(textEditObject->selectionStart(), i);
- QCOMPARE(textEditObject->selectionEnd(), i);
- QVERIFY(textEditObject->selectedText().isNull());
- }
-
- textEditObject->setCursorPosition(0);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
- QVERIFY(textEditObject->selectedText().isNull());
-
- // Verify invalid positions are ignored.
- textEditObject->setCursorPosition(-1);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
- QVERIFY(textEditObject->selectedText().isNull());
-
- textEditObject->setCursorPosition(textEditObject->text().count()+1);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
- QVERIFY(textEditObject->selectedText().isNull());
-
- //Test selection
- for (int i=0; i<= testStr.size(); i++) {
- textEditObject->select(0,i);
- QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
- }
- for (int i=0; i<= testStr.size(); i++) {
- textEditObject->select(i,testStr.size());
- QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
- }
-
- textEditObject->setCursorPosition(0);
- QVERIFY(textEditObject->cursorPosition() == 0);
- QVERIFY(textEditObject->selectionStart() == 0);
- QVERIFY(textEditObject->selectionEnd() == 0);
- QVERIFY(textEditObject->selectedText().isNull());
-
- //Test Error Ignoring behaviour
- textEditObject->setCursorPosition(0);
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(-10,0);
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(100,101);
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(0,-10);
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(0,100);
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(0,10);
- QVERIFY(textEditObject->selectedText().size() == 10);
- textEditObject->select(-10,0);
- QVERIFY(textEditObject->selectedText().size() == 10);
- textEditObject->select(100,101);
- QVERIFY(textEditObject->selectedText().size() == 10);
- textEditObject->select(0,-10);
- QVERIFY(textEditObject->selectedText().size() == 10);
- textEditObject->select(0,100);
- QVERIFY(textEditObject->selectedText().size() == 10);
-
- textEditObject->deselect();
- QVERIFY(textEditObject->selectedText().isNull());
- textEditObject->select(0,10);
- QVERIFY(textEditObject->selectedText().size() == 10);
- textEditObject->deselect();
- QVERIFY(textEditObject->selectedText().isNull());
-}
-
-void tst_qquicktextedit::isRightToLeft_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<bool>("emptyString");
- QTest::addColumn<bool>("firstCharacter");
- QTest::addColumn<bool>("lastCharacter");
- QTest::addColumn<bool>("middleCharacter");
- QTest::addColumn<bool>("startString");
- QTest::addColumn<bool>("midString");
- QTest::addColumn<bool>("endString");
-
- const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
- QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
- QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
- QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
- QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
- QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
- QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
-}
-
-void tst_qquicktextedit::isRightToLeft()
-{
- QFETCH(QString, text);
- QFETCH(bool, emptyString);
- QFETCH(bool, firstCharacter);
- QFETCH(bool, lastCharacter);
- QFETCH(bool, middleCharacter);
- QFETCH(bool, startString);
- QFETCH(bool, midString);
- QFETCH(bool, endString);
-
- QQuickTextEdit textEdit;
- textEdit.setText(text);
-
- // first test that the right string is delivered to the QString::isRightToLeft()
- QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
- QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
- QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
- QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
- QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
- QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
- if (text.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
- QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
-
- // then test that the feature actually works
- QCOMPARE(textEdit.isRightToLeft(0,0), emptyString);
- QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter);
- QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
- QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
- QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString);
- QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString);
- if (text.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
- QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString);
-}
-
-void tst_qquicktextedit::keySelection()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
-
- QSignalSpy spy(input, SIGNAL(selectionChanged()));
-
- simulateKey(&canvas, Qt::Key_Right, Qt::ShiftModifier);
- QVERIFY(input->hasActiveFocus() == true);
- QCOMPARE(input->selectedText(), QString("a"));
- QCOMPARE(spy.count(), 1);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
- QCOMPARE(input->selectedText(), QString());
- QCOMPARE(spy.count(), 2);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
- QCOMPARE(input->selectedText(), QString());
- QCOMPARE(spy.count(), 2);
-
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
- QCOMPARE(spy.count(), 2);
- simulateKey(&canvas, Qt::Key_Left, Qt::ShiftModifier);
- QVERIFY(input->hasActiveFocus() == true);
- QCOMPARE(input->selectedText(), QString("a"));
- QCOMPARE(spy.count(), 3);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
- QCOMPARE(input->selectedText(), QString());
- QCOMPARE(spy.count(), 4);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
- QCOMPARE(input->selectedText(), QString());
- QCOMPARE(spy.count(), 4);
-}
-
-void tst_qquicktextedit::moveCursorSelection_data()
-{
- QTest::addColumn<QString>("testStr");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<int>("movePosition");
- QTest::addColumn<QQuickTextEdit::SelectionMode>("mode");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<bool>("reversible");
-
- QTest::newRow("(t)he|characters")
- << standard[0] << 0 << 1 << QQuickTextEdit::SelectCharacters << 0 << 1 << true;
- QTest::newRow("do(g)|characters")
- << standard[0] << 43 << 44 << QQuickTextEdit::SelectCharacters << 43 << 44 << true;
- QTest::newRow("jum(p)ed|characters")
- << standard[0] << 23 << 24 << QQuickTextEdit::SelectCharacters << 23 << 24 << true;
- QTest::newRow("jumped( )over|characters")
- << standard[0] << 26 << 27 << QQuickTextEdit::SelectCharacters << 26 << 27 << true;
- QTest::newRow("(the )|characters")
- << standard[0] << 0 << 4 << QQuickTextEdit::SelectCharacters << 0 << 4 << true;
- QTest::newRow("( dog)|characters")
- << standard[0] << 40 << 44 << QQuickTextEdit::SelectCharacters << 40 << 44 << true;
- QTest::newRow("( jumped )|characters")
- << standard[0] << 19 << 27 << QQuickTextEdit::SelectCharacters << 19 << 27 << true;
- QTest::newRow("th(e qu)ick|characters")
- << standard[0] << 2 << 6 << QQuickTextEdit::SelectCharacters << 2 << 6 << true;
- QTest::newRow("la(zy d)og|characters")
- << standard[0] << 38 << 42 << QQuickTextEdit::SelectCharacters << 38 << 42 << true;
- QTest::newRow("jum(ped ov)er|characters")
- << standard[0] << 23 << 29 << QQuickTextEdit::SelectCharacters << 23 << 29 << true;
- QTest::newRow("()the|characters")
- << standard[0] << 0 << 0 << QQuickTextEdit::SelectCharacters << 0 << 0 << true;
- QTest::newRow("dog()|characters")
- << standard[0] << 44 << 44 << QQuickTextEdit::SelectCharacters << 44 << 44 << true;
- QTest::newRow("jum()ped|characters")
- << standard[0] << 23 << 23 << QQuickTextEdit::SelectCharacters << 23 << 23 << true;
-
- QTest::newRow("<(t)he>|words")
- << standard[0] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 3 << true;
- QTest::newRow("<do(g)>|words")
- << standard[0] << 43 << 44 << QQuickTextEdit::SelectWords << 41 << 44 << true;
- QTest::newRow("<jum(p)ed>|words")
- << standard[0] << 23 << 24 << QQuickTextEdit::SelectWords << 20 << 26 << true;
- QTest::newRow("<jumped( )>over|words")
- << standard[0] << 26 << 27 << QQuickTextEdit::SelectWords << 20 << 27 << false;
- QTest::newRow("jumped<( )over>|words,reversed")
- << standard[0] << 27 << 26 << QQuickTextEdit::SelectWords << 26 << 31 << false;
- QTest::newRow("<(the )>quick|words")
- << standard[0] << 0 << 4 << QQuickTextEdit::SelectWords << 0 << 4 << false;
- QTest::newRow("<(the )quick>|words,reversed")
- << standard[0] << 4 << 0 << QQuickTextEdit::SelectWords << 0 << 9 << false;
- QTest::newRow("<lazy( dog)>|words")
- << standard[0] << 40 << 44 << QQuickTextEdit::SelectWords << 36 << 44 << false;
- QTest::newRow("lazy<( dog)>|words,reversed")
- << standard[0] << 44 << 40 << QQuickTextEdit::SelectWords << 40 << 44 << false;
- QTest::newRow("<fox( jumped )>over|words")
- << standard[0] << 19 << 27 << QQuickTextEdit::SelectWords << 16 << 27 << false;
- QTest::newRow("fox<( jumped )over>|words,reversed")
- << standard[0] << 27 << 19 << QQuickTextEdit::SelectWords << 19 << 31 << false;
- QTest::newRow("<th(e qu)ick>|words")
- << standard[0] << 2 << 6 << QQuickTextEdit::SelectWords << 0 << 9 << true;
- QTest::newRow("<la(zy d)og|words>")
- << standard[0] << 38 << 42 << QQuickTextEdit::SelectWords << 36 << 44 << true;
- QTest::newRow("<jum(ped ov)er>|words")
- << standard[0] << 23 << 29 << QQuickTextEdit::SelectWords << 20 << 31 << true;
- QTest::newRow("<()>the|words")
- << standard[0] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
- QTest::newRow("dog<()>|words")
- << standard[0] << 44 << 44 << QQuickTextEdit::SelectWords << 44 << 44 << true;
- QTest::newRow("jum<()>ped|words")
- << standard[0] << 23 << 23 << QQuickTextEdit::SelectWords << 23 << 23 << true;
-
- QTest::newRow("Hello<(,)> |words")
- << standard[2] << 5 << 6 << QQuickTextEdit::SelectWords << 5 << 6 << true;
- QTest::newRow("Hello<(, )>world|words")
- << standard[2] << 5 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
- QTest::newRow("Hello<(, )world>|words,reversed")
- << standard[2] << 7 << 5 << QQuickTextEdit::SelectWords << 5 << 12 << false;
- QTest::newRow("<Hel(lo, )>world|words")
- << standard[2] << 3 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
- QTest::newRow("<Hel(lo, )world>|words,reversed")
- << standard[2] << 7 << 3 << QQuickTextEdit::SelectWords << 0 << 12 << false;
- QTest::newRow("<Hel(lo)>,|words")
- << standard[2] << 3 << 5 << QQuickTextEdit::SelectWords << 0 << 5 << true;
- QTest::newRow("Hello<()>,|words")
- << standard[2] << 5 << 5 << QQuickTextEdit::SelectWords << 5 << 5 << true;
- QTest::newRow("Hello,<()>|words")
- << standard[2] << 6 << 6 << QQuickTextEdit::SelectWords << 6 << 6 << true;
- QTest::newRow("Hello<,( )>world|words")
- << standard[2] << 6 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
- QTest::newRow("Hello,<( )world>|words,reversed")
- << standard[2] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
- QTest::newRow("Hello<,( world)>|words")
- << standard[2] << 6 << 12 << QQuickTextEdit::SelectWords << 5 << 12 << false;
- QTest::newRow("Hello,<( world)>|words,reversed")
- << standard[2] << 12 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
- QTest::newRow("Hello<,( world!)>|words")
- << standard[2] << 6 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << false;
- QTest::newRow("Hello,<( world!)>|words,reversed")
- << standard[2] << 13 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
- QTest::newRow("Hello<(, world!)>|words")
- << standard[2] << 5 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << true;
- QTest::newRow("world<(!)>|words")
- << standard[2] << 12 << 13 << QQuickTextEdit::SelectWords << 12 << 13 << true;
- QTest::newRow("world!<()>)|words")
- << standard[2] << 13 << 13 << QQuickTextEdit::SelectWords << 13 << 13 << true;
- QTest::newRow("world<()>!)|words")
- << standard[2] << 12 << 12 << QQuickTextEdit::SelectWords << 12 << 12 << true;
-
- QTest::newRow("<(,)>olleH |words")
- << standard[3] << 7 << 8 << QQuickTextEdit::SelectWords << 7 << 8 << true;
- QTest::newRow("<dlrow( ,)>olleH|words")
- << standard[3] << 6 << 8 << QQuickTextEdit::SelectWords << 1 << 8 << false;
- QTest::newRow("dlrow<( ,)>olleH|words,reversed")
- << standard[3] << 8 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
- QTest::newRow("<dlrow( ,ol)leH>|words")
- << standard[3] << 6 << 10 << QQuickTextEdit::SelectWords << 1 << 13 << false;
- QTest::newRow("dlrow<( ,ol)leH>|words,reversed")
- << standard[3] << 10 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
- QTest::newRow(",<(ol)leH>,|words")
- << standard[3] << 8 << 10 << QQuickTextEdit::SelectWords << 8 << 13 << true;
- QTest::newRow(",<()>olleH|words")
- << standard[3] << 8 << 8 << QQuickTextEdit::SelectWords << 8 << 8 << true;
- QTest::newRow("<()>,olleH|words")
- << standard[3] << 7 << 7 << QQuickTextEdit::SelectWords << 7 << 7 << true;
- QTest::newRow("<dlrow( )>,olleH|words")
- << standard[3] << 6 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
- QTest::newRow("dlrow<( ),>olleH|words,reversed")
- << standard[3] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
- QTest::newRow("<(dlrow )>,olleH|words")
- << standard[3] << 1 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
- QTest::newRow("<(dlrow ),>olleH|words,reversed")
- << standard[3] << 7 << 1 << QQuickTextEdit::SelectWords << 1 << 8 << false;
- QTest::newRow("<(!dlrow )>,olleH|words")
- << standard[3] << 0 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
- QTest::newRow("<(!dlrow ),>olleH|words,reversed")
- << standard[3] << 7 << 0 << QQuickTextEdit::SelectWords << 0 << 8 << false;
- QTest::newRow("(!dlrow ,)olleH|words")
- << standard[3] << 0 << 8 << QQuickTextEdit::SelectWords << 0 << 8 << true;
- QTest::newRow("<(!)>dlrow|words")
- << standard[3] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 1 << true;
- QTest::newRow("<()>!dlrow|words")
- << standard[3] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
- QTest::newRow("!<()>dlrow|words")
- << standard[3] << 1 << 1 << QQuickTextEdit::SelectWords << 1 << 1 << true;
-}
-
-void tst_qquicktextedit::moveCursorSelection()
-{
- QFETCH(QString, testStr);
- QFETCH(int, cursorPosition);
- QFETCH(int, movePosition);
- QFETCH(QQuickTextEdit::SelectionMode, mode);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(bool, reversible);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(textinputComponent.create());
- QVERIFY(texteditObject != 0);
-
- texteditObject->setCursorPosition(cursorPosition);
- texteditObject->moveCursorSelection(movePosition, mode);
-
- QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
- QCOMPARE(texteditObject->selectionStart(), selectionStart);
- QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
-
- if (reversible) {
- texteditObject->setCursorPosition(movePosition);
- texteditObject->moveCursorSelection(cursorPosition, mode);
-
- QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
- QCOMPARE(texteditObject->selectionStart(), selectionStart);
- QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
- }
-}
-
-void tst_qquicktextedit::moveCursorSelectionSequence_data()
-{
- QTest::addColumn<QString>("testStr");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<int>("movePosition1");
- QTest::addColumn<int>("movePosition2");
- QTest::addColumn<int>("selection1Start");
- QTest::addColumn<int>("selection1End");
- QTest::addColumn<int>("selection2Start");
- QTest::addColumn<int>("selection2End");
-
- QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
- << standard[0]
- << 9 << 13 << 17
- << 4 << 15
- << 4 << 19;
- QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
- << standard[0]
- << 13 << 9 << 17
- << 9 << 15
- << 10 << 19;
- QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
- << standard[0]
- << 9 << 13 << 16
- << 4 << 15
- << 4 << 16;
- QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
- << standard[0]
- << 13 << 9 << 16
- << 9 << 15
- << 10 << 16;
- QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
- << standard[0]
- << 9 << 13 << 15
- << 4 << 15
- << 4 << 15;
- QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
- << standard[0]
- << 13 << 9 << 15
- << 9 << 15
- << 10 << 15;
- QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 10
- << 4 << 15
- << 4 << 10;
- QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl")
- << standard[0]
- << 13 << 9 << 10
- << 9 << 15
- << 10 << 15;
- QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 9
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
- << standard[0]
- << 13 << 9 << 9
- << 9 << 15
- << 9 << 15;
- QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 7
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 7
- << 9 << 15
- << 4 << 15;
- QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 4
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 4
- << 9 << 15
- << 4 << 15;
- QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 3
- << 4 << 15
- << 3 << 9;
- QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 3
- << 9 << 15
- << 3 << 15;
- QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 1
- << 4 << 15
- << 0 << 9;
- QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 1
- << 9 << 15
- << 0 << 15;
-
- QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
- << standard[2]
- << 2 << 4 << 8
- << 0 << 5
- << 0 << 12;
- QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
- << standard[2]
- << 4 << 2 << 8
- << 0 << 5
- << 0 << 12;
-
- QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
- << standard[3]
- << 9 << 11 << 5
- << 8 << 13
- << 1 << 13;
- QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
- << standard[3]
- << 11 << 9 << 5
- << 8 << 13
- << 1 << 13;
-}
-
-void tst_qquicktextedit::moveCursorSelectionSequence()
-{
- QFETCH(QString, testStr);
- QFETCH(int, cursorPosition);
- QFETCH(int, movePosition1);
- QFETCH(int, movePosition2);
- QFETCH(int, selection1Start);
- QFETCH(int, selection1End);
- QFETCH(int, selection2Start);
- QFETCH(int, selection2End);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
- QDeclarativeComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(texteditObject != 0);
-
- texteditObject->setCursorPosition(cursorPosition);
-
- texteditObject->moveCursorSelection(movePosition1, QQuickTextEdit::SelectWords);
- QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
- QCOMPARE(texteditObject->selectionStart(), selection1Start);
- QCOMPARE(texteditObject->selectionEnd(), selection1End);
-
- texteditObject->moveCursorSelection(movePosition2, QQuickTextEdit::SelectWords);
- QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
- QCOMPARE(texteditObject->selectionStart(), selection2Start);
- QCOMPARE(texteditObject->selectionEnd(), selection2End);
-}
-
-
-void tst_qquicktextedit::mouseSelection_data()
-{
- QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<int>("from");
- QTest::addColumn<int>("to");
- QTest::addColumn<QString>("selectedText");
-
- // import installed
- QTest::newRow("on") << TESTDATA("mouseselection_true.qml") << 4 << 9 << "45678";
- QTest::newRow("off") << TESTDATA("mouseselection_false.qml") << 4 << 9 << QString();
- QTest::newRow("default") << TESTDATA("mouseselection_default.qml") << 4 << 9 << QString();
- QTest::newRow("off word selection") << TESTDATA("mouseselection_false_words.qml") << 4 << 9 << QString();
- QTest::newRow("on word selection (4,9)") << TESTDATA("mouseselection_true_words.qml") << 4 << 9 << "0123456789";
- QTest::newRow("on word selection (2,13)") << TESTDATA("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (2,30)") << TESTDATA("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,13)") << TESTDATA("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,30)") << TESTDATA("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (13,2)") << TESTDATA("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (20,2)") << TESTDATA("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (12,9)") << TESTDATA("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (30,9)") << TESTDATA("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-}
-
-void tst_qquicktextedit::mouseSelection()
-{
- QFETCH(QString, qmlfile);
- QFETCH(int, from);
- QFETCH(int, to);
- QFETCH(QString, selectedText);
-
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
- QVERIFY(textEditObject != 0);
-
- // press-and-drag-and-release from x1 to x2
- QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
- QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
- QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
- QTest::mouseMove(&canvas, p2);
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
- QTest::qWait(50);
- QTRY_COMPARE(textEditObject->selectedText(), selectedText);
-
- // 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);
- QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
- QTest::qWait(50);
- QTRY_COMPARE(textEditObject->selectedText(), selectedText);
-}
-
-void tst_qquicktextedit::dragMouseSelection()
-{
- QString qmlfile = TESTDATA("mouseselection_true.qml");
-
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
- QVERIFY(textEditObject != 0);
-
- // press-and-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = textEditObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QTest::qWait(300);
- QString str1;
- QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
-
- // press and drag the current selection.
- x1 = 40;
- x2 = 100;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QTest::qWait(300);
- QString str2;
- QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
-
- QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and not the first moved.
-}
-
-void tst_qquicktextedit::mouseSelectionMode_data()
-{
- QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<bool>("selectWords");
-
- // import installed
- QTest::newRow("SelectWords") << TESTDATA("mouseselectionmode_words.qml") << true;
- QTest::newRow("SelectCharacters") << TESTDATA("mouseselectionmode_characters.qml") << false;
- QTest::newRow("default") << TESTDATA("mouseselectionmode_default.qml") << false;
-}
-
-void tst_qquicktextedit::mouseSelectionMode()
-{
- QFETCH(QString, qmlfile);
- QFETCH(bool, selectWords);
-
- QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
- QVERIFY(textEditObject != 0);
-
- // press-and-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = textEditObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
-// QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
-// QGuiApplication::sendEvent(&canvas, &mv);
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QString str = textEditObject->selectedText();
- if (selectWords) {
- QTRY_COMPARE(textEditObject->selectedText(), text);
- } else {
- QTRY_VERIFY(textEditObject->selectedText().length() > 3);
- QVERIFY(str != text);
- }
-}
-
-void tst_qquicktextedit::inputMethodHints()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("inputmethodhints.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
- QVERIFY(textEditObject != 0);
- QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
- textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
- QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
-}
-
-void tst_qquicktextedit::positionAt()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
- QVERIFY(canvas.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
- QVERIFY(texteditObject != 0);
-
- QFontMetrics fm(texteditObject->font());
- const int y0 = fm.height() / 2;
- const int y1 = fm.height() * 3 / 2;
-
- int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
- int widthBegin = 0;
- int widthEnd = 0;
- if (!qmlDisableDistanceField()) {
- QTextLayout layout(texteditObject->text());
-
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
-
- layout.beginLayout();
- QTextLine line = layout.createLine();
- layout.endLayout();
-
- widthBegin = floor(line.cursorToX(pos - 1));
- widthEnd = ceil(line.cursorToX(pos + 1));
- } else {
- widthBegin = fm.width(texteditObject->text().left(pos - 1));
- widthEnd = fm.width(texteditObject->text().left(pos + 1));
- }
-
- QVERIFY(widthBegin <= texteditObject->width() / 2);
- QVERIFY(widthEnd >= texteditObject->width() / 2);
-
- const qreal x0 = texteditObject->positionToRectangle(pos).x();
- const qreal x1 = texteditObject->positionToRectangle(pos + 1).x();
-
- QString preeditText = texteditObject->text().mid(0, pos);
- texteditObject->setText(texteditObject->text().mid(pos));
- texteditObject->setCursorPosition(0);
-
- QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent);
-
- // Check all points within the preedit text return the same position.
- QCOMPARE(texteditObject->positionAt(0, y0), 0);
- QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0);
- QCOMPARE(texteditObject->positionAt(x0, y0), 0);
-
- // Verify positioning returns to normal after the preedit text.
- QCOMPARE(texteditObject->positionAt(x1, y0), 1);
- QCOMPARE(texteditObject->positionToRectangle(1).x(), x1);
-
- QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0);
-}
-
-void tst_qquicktextedit::cursorDelegate()
-{
- QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorTest.qml")));
- view.show();
- view.requestActivateWindow();
- QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
- QVERIFY(textEditObject != 0);
- QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
- //Test Delegate gets created
- textEditObject->setFocus(true);
- QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance");
- QVERIFY(delegateObject);
- QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
- //Test Delegate gets moved
- for (int i=0; i<= textEditObject->text().length(); i++) {
- textEditObject->setCursorPosition(i);
- QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
- }
- // Clear preedit text;
- QInputMethodEvent event;
- QGuiApplication::sendEvent(&view, &event);
-
-
- // Test delegate gets moved on mouse press.
- textEditObject->setSelectByMouse(true);
- textEditObject->setCursorPosition(0);
- const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
- QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
- QTest::qWait(50);
- QTRY_VERIFY(textEditObject->cursorPosition() != 0);
- QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
-
- // Test delegate gets moved on mouse drag
- textEditObject->setCursorPosition(0);
- const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
- QTest::mousePress(&view, Qt::LeftButton, 0, point1);
- QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(&view, &mv);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
- QTest::qWait(50);
- QTRY_COMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
-
- textEditObject->setReadOnly(true);
- textEditObject->setCursorPosition(0);
- QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
- QTest::qWait(50);
- QTRY_VERIFY(textEditObject->cursorPosition() != 0);
- QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
-
- textEditObject->setCursorPosition(0);
- QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
- QTest::qWait(50);
- QTRY_VERIFY(textEditObject->cursorPosition() != 0);
- QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
-
- textEditObject->setCursorPosition(0);
- QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
- //Test Delegate gets deleted
- textEditObject->setCursorDelegate(0);
- QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
-}
-
-void tst_qquicktextedit::cursorVisible()
-{
- QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorVisible.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QQuickTextEdit edit;
- QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
-
- QCOMPARE(edit.isCursorVisible(), false);
-
- edit.setCursorVisible(true);
- QCOMPARE(edit.isCursorVisible(), true);
- QCOMPARE(spy.count(), 1);
-
- edit.setCursorVisible(false);
- QCOMPARE(edit.isCursorVisible(), false);
- QCOMPARE(spy.count(), 2);
-
- edit.setFocus(true);
- QCOMPARE(edit.isCursorVisible(), false);
- QCOMPARE(spy.count(), 2);
-
- edit.setParentItem(view.rootObject());
- QCOMPARE(edit.isCursorVisible(), true);
- QCOMPARE(spy.count(), 3);
-
- edit.setFocus(false);
- QCOMPARE(edit.isCursorVisible(), false);
- QCOMPARE(spy.count(), 4);
-
- edit.setFocus(true);
- QCOMPARE(edit.isCursorVisible(), true);
- QCOMPARE(spy.count(), 5);
-
- QQuickView alternateView;
- alternateView.show();
- alternateView.requestActivateWindow();
- QTest::qWaitForWindowShown(&alternateView);
-
- QCOMPARE(edit.isCursorVisible(), false);
- QCOMPARE(spy.count(), 6);
-
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QCOMPARE(edit.isCursorVisible(), true);
- QCOMPARE(spy.count(), 7);
-}
-
-void tst_qquicktextedit::delegateLoading_data()
-{
- QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<QString>("error");
-
- // import installed
- QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
- QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
- QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
-}
-
-void tst_qquicktextedit::delegateLoading()
-{
- QFETCH(QString, qmlfile);
- QFETCH(QString, error);
-
- TestHTTPServer server(42332);
- server.serveDirectory(TESTDATA("httpfail"), TestHTTPServer::Disconnect);
- server.serveDirectory(TESTDATA("httpslow"), TestHTTPServer::Delay);
- server.serveDirectory(TESTDATA("http"));
-
- QQuickView view(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
- view.show();
- view.requestActivateWindow();
-
- if (!error.isEmpty()) {
- QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
- QTRY_VERIFY(view.status()==QQuickView::Error);
- QTRY_VERIFY(!view.rootObject()); // there is fail item inside this test
- } else {
- QTRY_VERIFY(view.rootObject());//Wait for loading to finish.
- QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
- // view.rootObject()->dumpObjectTree();
- QVERIFY(textEditObject != 0);
- textEditObject->setFocus(true);
- QQuickItem *delegate;
- delegate = view.rootObject()->findChild<QQuickItem*>("delegateOkay");
- QVERIFY(delegate);
- delegate = view.rootObject()->findChild<QQuickItem*>("delegateSlow");
- QVERIFY(delegate);
-
- delete delegate;
- }
-
-
- //A test should be added here with a component which is ready but component.create() returns null
- //Not sure how to accomplish this with QQuickTextEdits cursor delegate
- //###This was only needed for code coverage, and could be a case of overzealous defensive programming
- //delegate = view.rootObject()->findChild<QQuickItem*>("delegateErrorB");
- //QVERIFY(!delegate);
-}
-
-/*
-TextEdit element should only handle left/right keys until the cursor reaches
-the extent of the text, then they should ignore the keys.
-*/
-void tst_qquicktextedit::navigation()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickItem *input = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
-}
-
-void tst_qquicktextedit::copyAndPaste() {
-#ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
- {
- PasteboardRef pasteboard;
- OSStatus status = PasteboardCreate(0, &pasteboard);
- if (status == noErr)
- CFRelease(pasteboard);
- else
- QSKIP("This machine doesn't support the clipboard");
- }
-#endif
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- // copy and paste
- QCOMPARE(textEdit->text().length(), 12);
- textEdit->select(0, textEdit->text().length());;
- textEdit->copy();
- QCOMPARE(textEdit->selectedText(), QString("Hello world!"));
- QCOMPARE(textEdit->selectedText().length(), 12);
- textEdit->setCursorPosition(0);
- QVERIFY(textEdit->canPaste());
- textEdit->paste();
- QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textEdit->text().length(), 24);
-
- // canPaste
- QVERIFY(textEdit->canPaste());
- textEdit->setReadOnly(true);
- QVERIFY(!textEdit->canPaste());
- textEdit->setReadOnly(false);
- QVERIFY(textEdit->canPaste());
-
- // QTBUG-12339
- // test that document and internal text attribute are in sync
- QQuickItemPrivate* pri = QQuickItemPrivate::get(textEdit);
- QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(pri);
- QCOMPARE(textEdit->text(), editPrivate->text);
-
- // select word
- textEdit->setCursorPosition(0);
- textEdit->selectWord();
- QCOMPARE(textEdit->selectedText(), QString("Hello"));
-
- // select all and cut
- textEdit->selectAll();
- textEdit->cut();
- QCOMPARE(textEdit->text().length(), 0);
- textEdit->paste();
- QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textEdit->text().length(), 24);
-#endif
-}
-
-void tst_qquicktextedit::canPaste() {
-#ifndef QT_NO_CLIPBOARD
-
- QGuiApplication::clipboard()->setText("Some text");
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- // check initial value - QTBUG-17765
- QTextControl tc;
- QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
-#endif
-}
-
-void tst_qquicktextedit::canPasteEmpty() {
-#ifndef QT_NO_CLIPBOARD
-
- QGuiApplication::clipboard()->clear();
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- // check initial value - QTBUG-17765
- QTextControl tc;
- QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
-#endif
-}
-
-void tst_qquicktextedit::readOnly()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("readOnly.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(edit != 0);
- QTRY_VERIFY(edit->hasActiveFocus() == true);
- QVERIFY(edit->isReadOnly() == true);
- QString initial = edit->text();
- for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
- simulateKey(&canvas, k);
- simulateKey(&canvas, Qt::Key_Return);
- simulateKey(&canvas, Qt::Key_Space);
- simulateKey(&canvas, Qt::Key_Escape);
- QCOMPARE(edit->text(), initial);
-
- edit->setCursorPosition(3);
- edit->setReadOnly(false);
- QCOMPARE(edit->isReadOnly(), false);
- QCOMPARE(edit->cursorPosition(), edit->text().length());
-}
-
-void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers)
-{
- QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
- QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
-
- QGuiApplication::sendEvent(view, &press);
- QGuiApplication::sendEvent(view, &release);
-}
-
-void tst_qquicktextedit::textInput()
-{
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
- QVERIFY(edit);
- QVERIFY(edit->hasActiveFocus() == true);
-
- // test that input method event is committed
- QInputMethodEvent event;
- event.setCommitString( "Hello world!", 0, 0);
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
- QCOMPARE(edit->text(), QString("Hello world!"));
-
- // QTBUG-12339
- // test that document and internal text attribute are in sync
- QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(edit));
- QCOMPARE(editPrivate->text, QString("Hello world!"));
-}
-
-class PlatformInputContext : public QPlatformInputContext
-{
-public:
- PlatformInputContext() : m_visible(false) {}
-
- virtual void showInputPanel()
- {
- m_visible = true;
- }
- virtual void hideInputPanel()
- {
- m_visible = false;
- }
- virtual bool isInputPanelVisible() const
- {
- return m_visible;
- }
-
- bool m_visible;
-};
-
-void tst_qquicktextedit::openInputPanel()
-{
- PlatformInputContext platformInputContext;
- QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
- inputPanelPrivate->testContext = &platformInputContext;
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("openInputPanel.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
- QVERIFY(edit);
-
- // check default values
- QVERIFY(edit->focusOnPress());
- QVERIFY(!edit->hasActiveFocus());
- qDebug() << &edit << qApp->inputPanel()->inputItem();
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
-
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should open on focus
- QPoint centerPoint(view.width()/2, view.height()/2);
- Qt::KeyboardModifiers noModifiers = 0;
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QVERIFY(edit->hasActiveFocus());
- QCOMPARE(qApp->inputPanel()->inputItem(), edit);
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
-
- // input panel should be re-opened when pressing already focused TextEdit
- qApp->inputPanel()->hide();
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QVERIFY(edit->hasActiveFocus());
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
-
- // input panel should stay visible if focus is lost to another text editor
- QSignalSpy inputPanelVisibilitySpy(qApp->inputPanel(), SIGNAL(visibleChanged()));
- QQuickTextEdit anotherEdit;
- anotherEdit.setParentItem(view.rootObject());
- anotherEdit.setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QCOMPARE(qApp->inputPanel()->inputItem(), qobject_cast<QObject*>(&anotherEdit));
- QCOMPARE(inputPanelVisibilitySpy.count(), 0);
-
- anotherEdit.setFocus(false);
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
- QCOMPARE(view.activeFocusItem(), view.rootItem());
- anotherEdit.setFocus(true);
-
- // input item should be null if focus is lost to an item that doesn't accept inputs
- QQuickItem item;
- item.setParentItem(view.rootObject());
- item.setFocus(true);
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
- QCOMPARE(view.activeFocusItem(), &item);
-
- qApp->inputPanel()->hide();
-
- // input panel should not be opened if TextEdit is read only
- edit->setReadOnly(true);
- edit->setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should not be opened if focusOnPress is set to false
- edit->setFocusOnPress(false);
- edit->setFocus(false);
- edit->setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should open when openSoftwareInputPanel is called
- edit->openSoftwareInputPanel();
- QCOMPARE(qApp->inputPanel()->visible(), true);
-
- // input panel should close when closeSoftwareInputPanel is called
- edit->closeSoftwareInputPanel();
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- inputPanelPrivate->testContext = 0;
-}
-
-void tst_qquicktextedit::geometrySignals()
-{
- QDeclarativeComponent component(&engine, TESTDATA("geometrySignals.qml"));
- QObject *o = component.create();
- QVERIFY(o);
- QCOMPARE(o->property("bindingWidth").toInt(), 400);
- QCOMPARE(o->property("bindingHeight").toInt(), 500);
- delete o;
-}
-
-void tst_qquicktextedit::pastingRichText_QTBUG_14003()
-{
-#ifndef QT_NO_CLIPBOARD
- QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.PlainText }";
- QDeclarativeComponent component(&engine);
- component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(component.create());
-
- QTRY_VERIFY(obj != 0);
- QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
-
- QMimeData *mData = new QMimeData;
- mData->setHtml("<font color=\"red\">Hello</font>");
- QGuiApplication::clipboard()->setMimeData(mData);
-
- obj->paste();
- QTRY_VERIFY(obj->text() == "");
- QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
-#endif
-}
-
-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";
-}
-
-void tst_qquicktextedit::implicitSize()
-{
- QFETCH(QString, text);
- QFETCH(QString, wrap);
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(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_qquicktextedit::testQtQuick11Attributes()
-{
- QFETCH(QString, code);
- QFETCH(QString, warning);
- QFETCH(QString, error);
-
- QDeclarativeEngine engine;
- QObject *obj;
-
- QDeclarativeComponent valid(&engine);
- valid.setData("import QtQuick 2.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
- obj = valid.create();
- QVERIFY(obj);
- QVERIFY(valid.errorString().isEmpty());
- delete obj;
-
- QDeclarativeComponent invalid(&engine);
- invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
- QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
- obj = invalid.create();
- QCOMPARE(invalid.errorString(), error);
- delete obj;
-}
-
-void tst_qquicktextedit::testQtQuick11Attributes_data()
-{
- QTest::addColumn<QString>("code");
- QTest::addColumn<QString>("warning");
- QTest::addColumn<QString>("error");
-
- QTest::newRow("canPaste") << "property bool foo: canPaste"
- << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
- << "";
-
- QTest::newRow("lineCount") << "property int foo: lineCount"
- << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount"
- << "";
-
- QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
- << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
- << "";
-
- QTest::newRow("deselect") << "Component.onCompleted: deselect()"
- << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
- << "";
-
- QTest::newRow("onLinkActivated") << "onLinkActivated: {}"
- << "QDeclarativeComponent: Component is not ready"
- << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n";
-}
-
-void tst_qquicktextedit::preeditCursorRectangle()
-{
- QString preeditText = "super";
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
-
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
- QVERIFY(edit);
-
- QSignalSpy editSpy(edit, SIGNAL(cursorRectangleChanged()));
- QSignalSpy panelSpy(qGuiApp->inputPanel(), SIGNAL(cursorRectangleChanged()));
-
- QRect currentRect;
-
- QInputMethodQueryEvent query(Qt::ImCursorRectangle);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
-
- // Verify that the micro focus rect is positioned the same for position 0 as
- // it would be if there was no preedit text.
- QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
- << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QCOMPARE(currentRect, previousRect);
- QCOMPARE(editSpy.count(), 0);
- QCOMPARE(panelSpy.count(), 0);
-
- // Verify that the micro focus rect moves to the left as the cursor position
- // is incremented.
- for (int i = 1; i <= 5; ++i) {
- QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
- << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QVERIFY(previousRect.left() < currentRect.left());
- QVERIFY(editSpy.count() > 0); editSpy.clear();
- QVERIFY(panelSpy.count() > 0); panelSpy.clear();
- previousRect = currentRect;
- }
-
- // Verify that if there is no preedit cursor then the micro focus rect is the
- // same as it would be if it were positioned at the end of the preedit text.
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- editSpy.clear();
- panelSpy.clear();
- { QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent); }
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QCOMPARE(currentRect, previousRect);
- QVERIFY(editSpy.count() > 0);
- QVERIFY(panelSpy.count() > 0);
-}
-
-void tst_qquicktextedit::inputMethodComposing()
-{
- QString text = "supercalifragisiticexpialidocious!";
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
- QVERIFY(edit);
- QSignalSpy spy(edit, SIGNAL(inputMethodComposingChanged()));
- edit->setCursorPosition(12);
-
- QCOMPARE(edit->isInputMethodComposing(), false);
-
- {
- QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(edit, &event);
- }
-
- QCOMPARE(edit->isInputMethodComposing(), true);
- QCOMPARE(spy.count(), 1);
-
- {
- QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(edit, &event);
- }
- QCOMPARE(spy.count(), 1);
-
- {
- QInputMethodEvent event;
- QGuiApplication::sendEvent(edit, &event);
- }
- QCOMPARE(edit->isInputMethodComposing(), false);
- QCOMPARE(spy.count(), 2);
-}
-
-void tst_qquicktextedit::cursorRectangleSize()
-{
- QQuickView *canvas = new QQuickView(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
- QVERIFY(canvas->rootObject() != 0);
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(canvas->rootObject());
-
- // make sure cursor rectangle is not at (0,0)
- textEdit->setX(10);
- textEdit->setY(10);
- textEdit->setCursorPosition(3);
- QVERIFY(textEdit != 0);
- textEdit->setFocus(true);
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
-
- QInputMethodQueryEvent event(Qt::ImCursorRectangle);
- qApp->sendEvent(qApp->inputPanel()->inputItem(), &event);
- QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
-
- QRect cursorRectFromItem = textEdit->cursorRectangle();
- QRectF cursorRectFromPositionToRectangle = textEdit->positionToRectangle(textEdit->cursorPosition());
-
- // item and input query cursor rectangles match
- QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
-
- // item cursor rectangle and positionToRectangle calculations match
- QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
-
- // item-canvas transform and input item transform match
- QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToCanvasTransform(), qApp->inputPanel()->inputItemTransform());
-
- // input panel cursorRectangle property and tranformed item cursor rectangle match
- QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToCanvasTransform().mapRect(cursorRectFromItem);
- QCOMPARE(sceneCursorRect, qApp->inputPanel()->cursorRectangle());
-
- delete canvas;
-}
-
-void tst_qquicktextedit::getText_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<int>("start");
- QTest::addColumn<int>("end");
- QTest::addColumn<QString>("expectedText");
-
- const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
- const QString plainBoldText = QStringLiteral("This is some bold text");
-
- QTest::newRow("all plain text")
- << standard.at(0)
- << 0 << standard.at(0).length()
- << standard.at(0);
-
- QTest::newRow("plain text sub string")
- << standard.at(0)
- << 0 << 12
- << standard.at(0).mid(0, 12);
-
- QTest::newRow("plain text sub string reversed")
- << standard.at(0)
- << 12 << 0
- << standard.at(0).mid(0, 12);
-
- QTest::newRow("plain text cropped beginning")
- << standard.at(0)
- << -3 << 4
- << standard.at(0).mid(0, 4);
-
- QTest::newRow("plain text cropped end")
- << standard.at(0)
- << 23 << standard.at(0).length() + 8
- << standard.at(0).mid(23);
-
- QTest::newRow("plain text cropped beginning and end")
- << standard.at(0)
- << -9 << standard.at(0).length() + 4
- << standard.at(0);
-
- QTest::newRow("all rich text")
- << richBoldText
- << 0 << plainBoldText.length()
- << plainBoldText;
-
- QTest::newRow("rich text sub string")
- << richBoldText
- << 14 << 21
- << plainBoldText.mid(14, 7);
-}
-
-void tst_qquicktextedit::getText()
-{
- QFETCH(QString, text);
- QFETCH(int, start);
- QFETCH(int, end);
- QFETCH(QString, expectedText);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- QCOMPARE(textEdit->getText(start, end), expectedText);
-}
-
-void tst_qquicktextedit::getFormattedText_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
- QTest::addColumn<int>("start");
- QTest::addColumn<int>("end");
- QTest::addColumn<QString>("expectedText");
-
- const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
- const QString plainBoldText = QStringLiteral("This is some bold text");
-
- QTest::newRow("all plain text")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << 0 << standard.at(0).length()
- << standard.at(0);
-
- QTest::newRow("plain text sub string")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << 0 << 12
- << standard.at(0).mid(0, 12);
-
- QTest::newRow("plain text sub string reversed")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << 12 << 0
- << standard.at(0).mid(0, 12);
-
- QTest::newRow("plain text cropped beginning")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << -3 << 4
- << standard.at(0).mid(0, 4);
-
- QTest::newRow("plain text cropped end")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << 23 << standard.at(0).length() + 8
- << standard.at(0).mid(23);
-
- QTest::newRow("plain text cropped beginning and end")
- << standard.at(0)
- << QQuickTextEdit::PlainText
- << -9 << standard.at(0).length() + 4
- << standard.at(0);
-
- QTest::newRow("all rich (Auto) text")
- << richBoldText
- << QQuickTextEdit::AutoText
- << 0 << plainBoldText.length()
- << QString("This is some \\<.*\\>bold\\</.*\\> text");
-
- QTest::newRow("all rich (Rich) text")
- << richBoldText
- << QQuickTextEdit::RichText
- << 0 << plainBoldText.length()
- << QString("This is some \\<.*\\>bold\\</.*\\> text");
-
- QTest::newRow("all rich (Plain) text")
- << richBoldText
- << QQuickTextEdit::PlainText
- << 0 << richBoldText.length()
- << richBoldText;
-
- QTest::newRow("rich (Auto) text sub string")
- << richBoldText
- << QQuickTextEdit::AutoText
- << 14 << 21
- << QString("\\<.*\\>old\\</.*\\> tex");
-
- QTest::newRow("rich (Rich) text sub string")
- << richBoldText
- << QQuickTextEdit::RichText
- << 14 << 21
- << QString("\\<.*\\>old\\</.*\\> tex");
-
- QTest::newRow("rich (Plain) text sub string")
- << richBoldText
- << QQuickTextEdit::PlainText
- << 17 << 27
- << richBoldText.mid(17, 10);
-}
-
-void tst_qquicktextedit::getFormattedText()
-{
- QFETCH(QString, text);
- QFETCH(QQuickTextEdit::TextFormat, textFormat);
- QFETCH(int, start);
- QFETCH(int, end);
- QFETCH(QString, expectedText);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit {}";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- textEdit->setTextFormat(textFormat);
- textEdit->setText(text);
-
- if (textFormat == QQuickTextEdit::RichText
- || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
- QVERIFY(textEdit->getFormattedText(start, end).contains(QRegExp(expectedText)));
- } else {
- QCOMPARE(textEdit->getFormattedText(start, end), expectedText);
- }
-}
-
-void tst_qquicktextedit::insert_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<int>("insertPosition");
- QTest::addColumn<QString>("insertText");
- QTest::addColumn<QString>("expectedText");
- QTest::addColumn<int>("expectedSelectionStart");
- QTest::addColumn<int>("expectedSelectionEnd");
- QTest::addColumn<int>("expectedCursorPosition");
- QTest::addColumn<bool>("selectionChanged");
- QTest::addColumn<bool>("cursorPositionChanged");
-
- QTest::newRow("at cursor position (beginning)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0 << 0
- << QString("Hello")
- << QString("Hello") + standard.at(0)
- << 5 << 5 << 5
- << false << true;
-
- QTest::newRow("at cursor position (end)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << standard.at(0).length() << standard.at(0).length() << standard.at(0).length()
- << QString("Hello")
- << standard.at(0) + QString("Hello")
- << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
- << false << true;
-
- QTest::newRow("at cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 18 << 18 << 18
- << QString("Hello")
- << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
- << 23 << 23 << 23
- << false << true;
-
- QTest::newRow("after cursor position (beginning)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0 << 18
- << QString("Hello")
- << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("before cursor position (end)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << standard.at(0).length() << standard.at(0).length() << 18
- << QString("Hello")
- << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
- << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
- << false << true;
-
- QTest::newRow("before cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 18 << 18 << 0
- << QString("Hello")
- << QString("Hello") + standard.at(0)
- << 23 << 23 << 23
- << false << true;
-
- QTest::newRow("after cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 18 << 18 << standard.at(0).length()
- << QString("Hello")
- << standard.at(0) + QString("Hello")
- << 18 << 18 << 18
- << false << false;
-
- QTest::newRow("before selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 19 << 0
- << QString("Hello")
- << QString("Hello") + standard.at(0)
- << 19 << 24 << 24
- << false << true;
-
- QTest::newRow("before reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 19 << 14 << 0
- << QString("Hello")
- << QString("Hello") + standard.at(0)
- << 19 << 24 << 19
- << false << true;
-
- QTest::newRow("after selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 19 << standard.at(0).length()
- << QString("Hello")
- << standard.at(0) + QString("Hello")
- << 14 << 19 << 19
- << false << false;
-
- QTest::newRow("after reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 19 << 14 << standard.at(0).length()
- << QString("Hello")
- << standard.at(0) + QString("Hello")
- << 14 << 19 << 14
- << false << false;
-
- QTest::newRow("into selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 19 << 18
- << QString("Hello")
- << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
- << 14 << 24 << 24
- << true << true;
-
- QTest::newRow("into reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 19 << 14 << 18
- << QString("Hello")
- << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
- << 14 << 24 << 14
- << true << false;
-
- QTest::newRow("rich text into plain text")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0 << 0
- << QString("<b>Hello</b>")
- << QString("<b>Hello</b>") + standard.at(0)
- << 12 << 12 << 12
- << false << true;
-
- QTest::newRow("rich text into rich text")
- << standard.at(0) << QQuickTextEdit::RichText
- << 0 << 0 << 0
- << QString("<b>Hello</b>")
- << QString("Hello") + standard.at(0)
- << 5 << 5 << 5
- << false << true;
-
- QTest::newRow("rich text into auto text")
- << standard.at(0) << QQuickTextEdit::AutoText
- << 0 << 0 << 0
- << QString("<b>Hello</b>")
- << QString("Hello") + standard.at(0)
- << 5 << 5 << 5
- << false << true;
-
- QTest::newRow("before start")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0 << -3
- << QString("Hello")
- << standard.at(0)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("past end")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0 << standard.at(0).length() + 3
- << QString("Hello")
- << standard.at(0)
- << 0 << 0 << 0
- << false << false;
-}
-
-void tst_qquicktextedit::insert()
-{
- QFETCH(QString, text);
- QFETCH(QQuickTextEdit::TextFormat, textFormat);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(int, insertPosition);
- QFETCH(QString, insertText);
- QFETCH(QString, expectedText);
- QFETCH(int, expectedSelectionStart);
- QFETCH(int, expectedSelectionEnd);
- QFETCH(int, expectedCursorPosition);
- QFETCH(bool, selectionChanged);
- QFETCH(bool, cursorPositionChanged);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- textEdit->setTextFormat(textFormat);
- textEdit->select(selectionStart, selectionEnd);
-
- QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
- QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
- QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
- QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString)));
- QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
-
- textEdit->insert(insertPosition, insertText);
-
- if (textFormat == QQuickTextEdit::RichText || (textFormat == QQuickTextEdit::AutoText && (
- Qt::mightBeRichText(text) || Qt::mightBeRichText(insertText)))) {
- QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
- } else {
- QCOMPARE(textEdit->text(), expectedText);
-
- }
- QCOMPARE(textEdit->length(), expectedText.length());
-
- QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
- QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
- QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
-
- if (selectionStart > selectionEnd)
- qSwap(selectionStart, selectionEnd);
-
- QEXPECT_FAIL("into selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("into reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QCOMPARE(selectionSpy.count() > 0, selectionChanged);
- QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
- QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
- QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
- QCOMPARE(textSpy.count() > 0, text != expectedText);
- QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
-}
-
-void tst_qquicktextedit::remove_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<int>("removeStart");
- QTest::addColumn<int>("removeEnd");
- QTest::addColumn<QString>("expectedText");
- QTest::addColumn<int>("expectedSelectionStart");
- QTest::addColumn<int>("expectedSelectionEnd");
- QTest::addColumn<int>("expectedCursorPosition");
- QTest::addColumn<bool>("selectionChanged");
- QTest::addColumn<bool>("cursorPositionChanged");
-
- const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
- const QString plainBoldText = QStringLiteral("This is some bold text");
-
- QTest::newRow("from cursor position (beginning)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << 0 << 5
- << standard.at(0).mid(5)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("to cursor position (beginning)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << 5 << 0
- << standard.at(0).mid(5)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("to cursor position (end)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << standard.at(0).length() << standard.at(0).length()
- << standard.at(0).length() << standard.at(0).length() - 5
- << standard.at(0).mid(0, standard.at(0).length() - 5)
- << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
- << false << true;
-
- QTest::newRow("to cursor position (end)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << standard.at(0).length() << standard.at(0).length()
- << standard.at(0).length() - 5 << standard.at(0).length()
- << standard.at(0).mid(0, standard.at(0).length() - 5)
- << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
- << false << true;
-
- QTest::newRow("from cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 18 << 18
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 18 << 18 << 18
- << false << false;
-
- QTest::newRow("to cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 23 << 23
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 18 << 18 << 18
- << false << true;
-
- QTest::newRow("after cursor position (beginning)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("before cursor position (end)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << standard.at(0).length() << standard.at(0).length()
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
- << false << true;
-
- QTest::newRow("before cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 23 << 23
- << 0 << 5
- << standard.at(0).mid(5)
- << 18 << 18 << 18
- << false << true;
-
- QTest::newRow("after cursor position (middle)")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 18 << 18
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 18 << 18 << 18
- << false << false;
-
- QTest::newRow("before selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 19
- << 0 << 5
- << standard.at(0).mid(5)
- << 9 << 14 << 14
- << false << true;
-
- QTest::newRow("before reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 19 << 14
- << 0 << 5
- << standard.at(0).mid(5)
- << 9 << 14 << 9
- << false << true;
-
- QTest::newRow("after selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 19
- << standard.at(0).length() - 5 << standard.at(0).length()
- << standard.at(0).mid(0, standard.at(0).length() - 5)
- << 14 << 19 << 19
- << false << false;
-
- QTest::newRow("after reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 19 << 14
- << standard.at(0).length() - 5 << standard.at(0).length()
- << standard.at(0).mid(0, standard.at(0).length() - 5)
- << 14 << 19 << 14
- << false << false;
-
- QTest::newRow("from selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 14 << 24
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 14 << 19 << 19
- << true << true;
-
- QTest::newRow("from reversed selection")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 24 << 14
- << 18 << 23
- << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
- << 14 << 19 << 14
- << true << false;
-
- QTest::newRow("plain text cropped beginning")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << -3 << 4
- << standard.at(0).mid(4)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("plain text cropped end")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << 23 << standard.at(0).length() + 8
- << standard.at(0).mid(0, 23)
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("plain text cropped beginning and end")
- << standard.at(0) << QQuickTextEdit::PlainText
- << 0 << 0
- << -9 << standard.at(0).length() + 4
- << QString()
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("all rich text")
- << richBoldText << QQuickTextEdit::RichText
- << 0 << 0
- << 0 << plainBoldText.length()
- << QString()
- << 0 << 0 << 0
- << false << false;
-
- QTest::newRow("rick text sub string")
- << richBoldText << QQuickTextEdit::RichText
- << 0 << 0
- << 14 << 21
- << plainBoldText.mid(0, 14) + plainBoldText.mid(21)
- << 0 << 0 << 0
- << false << false;
-}
-
-void tst_qquicktextedit::remove()
-{
- QFETCH(QString, text);
- QFETCH(QQuickTextEdit::TextFormat, textFormat);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(int, removeStart);
- QFETCH(int, removeEnd);
- QFETCH(QString, expectedText);
- QFETCH(int, expectedSelectionStart);
- QFETCH(int, expectedSelectionEnd);
- QFETCH(int, expectedCursorPosition);
- QFETCH(bool, selectionChanged);
- QFETCH(bool, cursorPositionChanged);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- textEdit->setTextFormat(textFormat);
- textEdit->select(selectionStart, selectionEnd);
-
- QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
- QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
- QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
- QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString)));
- QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
-
- textEdit->remove(removeStart, removeEnd);
-
- if (textFormat == QQuickTextEdit::RichText
- || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
- QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
- } else {
- QCOMPARE(textEdit->text(), expectedText);
- }
- QCOMPARE(textEdit->length(), expectedText.length());
-
- if (selectionStart > selectionEnd) //
- qSwap(selectionStart, selectionEnd);
-
- QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
- QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
- QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
-
- QEXPECT_FAIL("from selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("from reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QCOMPARE(selectionSpy.count() > 0, selectionChanged);
- QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
- QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
- QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
- QCOMPARE(textSpy.count() > 0, text != expectedText);
-
-
- if (cursorPositionChanged) //
- QVERIFY(cursorPositionSpy.count() > 0);
-}
-
-
-void tst_qquicktextedit::keySequence_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QKeySequence>("sequence");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<QString>("expectedText");
- QTest::addColumn<QString>("selectedText");
-
- // 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);
- QTest::newRow("select end of line")
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
- << 44 << standard.at(0) << standard.at(0).mid(5);
- QTest::newRow("select end of document")
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
- << 44 << standard.at(0) << standard.at(0).mid(3);
- QTest::newRow("select end of block")
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
- << 44 << standard.at(0) << standard.at(0).mid(18);
- QTest::newRow("delete end of line")
- << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
- << 24 << standard.at(0).mid(0, 24) << QString();
- QTest::newRow("move to start of line")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
- << 0 << standard.at(0) << QString();
- QTest::newRow("move to start of block")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
- << 0 << standard.at(0) << QString();
- 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")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
- << 2 << standard.at(0) << QString();
- QTest::newRow("select next char")
- << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
- << 24 << standard.at(0) << standard.at(0).mid(23, 1);
- QTest::newRow("select previous char")
- << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
- << 18 << standard.at(0) << standard.at(0).mid(18, 1);
- QTest::newRow("move to next word")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
- << 10 << standard.at(0) << QString();
- QTest::newRow("move to previous word")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
- << 4 << standard.at(0) << QString();
- QTest::newRow("select previous word")
- << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
- << 10 << standard.at(0) << standard.at(0).mid(10, 1);
- 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();
- 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();
- 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();
- 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();
-}
-
-void tst_qquicktextedit::keySequence()
-{
- QFETCH(QString, text);
- QFETCH(QKeySequence, sequence);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(int, cursorPosition);
- QFETCH(QString, expectedText);
- QFETCH(QString, selectedText);
-
- if (sequence.isEmpty()) {
- QSKIP("Key sequence is undefined");
- }
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; text: \"" + text + "\" }";
- QDeclarativeComponent textEditComponent(&engine);
- textEditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
-
- QQuickCanvas canvas;
- textEdit->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
-
- textEdit->select(selectionStart, selectionEnd);
-
- simulateKeys(&canvas, sequence);
-
- QCOMPARE(textEdit->cursorPosition(), cursorPosition);
- QCOMPARE(textEdit->text(), expectedText);
- QCOMPARE(textEdit->selectedText(), selectedText);
-}
-
-#define NORMAL 0
-#define REPLACE_UNTIL_END 1
-
-void tst_qquicktextedit::undo_data()
-{
- QTest::addColumn<QStringList>("insertString");
- QTest::addColumn<IntList>("insertIndex");
- QTest::addColumn<IntList>("insertMode");
- QTest::addColumn<QStringList>("expectedString");
- QTest::addColumn<bool>("use_keys");
-
- for (int i=0; i<2; i++) {
- QString keys_str = "keyboard";
- bool use_keys = true;
- if (i==0) {
- keys_str = "insert";
- use_keys = false;
- }
-
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "1";
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "5";
-
- insertIndex << 1;
- insertMode << NORMAL;
- insertString << "3";
-
- insertIndex << 1;
- insertMode << NORMAL;
- insertString << "2";
-
- insertIndex << 3;
- insertMode << NORMAL;
- insertString << "4";
-
- expectedString << "12345";
- expectedString << "1235";
- expectedString << "135";
- expectedString << "15";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "World"; // World
-
- insertIndex << 0;
- insertMode << NORMAL;
- insertString << "Hello"; // HelloWorld
-
- insertIndex << 0;
- insertMode << NORMAL;
- insertString << "Well"; // WellHelloWorld
-
- insertIndex << 9;
- insertMode << NORMAL;
- insertString << "There"; // WellHelloThereWorld;
-
- expectedString << "WellHelloThereWorld";
- expectedString << "WellHelloWorld";
- expectedString << "HelloWorld";
- expectedString << "World";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "Ensuring";
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << " instan";
-
- insertIndex << 9;
- insertMode << NORMAL;
- insertString << "an ";
-
- insertIndex << 10;
- insertMode << REPLACE_UNTIL_END;
- insertString << " unique instance.";
-
- expectedString << "Ensuring a unique instance.";
- expectedString << "Ensuring a "; // ### Not present in TextInput.
- expectedString << "Ensuring an instan";
- expectedString << "Ensuring instan";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- }
-}
-
-void tst_qquicktextedit::undo()
-{
- QFETCH(QStringList, insertString);
- QFETCH(IntList, insertIndex);
- QFETCH(IntList, insertMode);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- QQuickCanvas canvas;
- textInput->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
-
- int i;
-
-// STEP 1: First build up an undo history by inserting or typing some strings...
- for (i = 0; i < insertString.size(); ++i) {
- if (insertIndex[i] > -1)
- textInput->setCursorPosition(insertIndex[i]);
-
- // experimental stuff
- if (insertMode[i] == REPLACE_UNTIL_END) {
- textInput->select(insertIndex[i], insertIndex[i] + 8);
-
- // This is what I actually want...
- // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
- }
-
- for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
- }
-
-// STEP 2: Next call undo several times and see if we can restore to the previous state
- for (i = 0; i < expectedString.size() - 1; ++i) {
- QCOMPARE(textInput->text(), expectedString[i]);
- simulateKeys(&canvas, QKeySequence::Undo);
- }
-
-// STEP 3: Verify that we have undone everything
- QVERIFY(textInput->text().isEmpty());
-}
-
-void tst_qquicktextedit::redo_data()
-{
- QTest::addColumn<QStringList>("insertString");
- QTest::addColumn<IntList>("insertIndex");
- QTest::addColumn<QStringList>("expectedString");
-
- {
- IntList insertIndex;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertString << "World"; // World
- insertIndex << 0;
- insertString << "Hello"; // HelloWorld
- insertIndex << 0;
- insertString << "Well"; // WellHelloWorld
- insertIndex << 9;
- insertString << "There"; // WellHelloThereWorld;
-
- expectedString << "World";
- expectedString << "HelloWorld";
- expectedString << "WellHelloWorld";
- expectedString << "WellHelloThereWorld";
-
- QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
- }
-}
-
-void tst_qquicktextedit::redo()
-{
- QFETCH(QStringList, insertString);
- QFETCH(IntList, insertIndex);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- QQuickCanvas canvas;
- textInput->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
-
- int i;
- // inserts the diff strings at diff positions
- for (i = 0; i < insertString.size(); ++i) {
- if (insertIndex[i] > -1)
- textInput->setCursorPosition(insertIndex[i]);
- for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
- }
-
- // undo everything
- while (!textInput->text().isEmpty())
- simulateKeys(&canvas, QKeySequence::Undo);
-
- for (i = 0; i < expectedString.size(); ++i) {
- simulateKeys(&canvas, QKeySequence::Redo);
- QCOMPARE(textInput->text() , expectedString[i]);
- }
-}
-
-void tst_qquicktextedit::undo_keypressevents_data()
-{
- QTest::addColumn<KeyList>("keys");
- QTest::addColumn<QStringList>("expectedString");
-
- {
- KeyList keys;
- QStringList expectedString;
-
- keys << "AFRAID"
- << Qt::Key_Home
- << "VERY"
- << Qt::Key_Left
- << Qt::Key_Left
- << Qt::Key_Left
- << Qt::Key_Left
- << "BE"
- << Qt::Key_End
- << "!";
-
- expectedString << "BEVERYAFRAID!";
- expectedString << "BEVERYAFRAID";
- expectedString << "VERYAFRAID";
- expectedString << "AFRAID";
-
- QTest::newRow("Inserts and moving cursor") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting '1234'
- keys << "1234" << Qt::Key_Home
- // skipping '12'
- << Qt::Key_Right << Qt::Key_Right
- // selecting '34'
- << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
- // deleting '34'
- << Qt::Key_Delete;
-
- expectedString << "12";
- expectedString << "1234";
-
- QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'AB12'
- keys << "AB12"
- << Qt::Key_Home
- // selecting 'AB'
- << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
- << Qt::Key_Delete
- << QKeySequence::Undo
- // ### Text is selected in text input
-// << Qt::Key_Right
- << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
- << Qt::Key_Delete;
-
- expectedString << "AB";
- expectedString << "AB12";
-
- QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'ABCD'
- keys << "abcd"
- //move left two
- << Qt::Key_Left << Qt::Key_Left
- // inserting '1234'
- << "1234"
- // selecting '1234'
- << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
- // overwriting '1234' with '5'
- << "5"
- // undoing deletion of 'AB'
- << QKeySequence::Undo
- // ### Text is selected in text input
- << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
- // overwriting '1234' with '6'
- << "6";
-
- expectedString << "ab6cd";
- // for versions previous to 3.2 we overwrite needed two undo operations
- expectedString << "ab1234cd";
- expectedString << "abcd";
-
- QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'ABC'
- keys << "ABC"
- // removes 'C'
- << Qt::Key_Backspace;
-
- expectedString << "AB";
- expectedString << "ABC";
-
- QTest::newRow("Inserts,backspace") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- keys << "ABC"
- // removes 'C'
- << Qt::Key_Backspace
- // inserting 'Z'
- << "Z";
-
- expectedString << "ABZ";
- expectedString << "AB";
- expectedString << "ABC";
-
- QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting '123'
- keys << "123" << Qt::Key_Home
- // selecting '123'
- << (Qt::Key_End | Qt::ShiftModifier)
- // overwriting '123' with 'ABC'
- << "ABC";
-
- expectedString << "ABC";
- // ### One operation in TextInput.
- expectedString << "A";
- expectedString << "123";
-
- QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
- }
-}
-
-void tst_qquicktextedit::undo_keypressevents()
-{
- QFETCH(KeyList, keys);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(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);
-
- for (int i = 0; i < expectedString.size(); ++i) {
- QCOMPARE(textInput->text() , expectedString[i]);
- simulateKeys(&canvas, QKeySequence::Undo);
- }
- QVERIFY(textInput->text().isEmpty());
-}
-
-void tst_qquicktextedit::emptytags_QTBUG_22058()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("qtbug-22058.qml")));
- QVERIFY(canvas.rootObject() != 0);
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("inputField")));
- QVERIFY(input->hasActiveFocus());
-
- QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());
- event.setCommitString("<b>Bold<");
- QGuiApplication::sendEvent(input, &event);
- QCOMPARE(input->text(), QString("<b>Bold<"));
- event.setCommitString(">");
- QEXPECT_FAIL("", "Entering empty tags into a TextEdit asserts - QTBUG-22058", Abort);
- QVERIFY(false);
- QGuiApplication::sendEvent(input, &event);
- QCOMPARE(input->text(), QString("<b>Bold<>"));
-}
-
-QTEST_MAIN(tst_qquicktextedit)
-
-#include "tst_qquicktextedit.moc"
diff --git a/tests/auto/declarative/qquicktextinput/qquicktextinput.pro b/tests/auto/declarative/qquicktextinput/qquicktextinput.pro
deleted file mode 100644
index 9c74559cb2..0000000000
--- a/tests/auto/declarative/qquicktextinput/qquicktextinput.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquicktextinput
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquicktextinput.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
diff --git a/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp
deleted file mode 100644
index a6a9add5d5..0000000000
--- a/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp
+++ /dev/null
@@ -1,3310 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include "../shared/util.h"
-#include <private/qinputpanel_p.h>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QFile>
-#include <QtDeclarative/qquickview.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qstylehints.h>
-#include <QInputPanel>
-#include <private/qquicktextinput_p.h>
-#include <private/qquicktextinput_p_p.h>
-#include <QDebug>
-#include <QDir>
-#include <QStyle>
-#include <QtOpenGL/QGLShaderProgram>
-#include <math.h>
-#include <qplatforminputcontext_qpa.h>
-#include <private/qinputpanel_p.h>
-
-#ifdef Q_OS_MAC
-#include <Carbon/Carbon.h>
-#endif
-
-#include "qplatformdefs.h"
-
-Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode)
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
-QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
-{
- // XXX This will be replaced by some clever persistent platform image store.
- QString persistent_dir = TESTDATA("");
- QString arch = "unknown-architecture"; // QTest needs to help with this.
-
- QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
-
- if (!QFile::exists(expectfile)) {
- actual.save(expectfile);
- qWarning() << "created" << expectfile;
- }
-
- return expectfile;
-}
-
-typedef QPair<int, QChar> Key;
-
-class tst_qquicktextinput : public QObject
-
-{
- Q_OBJECT
-public:
- tst_qquicktextinput();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void cleanup();
- void text();
- void width();
- void font();
- void color();
- void selection();
- void isRightToLeft_data();
- void isRightToLeft();
- void moveCursorSelection_data();
- void moveCursorSelection();
- void moveCursorSelectionSequence_data();
- void moveCursorSelectionSequence();
- void dragMouseSelection();
- void mouseSelectionMode_data();
- void mouseSelectionMode();
- void tripleClickSelectsAll();
-
- void horizontalAlignment_data();
- void horizontalAlignment();
- void horizontalAlignment_RightToLeft();
-
- void positionAt();
-
- void maxLength();
- void masks();
- void validators();
- void inputMethods();
-
- void passwordCharacter();
- void cursorDelegate();
- void cursorVisible();
- void cursorRectangle();
- void navigation();
- void navigation_RTL();
- void copyAndPaste();
- void copyAndPasteKeySequence();
- void canPasteEmpty();
- void canPaste();
- void readOnly();
-
- void openInputPanel();
- void setHAlignClearCache();
- void focusOutClearSelection();
-
- void echoMode();
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
- void passwordEchoDelay();
-#endif
- void geometrySignals();
- void testQtQuick11Attributes();
- void testQtQuick11Attributes_data();
-
- void preeditAutoScroll();
- void preeditCursorRectangle();
- void inputContextMouseHandler();
- void inputMethodComposing();
- void cursorRectangleSize();
-
- void keySequence_data();
- void keySequence();
-
- void undo_data();
- void undo();
- void redo_data();
- void redo();
- void undo_keypressevents_data();
- void undo_keypressevents();
-
- void QTBUG_19956();
- void QTBUG_19956_data();
- void QTBUG_19956_regexp();
-
-private:
- void simulateKey(QQuickView *, int key);
-
- void simulateKeys(QWindow *window, const QList<Key> &keys);
- void simulateKeys(QWindow *window, const QKeySequence &sequence);
-
- QDeclarativeEngine engine;
- QStringList standard;
- QStringList colorStrings;
-};
-
-typedef QList<int> IntList;
-Q_DECLARE_METATYPE(IntList)
-
-typedef QList<Key> KeyList;
-Q_DECLARE_METATYPE(KeyList)
-
-void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
-{
- for (int i = 0; i < keys.count(); ++i) {
- const int key = keys.at(i).first;
- const int modifiers = key & Qt::KeyboardModifierMask;
- const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
-
- QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
- QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
-
- QGuiApplication::sendEvent(window, &press);
- QGuiApplication::sendEvent(window, &release);
- }
-}
-
-void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
-{
- for (uint i = 0; i < sequence.count(); ++i) {
- const int key = sequence[i];
- const int modifiers = key & Qt::KeyboardModifierMask;
-
- QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
- }
-}
-
-QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
-{
- for (uint i = 0; i < sequence.count(); ++i)
- keys << Key(sequence[i], QChar());
- return keys;
-}
-
-template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
-{
- for (int i = 0; i < N - 1; ++i) {
- int key = QTest::asciiToKey(characters[i]);
- QChar character = QLatin1Char(characters[i]);
- keys << Key(key, character);
- }
- return keys;
-}
-
-QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
-{
- keys << Key(key, QChar());
- return keys;
-}
-
-void tst_qquicktextinput::initTestCase()
-{
-}
-
-void tst_qquicktextinput::cleanupTestCase()
-{
-}
-
-void tst_qquicktextinput::cleanup()
-{
- // ensure not even skipped tests with custom input context leave it dangling
- QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
- inputPanelPrivate->testContext = 0;
-}
-
-tst_qquicktextinput::tst_qquicktextinput()
-{
- standard << "the quick brown fox jumped over the lazy dog"
- << "It's supercalifragisiticexpialidocious!"
- << "Hello, world!"
- << "!dlrow ,olleH"
- << " spacey text ";
-
- colorStrings << "aliceblue"
- << "antiquewhite"
- << "aqua"
- << "darkkhaki"
- << "darkolivegreen"
- << "dimgray"
- << "palevioletred"
- << "lightsteelblue"
- << "#000000"
- << "#AAAAAA"
- << "#FFFFFF"
- << "#2AC05F";
-}
-
-void tst_qquicktextinput::text()
-{
- {
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->text(), QString(""));
-
- delete textinputObject;
- }
-
- for (int i = 0; i < standard.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->text(), standard.at(i));
-
- delete textinputObject;
- }
-
-}
-
-void tst_qquicktextinput::width()
-{
- // uses Font metrics to find the width for standard
- {
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->width(), 0.0);
-
- delete textinputObject;
- }
-
- bool requiresUnhintedMetrics = !qmlDisableDistanceField();
-
- for (int i = 0; i < standard.size(); i++)
- {
- QFont f;
- qreal metricWidth = 0.0;
- if (requiresUnhintedMetrics) {
- QString s = standard.at(i);
- s.replace(QLatin1Char('\n'), QChar::LineSeparator);
-
- QTextLayout layout(s);
- layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
- {
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
- }
-
- layout.beginLayout();
- forever {
- QTextLine line = layout.createLine();
- if (!line.isValid())
- break;
- }
-
- layout.endLayout();
-
- metricWidth = ceil(layout.boundingRect().width());
- } else {
- QFontMetricsF fm(f);
- metricWidth = fm.width(standard.at(i));
- }
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- int delta = abs(int(int(textinputObject->width()) - metricWidth));
- QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
-
- delete textinputObject;
- }
-}
-
-void tst_qquicktextinput::font()
-{
- //test size, then bold, then italic, then family
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->font().pointSize(), 40);
- QCOMPARE(textinputObject->font().bold(), false);
- QCOMPARE(textinputObject->font().italic(), false);
-
- delete textinputObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { font.bold: true; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->font().bold(), true);
- QCOMPARE(textinputObject->font().italic(), false);
-
- delete textinputObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { font.italic: true; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->font().italic(), true);
- QCOMPARE(textinputObject->font().bold(), false);
-
- delete textinputObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
- QCOMPARE(textinputObject->font().bold(), false);
- QCOMPARE(textinputObject->font().italic(), false);
-
- delete textinputObject;
- }
-
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->font().family(), QString(""));
-
- delete textinputObject;
- }
-}
-
-void tst_qquicktextinput::color()
-{
- //test color
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
-
- delete textinputObject;
- }
-
- //test selection color
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
-
- delete textinputObject;
- }
-
- //test selected text color
- for (int i = 0; i < colorStrings.size(); i++)
- {
- QString componentStr = "import QtQuick 2.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
-
- delete textinputObject;
- }
-
- {
- QString colorStr = "#AA001234";
- QColor testColor("#001234");
- testColor.setAlpha(170);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
-
- QVERIFY(textinputObject != 0);
- QCOMPARE(textinputObject->color(), testColor);
-
- delete textinputObject;
- }
-}
-
-void tst_qquicktextinput::selection()
-{
- QString testStr = standard[0];
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
-
-
- //Test selection follows cursor
- for (int i=0; i<= testStr.size(); i++) {
- textinputObject->setCursorPosition(i);
- QCOMPARE(textinputObject->cursorPosition(), i);
- QCOMPARE(textinputObject->selectionStart(), i);
- QCOMPARE(textinputObject->selectionEnd(), i);
- QVERIFY(textinputObject->selectedText().isNull());
- }
-
- textinputObject->setCursorPosition(0);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
- QVERIFY(textinputObject->selectedText().isNull());
-
- // Verify invalid positions are ignored.
- textinputObject->setCursorPosition(-1);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
- QVERIFY(textinputObject->selectedText().isNull());
-
- textinputObject->setCursorPosition(textinputObject->text().count()+1);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
- QVERIFY(textinputObject->selectedText().isNull());
-
- //Test selection
- for (int i=0; i<= testStr.size(); i++) {
- textinputObject->select(0,i);
- QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
- }
- for (int i=0; i<= testStr.size(); i++) {
- textinputObject->select(i,testStr.size());
- QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
- }
-
- textinputObject->setCursorPosition(0);
- QVERIFY(textinputObject->cursorPosition() == 0);
- QVERIFY(textinputObject->selectionStart() == 0);
- QVERIFY(textinputObject->selectionEnd() == 0);
- QVERIFY(textinputObject->selectedText().isNull());
-
- //Test Error Ignoring behaviour
- textinputObject->setCursorPosition(0);
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(-10,0);
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(100,110);
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(0,-10);
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(0,100);
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(0,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
- textinputObject->select(-10,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
- textinputObject->select(100,101);
- QVERIFY(textinputObject->selectedText().size() == 10);
- textinputObject->select(0,-10);
- QVERIFY(textinputObject->selectedText().size() == 10);
- textinputObject->select(0,100);
- QVERIFY(textinputObject->selectedText().size() == 10);
-
- textinputObject->deselect();
- QVERIFY(textinputObject->selectedText().isNull());
- textinputObject->select(0,10);
- QVERIFY(textinputObject->selectedText().size() == 10);
- textinputObject->deselect();
- QVERIFY(textinputObject->selectedText().isNull());
-
- // test input method selection
- QSignalSpy selectionSpy(textinputObject, SIGNAL(selectedTextChanged()));
- textinputObject->setFocus(true);
- {
- QList<QInputMethodEvent::Attribute> attributes;
- attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
- QInputMethodEvent event("", attributes);
- QApplication::sendEvent(textinputObject, &event);
- }
- QCOMPARE(selectionSpy.count(), 1);
- QCOMPARE(textinputObject->selectionStart(), 12);
- QCOMPARE(textinputObject->selectionEnd(), 17);
-
- delete textinputObject;
-}
-
-void tst_qquicktextinput::isRightToLeft_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<bool>("emptyString");
- QTest::addColumn<bool>("firstCharacter");
- QTest::addColumn<bool>("lastCharacter");
- QTest::addColumn<bool>("middleCharacter");
- QTest::addColumn<bool>("startString");
- QTest::addColumn<bool>("midString");
- QTest::addColumn<bool>("endString");
-
- const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
- QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
- QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
- QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
- QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
- QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
- QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
-}
-
-void tst_qquicktextinput::isRightToLeft()
-{
- QFETCH(QString, text);
- QFETCH(bool, emptyString);
- QFETCH(bool, firstCharacter);
- QFETCH(bool, lastCharacter);
- QFETCH(bool, middleCharacter);
- QFETCH(bool, startString);
- QFETCH(bool, midString);
- QFETCH(bool, endString);
-
- QQuickTextInput textInput;
- textInput.setText(text);
-
- // first test that the right string is delivered to the QString::isRightToLeft()
- QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
- QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
- QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
- QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
- QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
- QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
- if (text.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
- QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
-
- // then test that the feature actually works
- QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
- QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
- QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
- QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
- QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
- QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
- if (text.isEmpty())
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
- QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
-}
-
-void tst_qquicktextinput::moveCursorSelection_data()
-{
- QTest::addColumn<QString>("testStr");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<int>("movePosition");
- QTest::addColumn<QQuickTextInput::SelectionMode>("mode");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<bool>("reversible");
-
- // () contains the text selected by the cursor.
- // <> contains the actual selection.
-
- QTest::newRow("(t)he|characters")
- << standard[0] << 0 << 1 << QQuickTextInput::SelectCharacters << 0 << 1 << true;
- QTest::newRow("do(g)|characters")
- << standard[0] << 43 << 44 << QQuickTextInput::SelectCharacters << 43 << 44 << true;
- QTest::newRow("jum(p)ed|characters")
- << standard[0] << 23 << 24 << QQuickTextInput::SelectCharacters << 23 << 24 << true;
- QTest::newRow("jumped( )over|characters")
- << standard[0] << 26 << 27 << QQuickTextInput::SelectCharacters << 26 << 27 << true;
- QTest::newRow("(the )|characters")
- << standard[0] << 0 << 4 << QQuickTextInput::SelectCharacters << 0 << 4 << true;
- QTest::newRow("( dog)|characters")
- << standard[0] << 40 << 44 << QQuickTextInput::SelectCharacters << 40 << 44 << true;
- QTest::newRow("( jumped )|characters")
- << standard[0] << 19 << 27 << QQuickTextInput::SelectCharacters << 19 << 27 << true;
- QTest::newRow("th(e qu)ick|characters")
- << standard[0] << 2 << 6 << QQuickTextInput::SelectCharacters << 2 << 6 << true;
- QTest::newRow("la(zy d)og|characters")
- << standard[0] << 38 << 42 << QQuickTextInput::SelectCharacters << 38 << 42 << true;
- QTest::newRow("jum(ped ov)er|characters")
- << standard[0] << 23 << 29 << QQuickTextInput::SelectCharacters << 23 << 29 << true;
- QTest::newRow("()the|characters")
- << standard[0] << 0 << 0 << QQuickTextInput::SelectCharacters << 0 << 0 << true;
- QTest::newRow("dog()|characters")
- << standard[0] << 44 << 44 << QQuickTextInput::SelectCharacters << 44 << 44 << true;
- QTest::newRow("jum()ped|characters")
- << standard[0] << 23 << 23 << QQuickTextInput::SelectCharacters << 23 << 23 << true;
-
- QTest::newRow("<(t)he>|words")
- << standard[0] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 3 << true;
- QTest::newRow("<do(g)>|words")
- << standard[0] << 43 << 44 << QQuickTextInput::SelectWords << 41 << 44 << true;
- QTest::newRow("<jum(p)ed>|words")
- << standard[0] << 23 << 24 << QQuickTextInput::SelectWords << 20 << 26 << true;
- QTest::newRow("<jumped( )>over|words,ltr")
- << standard[0] << 26 << 27 << QQuickTextInput::SelectWords << 20 << 27 << false;
- QTest::newRow("jumped<( )over>|words,rtl")
- << standard[0] << 27 << 26 << QQuickTextInput::SelectWords << 26 << 31 << false;
- QTest::newRow("<(the )>quick|words,ltr")
- << standard[0] << 0 << 4 << QQuickTextInput::SelectWords << 0 << 4 << false;
- QTest::newRow("<(the )quick>|words,rtl")
- << standard[0] << 4 << 0 << QQuickTextInput::SelectWords << 0 << 9 << false;
- QTest::newRow("<lazy( dog)>|words,ltr")
- << standard[0] << 40 << 44 << QQuickTextInput::SelectWords << 36 << 44 << false;
- QTest::newRow("lazy<( dog)>|words,rtl")
- << standard[0] << 44 << 40 << QQuickTextInput::SelectWords << 40 << 44 << false;
- QTest::newRow("<fox( jumped )>over|words,ltr")
- << standard[0] << 19 << 27 << QQuickTextInput::SelectWords << 16 << 27 << false;
- QTest::newRow("fox<( jumped )over>|words,rtl")
- << standard[0] << 27 << 19 << QQuickTextInput::SelectWords << 19 << 31 << false;
- QTest::newRow("<th(e qu)ick>|words")
- << standard[0] << 2 << 6 << QQuickTextInput::SelectWords << 0 << 9 << true;
- QTest::newRow("<la(zy d)og|words>")
- << standard[0] << 38 << 42 << QQuickTextInput::SelectWords << 36 << 44 << true;
- QTest::newRow("<jum(ped ov)er>|words")
- << standard[0] << 23 << 29 << QQuickTextInput::SelectWords << 20 << 31 << true;
- QTest::newRow("<()>the|words")
- << standard[0] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
- QTest::newRow("dog<()>|words")
- << standard[0] << 44 << 44 << QQuickTextInput::SelectWords << 44 << 44 << true;
- QTest::newRow("jum<()>ped|words")
- << standard[0] << 23 << 23 << QQuickTextInput::SelectWords << 23 << 23 << true;
-
- QTest::newRow("Hello<(,)> |words")
- << standard[2] << 5 << 6 << QQuickTextInput::SelectWords << 5 << 6 << true;
- QTest::newRow("Hello<(, )>world|words,ltr")
- << standard[2] << 5 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
- QTest::newRow("Hello<(, )world>|words,rtl")
- << standard[2] << 7 << 5 << QQuickTextInput::SelectWords << 5 << 12 << false;
- QTest::newRow("<Hel(lo, )>world|words,ltr")
- << standard[2] << 3 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
- QTest::newRow("<Hel(lo, )world>|words,rtl")
- << standard[2] << 7 << 3 << QQuickTextInput::SelectWords << 0 << 12 << false;
- QTest::newRow("<Hel(lo)>,|words")
- << standard[2] << 3 << 5 << QQuickTextInput::SelectWords << 0 << 5 << true;
- QTest::newRow("Hello<()>,|words")
- << standard[2] << 5 << 5 << QQuickTextInput::SelectWords << 5 << 5 << true;
- QTest::newRow("Hello,<()>|words")
- << standard[2] << 6 << 6 << QQuickTextInput::SelectWords << 6 << 6 << true;
- QTest::newRow("Hello<,( )>world|words,ltr")
- << standard[2] << 6 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
- QTest::newRow("Hello,<( )world>|words,rtl")
- << standard[2] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
- QTest::newRow("Hello<,( world)>|words,ltr")
- << standard[2] << 6 << 12 << QQuickTextInput::SelectWords << 5 << 12 << false;
- QTest::newRow("Hello,<( world)>|words,rtl")
- << standard[2] << 12 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
- QTest::newRow("Hello<,( world!)>|words,ltr")
- << standard[2] << 6 << 13 << QQuickTextInput::SelectWords << 5 << 13 << false;
- QTest::newRow("Hello,<( world!)>|words,rtl")
- << standard[2] << 13 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
- QTest::newRow("Hello<(, world!)>|words")
- << standard[2] << 5 << 13 << QQuickTextInput::SelectWords << 5 << 13 << true;
- // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings.
- // QTBUG-11365
- // QTest::newRow("world<(!)>|words")
- // << standard[2] << 12 << 13 << QQuickTextInput::SelectWords << 12 << 13 << true;
- QTest::newRow("world!<()>)|words")
- << standard[2] << 13 << 13 << QQuickTextInput::SelectWords << 13 << 13 << true;
- QTest::newRow("world<()>!)|words")
- << standard[2] << 12 << 12 << QQuickTextInput::SelectWords << 12 << 12 << true;
-
- QTest::newRow("<(,)>olleH |words")
- << standard[3] << 7 << 8 << QQuickTextInput::SelectWords << 7 << 8 << true;
- QTest::newRow("<dlrow( ,)>olleH|words,ltr")
- << standard[3] << 6 << 8 << QQuickTextInput::SelectWords << 1 << 8 << false;
- QTest::newRow("dlrow<( ,)>olleH|words,rtl")
- << standard[3] << 8 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
- QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
- << standard[3] << 6 << 10 << QQuickTextInput::SelectWords << 1 << 13 << false;
- QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
- << standard[3] << 10 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
- QTest::newRow(",<(ol)leH>,|words")
- << standard[3] << 8 << 10 << QQuickTextInput::SelectWords << 8 << 13 << true;
- QTest::newRow(",<()>olleH|words")
- << standard[3] << 8 << 8 << QQuickTextInput::SelectWords << 8 << 8 << true;
- QTest::newRow("<()>,olleH|words")
- << standard[3] << 7 << 7 << QQuickTextInput::SelectWords << 7 << 7 << true;
- QTest::newRow("<dlrow( )>,olleH|words,ltr")
- << standard[3] << 6 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
- QTest::newRow("dlrow<( ),>olleH|words,rtl")
- << standard[3] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
- QTest::newRow("<(dlrow )>,olleH|words,ltr")
- << standard[3] << 1 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
- QTest::newRow("<(dlrow ),>olleH|words,rtl")
- << standard[3] << 7 << 1 << QQuickTextInput::SelectWords << 1 << 8 << false;
- QTest::newRow("<(!dlrow )>,olleH|words,ltr")
- << standard[3] << 0 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
- QTest::newRow("<(!dlrow ),>olleH|words,rtl")
- << standard[3] << 7 << 0 << QQuickTextInput::SelectWords << 0 << 8 << false;
- QTest::newRow("(!dlrow ,)olleH|words")
- << standard[3] << 0 << 8 << QQuickTextInput::SelectWords << 0 << 8 << true;
- QTest::newRow("<(!)>dlrow|words")
- << standard[3] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << true;
- QTest::newRow("<()>!dlrow|words")
- << standard[3] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
- QTest::newRow("!<()>dlrow|words")
- << standard[3] << 1 << 1 << QQuickTextInput::SelectWords << 1 << 1 << true;
-
- QTest::newRow(" <s(pac)ey> text |words")
- << standard[4] << 1 << 4 << QQuickTextInput::SelectWords << 1 << 7 << true;
- QTest::newRow(" spacey <t(ex)t> |words")
- << standard[4] << 11 << 13 << QQuickTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365
- QTest::newRow("<( )>spacey text |words|ltr")
- << standard[4] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << false;
- QTest::newRow("<( )spacey> text |words|rtl")
- << standard[4] << 1 << 0 << QQuickTextInput::SelectWords << 0 << 7 << false;
- QTest::newRow("spacey <text( )>|words|ltr")
- << standard[4] << 14 << 15 << QQuickTextInput::SelectWords << 10 << 15 << false;
-// QTBUG-11365
-// QTest::newRow("spacey text<( )>|words|rtl")
-// << standard[4] << 15 << 14 << QQuickTextInput::SelectWords << 14 << 15 << false;
- QTest::newRow("<()> spacey text |words")
- << standard[4] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << false;
- QTest::newRow(" spacey text <()>|words")
- << standard[4] << 15 << 15 << QQuickTextInput::SelectWords << 15 << 15 << false;
-}
-
-void tst_qquicktextinput::moveCursorSelection()
-{
- QFETCH(QString, testStr);
- QFETCH(int, cursorPosition);
- QFETCH(int, movePosition);
- QFETCH(QQuickTextInput::SelectionMode, mode);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(bool, reversible);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
-
- textinputObject->setCursorPosition(cursorPosition);
- textinputObject->moveCursorSelection(movePosition, mode);
-
- QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
- QCOMPARE(textinputObject->selectionStart(), selectionStart);
- QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
-
- if (reversible) {
- textinputObject->setCursorPosition(movePosition);
- textinputObject->moveCursorSelection(cursorPosition, mode);
-
- QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
- QCOMPARE(textinputObject->selectionStart(), selectionStart);
- QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
- }
-
- delete textinputObject;
-}
-
-void tst_qquicktextinput::moveCursorSelectionSequence_data()
-{
- QTest::addColumn<QString>("testStr");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<int>("movePosition1");
- QTest::addColumn<int>("movePosition2");
- QTest::addColumn<int>("selection1Start");
- QTest::addColumn<int>("selection1End");
- QTest::addColumn<int>("selection2Start");
- QTest::addColumn<int>("selection2End");
-
- // () contains the text selected by the cursor.
- // <> contains the actual selection.
- // ^ is the revised cursor position.
- // {} contains the revised selection.
-
- QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
- << standard[0]
- << 9 << 13 << 17
- << 4 << 15
- << 4 << 19;
- QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
- << standard[0]
- << 13 << 9 << 17
- << 9 << 15
- << 10 << 19;
- QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
- << standard[0]
- << 9 << 13 << 16
- << 4 << 15
- << 4 << 16;
- QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
- << standard[0]
- << 13 << 9 << 16
- << 9 << 15
- << 10 << 16;
- QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
- << standard[0]
- << 9 << 13 << 15
- << 4 << 15
- << 4 << 15;
- QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
- << standard[0]
- << 13 << 9 << 15
- << 9 << 15
- << 10 << 15;
- QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 10
- << 4 << 15
- << 4 << 10;
- QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
- << standard[0]
- << 13 << 9 << 10
- << 9 << 15
- << 10 << 15;
- QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 9
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
- << standard[0]
- << 13 << 9 << 9
- << 9 << 15
- << 9 << 15;
- QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 7
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 7
- << 9 << 15
- << 4 << 15;
- QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 4
- << 4 << 15
- << 4 << 9;
- QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 4
- << 9 << 15
- << 4 << 15;
- QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 3
- << 4 << 15
- << 3 << 9;
- QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 3
- << 9 << 15
- << 3 << 15;
- QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
- << standard[0]
- << 9 << 13 << 1
- << 4 << 15
- << 0 << 9;
- QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
- << standard[0]
- << 13 << 9 << 1
- << 9 << 15
- << 0 << 15;
-
- QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
- << standard[2]
- << 2 << 4 << 8
- << 0 << 5
- << 0 << 12;
- QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
- << standard[2]
- << 4 << 2 << 8
- << 0 << 5
- << 0 << 12;
-
- QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
- << standard[3]
- << 9 << 11 << 5
- << 8 << 13
- << 1 << 13;
- QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
- << standard[3]
- << 11 << 9 << 5
- << 8 << 13
- << 1 << 13;
-
- QTest::newRow("{<(^} sp)acey> text |ltr")
- << standard[4]
- << 0 << 3 << 0
- << 0 << 7
- << 0 << 0;
- QTest::newRow("{<( ^}sp)acey> text |ltr")
- << standard[4]
- << 0 << 3 << 1
- << 0 << 7
- << 0 << 1;
- QTest::newRow("<( {s^p)acey>} text |rtl")
- << standard[4]
- << 3 << 0 << 2
- << 0 << 7
- << 1 << 7;
- QTest::newRow("<( {^sp)acey>} text |rtl")
- << standard[4]
- << 3 << 0 << 1
- << 0 << 7
- << 1 << 7;
-
- QTest::newRow(" spacey <te(xt {^)>}|rtl")
- << standard[4]
- << 15 << 12 << 15
- << 10 << 15
- << 15 << 15;
-// QTBUG-11365
-// QTest::newRow(" spacey <te(xt{^ )>}|rtl")
-// << standard[4]
-// << 15 << 12 << 14
-// << 10 << 15
-// << 14 << 15;
- QTest::newRow(" spacey {<te(x^t} )>|ltr")
- << standard[4]
- << 12 << 15 << 13
- << 10 << 15
- << 10 << 14;
-// QTBUG-11365
-// QTest::newRow(" spacey {<te(xt^} )>|ltr")
-// << standard[4]
-// << 12 << 15 << 14
-// << 10 << 15
-// << 10 << 14;
-}
-
-void tst_qquicktextinput::moveCursorSelectionSequence()
-{
- QFETCH(QString, testStr);
- QFETCH(int, cursorPosition);
- QFETCH(int, movePosition1);
- QFETCH(int, movePosition2);
- QFETCH(int, selection1Start);
- QFETCH(int, selection1End);
- QFETCH(int, selection2Start);
- QFETCH(int, selection2End);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
- QDeclarativeComponent textinputComponent(&engine);
- textinputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
-
- textinputObject->setCursorPosition(cursorPosition);
-
- textinputObject->moveCursorSelection(movePosition1, QQuickTextInput::SelectWords);
- QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
- QCOMPARE(textinputObject->selectionStart(), selection1Start);
- QCOMPARE(textinputObject->selectionEnd(), selection1End);
-
- textinputObject->moveCursorSelection(movePosition2, QQuickTextInput::SelectWords);
- QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
- QCOMPARE(textinputObject->selectionStart(), selection2Start);
- QCOMPARE(textinputObject->selectionEnd(), selection2End);
-
- delete textinputObject;
-}
-
-void tst_qquicktextinput::dragMouseSelection()
-{
- QString qmlfile = TESTDATA("mouseselection_true.qml");
-
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(textInputObject != 0);
-
- // press-and-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = textInputObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QTest::qWait(100);
- QString str1;
- QVERIFY((str1 = textInputObject->selectedText()).length() > 3);
- QVERIFY(str1.length() > 3);
-
- // press and drag the current selection.
- x1 = 40;
- x2 = 100;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QTest::qWait(300);
- QString str2 = textInputObject->selectedText();
- QVERIFY(str2.length() > 3);
-
- QVERIFY(str1 != str2);
-}
-
-void tst_qquicktextinput::mouseSelectionMode_data()
-{
- QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<bool>("selectWords");
-
- // import installed
- QTest::newRow("SelectWords") << TESTDATA("mouseselectionmode_words.qml") << true;
- QTest::newRow("SelectCharacters") << TESTDATA("mouseselectionmode_characters.qml") << false;
- QTest::newRow("default") << TESTDATA("mouseselectionmode_default.qml") << false;
-}
-
-void tst_qquicktextinput::mouseSelectionMode()
-{
- QFETCH(QString, qmlfile);
- QFETCH(bool, selectWords);
-
- QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(textInputObject != 0);
-
- // press-and-drag-and-release from x1 to x2
- int x1 = 10;
- int x2 = 70;
- int y = textInputObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2,y)); // doesn't work
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QTest::qWait(300);
- if (selectWords) {
- QTRY_COMPARE(textInputObject->selectedText(), text);
- } else {
- QTRY_VERIFY(textInputObject->selectedText().length() > 3);
- QVERIFY(textInputObject->selectedText() != text);
- }
-}
-
-void tst_qquicktextinput::horizontalAlignment_data()
-{
- QTest::addColumn<int>("hAlign");
- QTest::addColumn<QString>("expectfile");
-
- QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
- QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
- QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
-}
-
-void tst_qquicktextinput::horizontalAlignment()
-{
- QSKIP("Image comparison of text is almost guaranteed to fail during development");
-
- QFETCH(int, hAlign);
- QFETCH(QString, expectfile);
-
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment.qml")));
-
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
- QObject *ob = canvas.rootObject();
- QVERIFY(ob != 0);
- ob->setProperty("horizontalAlignment",hAlign);
- QImage actual = canvas.grabFrameBuffer();
-
- expectfile = createExpectedFileIfNotFound(expectfile, actual);
-
- QImage expect(expectfile);
-
- QCOMPARE(actual,expect);
-}
-
-void tst_qquicktextinput::horizontalAlignment_RightToLeft()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment_RightToLeft.qml")));
- QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
- QVERIFY(textInput != 0);
- canvas.show();
-
- const QString rtlText = textInput->text();
-
- QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
- QVERIFY(textInputPrivate != 0);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // implicit alignment should follow the reading direction of RTL text
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // explicitly left aligned
- textInput->setHAlign(QQuickTextInput::AlignLeft);
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
-
- // explicitly right aligned
- textInput->setHAlign(QQuickTextInput::AlignRight);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // explicitly center aligned
- textInput->setHAlign(QQuickTextInput::AlignHCenter);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignHCenter);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
- QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width > canvas.width()/2);
-
- // reseted alignment should go back to following the text reading direction
- textInput->resetHAlign();
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // mirror the text item
- QQuickItemPrivate::get(textInput)->setLayoutMirror(true);
-
- // mirrored implicit alignment should continue to follow the reading direction of the text
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // explicitly right aligned behaves as left aligned
- textInput->setHAlign(QQuickTextInput::AlignRight);
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignLeft);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
-
- // mirrored explicitly left aligned behaves as right aligned
- textInput->setHAlign(QQuickTextInput::AlignLeft);
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
- QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
- // disable mirroring
- QQuickItemPrivate::get(textInput)->setLayoutMirror(false);
- QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- textInput->resetHAlign();
-
- // English text should be implicitly left aligned
- textInput->setText("Hello world!");
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
-
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- // If there is no commited text, the preedit text should determine the alignment.
- textInput->setText(QString());
- { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
-
- // Clear pre-edit text. TextInput should maybe do this itself on setText, but that may be
- // redundant as an actual input method may take care of it.
- { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
-
-#ifdef Q_OS_MAC
- // empty text with implicit alignment follows the system locale-based
- // keyboard input direction from QGuiApplication::keyboardInputDirection
- QEXPECT_FAIL("", "QTBUG-18040", Abort);
-#endif
- textInput->setText("");
- QCOMPARE(textInput->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
- if (QGuiApplication::keyboardInputDirection() == Qt::LeftToRight)
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
- else
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
- textInput->setHAlign(QQuickTextInput::AlignRight);
- QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
-
-
-#ifdef Q_OS_MAC
- QEXPECT_FAIL("", "QTBUG-18040", Abort); // alignment of TextInput with no text set to it
-#endif
- QString componentStr = "import QtQuick 2.0\nTextInput {}";
- QDeclarativeComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
- QCOMPARE(textObject->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
- QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
- delete textObject;
-}
-
-void tst_qquicktextinput::positionAt()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
- QVERIFY(canvas.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(textinputObject != 0);
-
- // Check autoscrolled...
- QFontMetrics fm(textinputObject->font());
-
- int pos = textinputObject->positionAt(textinputObject->width()/2);
- int textWidth = 0;
- int textLeftWidthBegin = 0;
- int textLeftWidthEnd = 0;
- if (!qmlDisableDistanceField()) {
- QTextLayout layout(textinputObject->text());
-
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
-
- layout.beginLayout();
- QTextLine line = layout.createLine();
- layout.endLayout();
-
- textLeftWidthBegin = floor(line.cursorToX(pos - 1));
- textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
- textWidth = floor(line.horizontalAdvance());
- } else {
- textWidth = fm.width(textinputObject->text());
- textLeftWidthBegin = fm.width(textinputObject->text().left(pos - 1));
- textLeftWidthEnd = fm.width(textinputObject->text().left(pos + 1));
- }
-
- QVERIFY(textLeftWidthBegin <= textWidth - textinputObject->width() / 2);
- QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
-
- int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
-
- // Check without autoscroll...
- textinputObject->setAutoScroll(false);
- pos = textinputObject->positionAt(textinputObject->width()/2);
-
- if (!qmlDisableDistanceField()) {
- QTextLayout layout(textinputObject->text());
-
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
-
- layout.beginLayout();
- QTextLine line = layout.createLine();
- layout.endLayout();
-
- textLeftWidthBegin = floor(line.cursorToX(pos - 1));
- textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
- } else {
- textLeftWidthBegin = fm.width(textinputObject->text().left(pos - 1));
- textLeftWidthEnd = fm.width(textinputObject->text().left(pos + 1));
- }
-
- QVERIFY(textLeftWidthBegin <= textinputObject->width() / 2);
- QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
-
- x = textinputObject->positionToRectangle(pos + 1).x() - 1;
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
-
- const qreal x0 = textinputObject->positionToRectangle(pos).x();
- const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
-
- QString preeditText = textinputObject->text().mid(0, pos);
- textinputObject->setText(textinputObject->text().mid(pos));
- textinputObject->setCursorPosition(0);
-
- QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent);
-
- // Check all points within the preedit text return the same position.
- QCOMPARE(textinputObject->positionAt(0), 0);
- QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
- QCOMPARE(textinputObject->positionAt(x0), 0);
-
- // Verify positioning returns to normal after the preedit text.
- QCOMPARE(textinputObject->positionAt(x1), 1);
- QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
-}
-
-void tst_qquicktextinput::maxLength()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("maxLength.qml")));
- QVERIFY(canvas.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(textinputObject != 0);
- QVERIFY(textinputObject->text().isEmpty());
- QVERIFY(textinputObject->maxLength() == 10);
- foreach (const QString &str, standard) {
- QVERIFY(textinputObject->text().length() <= 10);
- textinputObject->setText(str);
- QVERIFY(textinputObject->text().length() <= 10);
- }
-
- textinputObject->setText("");
- QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
- for (int i=0; i<20; i++) {
- QTRY_COMPARE(textinputObject->text().length(), qMin(i,10));
- //simulateKey(&canvas, Qt::Key_A);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- }
-}
-
-void tst_qquicktextinput::masks()
-{
- //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
- //QString componentStr = "import QtQuick 2.0\nTextInput { inputMask: 'HHHHhhhh'; }";
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("masks.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(textinputObject != 0);
- QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
- QVERIFY(textinputObject->text().length() == 0);
- QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
- for (int i=0; i<10; i++) {
- QTRY_COMPARE(qMin(i,8), textinputObject->text().length());
- QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
- //simulateKey(&canvas, Qt::Key_A);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- }
-}
-
-void tst_qquicktextinput::validators()
-{
- // Note that this test assumes that the validators are working properly
- // so you may need to run their tests first. All validators are checked
- // here to ensure that their exposure to QML is working.
-
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("validators.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *intInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("intInput")));
- QVERIFY(intInput);
- intInput->setFocus(true);
- QTRY_VERIFY(intInput->hasActiveFocus());
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(intInput->text(), QLatin1String("1"));
- QCOMPARE(intInput->hasAcceptableInput(), false);
- QTest::keyPress(&canvas, Qt::Key_2);
- QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(intInput->text(), QLatin1String("1"));
- QCOMPARE(intInput->hasAcceptableInput(), false);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QCOMPARE(intInput->text(), QLatin1String("11"));
- QCOMPARE(intInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_0);
- QTest::keyRelease(&canvas, Qt::Key_0, Qt::NoModifier ,10);
- QTest::qWait(50);
- QCOMPARE(intInput->text(), QLatin1String("11"));
- QCOMPARE(intInput->hasAcceptableInput(), true);
-
- QQuickTextInput *dblInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("dblInput")));
- QTRY_VERIFY(dblInput);
- dblInput->setFocus(true);
- QVERIFY(dblInput->hasActiveFocus() == true);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
- QCOMPARE(dblInput->hasAcceptableInput(), false);
- QTest::keyPress(&canvas, Qt::Key_2);
- QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_Period);
- QTest::keyRelease(&canvas, Qt::Key_Period, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
-
- QQuickTextInput *strInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("strInput")));
- QTRY_VERIFY(strInput);
- strInput->setFocus(true);
- QVERIFY(strInput->hasActiveFocus() == true);
- QTest::keyPress(&canvas, Qt::Key_1);
- QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String(""));
- QCOMPARE(strInput->hasAcceptableInput(), false);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String("a"));
- QCOMPARE(strInput->hasAcceptableInput(), false);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String("aa"));
- QCOMPARE(strInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String("aaa"));
- QCOMPARE(strInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
- QCOMPARE(strInput->hasAcceptableInput(), true);
- QTest::keyPress(&canvas, Qt::Key_A);
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QTest::qWait(50);
- QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
- QCOMPARE(strInput->hasAcceptableInput(), true);
-}
-
-void tst_qquicktextinput::inputMethods()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("inputmethods.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- // test input method hints
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(canvas.rootObject());
- QVERIFY(input != 0);
- QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
- input->setInputMethodHints(Qt::ImhUppercaseOnly);
- QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
-
- input->setFocus(true);
- QVERIFY(input->hasActiveFocus() == true);
- // test that input method event is committed
- QInputMethodEvent event;
- event.setCommitString( "My ", -12, 0);
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
- QCOMPARE(input->text(), QString("My Hello world!"));
-
- input->setCursorPosition(2);
- event.setCommitString("Your", -2, 2);
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
- QCOMPARE(input->text(), QString("Your Hello world!"));
- QCOMPARE(input->cursorPosition(), 4);
-
- input->setCursorPosition(7);
- event.setCommitString("Goodbye", -2, 5);
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
- QCOMPARE(input->text(), QString("Your Goodbye world!"));
- QCOMPARE(input->cursorPosition(), 12);
-
- input->setCursorPosition(8);
- event.setCommitString("Our", -8, 4);
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
- QCOMPARE(input->text(), QString("Our Goodbye world!"));
- QCOMPARE(input->cursorPosition(), 7);
-
- // test that basic tentative commit gets to text property on preedit state
- input->setText("");
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent preeditEvent("test", attributes);
- preeditEvent.setTentativeCommitString("test");
- QApplication::sendEvent(input, &preeditEvent);
- QCOMPARE(input->text(), QString("test"));
-
- // tentative commit not allowed present in surrounding text
- QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
- QApplication::sendEvent(input, &queryEvent);
- QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
-
- // if text with tentative commit does not validate, not allowed to be part of text property
- input->setText(""); // ensure input state is reset
- QValidator *validator = new QIntValidator(0, 100);
- input->setValidator(validator);
- QApplication::sendEvent(input, &preeditEvent);
- QCOMPARE(input->text(), QString(""));
- input->setValidator(0);
- delete validator;
-}
-
-/*
-TextInput element should only handle left/right keys until the cursor reaches
-the extent of the text, then they should ignore the keys.
-
-*/
-void tst_qquicktextinput::navigation()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- input->setCursorPosition(0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
- //QT-2944: If text is selected, ensure we deselect upon cursor motion
- input->setCursorPosition(input->text().length());
- input->select(0,input->text().length());
- QVERIFY(input->selectionStart() != input->selectionEnd());
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->selectionStart() == input->selectionEnd());
- QVERIFY(input->selectionStart() == input->text().length());
- QVERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
-
- // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
- input->setCursorPosition(2);
- QCOMPARE(input->cursorPosition(),2);
- simulateKey(&canvas, Qt::Key_Up);
- QCOMPARE(input->cursorPosition(),2);
- simulateKey(&canvas, Qt::Key_Down);
- QCOMPARE(input->cursorPosition(),2);
-}
-
-void tst_qquicktextinput::navigation_RTL()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
- input->setText(QString::fromUtf16(arabic_str, 11));
-
- input->setCursorPosition(0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
-
- // move off
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == false);
-
- // move back
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == true);
-
- input->setCursorPosition(input->text().length());
- QVERIFY(input->hasActiveFocus() == true);
-
- // move off
- simulateKey(&canvas, Qt::Key_Left);
- QVERIFY(input->hasActiveFocus() == false);
-
- // move back
- simulateKey(&canvas, Qt::Key_Right);
- QVERIFY(input->hasActiveFocus() == true);
-}
-
-void tst_qquicktextinput::copyAndPaste() {
-#ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
- {
- PasteboardRef pasteboard;
- OSStatus status = PasteboardCreate(0, &pasteboard);
- if (status == noErr)
- CFRelease(pasteboard);
- else
- QSKIP("This machine doesn't support the clipboard");
- }
-#endif
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- // copy and paste
- QCOMPARE(textInput->text().length(), 12);
- textInput->select(0, textInput->text().length());;
- textInput->copy();
- QCOMPARE(textInput->selectedText(), QString("Hello world!"));
- QCOMPARE(textInput->selectedText().length(), 12);
- textInput->setCursorPosition(0);
- QVERIFY(textInput->canPaste());
- textInput->paste();
- QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textInput->text().length(), 24);
-
- // can paste
- QVERIFY(textInput->canPaste());
- textInput->setReadOnly(true);
- QVERIFY(!textInput->canPaste());
- textInput->setReadOnly(false);
- QVERIFY(textInput->canPaste());
-
- // select word
- textInput->setCursorPosition(0);
- textInput->selectWord();
- QCOMPARE(textInput->selectedText(), QString("Hello"));
-
- // select all and cut
- textInput->selectAll();
- textInput->cut();
- QCOMPARE(textInput->text().length(), 0);
- textInput->paste();
- QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textInput->text().length(), 24);
-
- // clear copy buffer
- QClipboard *clipboard = QGuiApplication::clipboard();
- QVERIFY(clipboard);
- clipboard->clear();
- QVERIFY(!textInput->canPaste());
-
- // test that copy functionality is disabled
- // when echo mode is set to hide text/password mode
- int index = 0;
- while (index < 4) {
- QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
- textInput->setEchoMode(echoMode);
- textInput->setText("My password");
- textInput->select(0, textInput->text().length());;
- textInput->copy();
- if (echoMode == QQuickTextInput::Normal) {
- QVERIFY(!clipboard->text().isEmpty());
- QCOMPARE(clipboard->text(), QString("My password"));
- clipboard->clear();
- } else {
- QVERIFY(clipboard->text().isEmpty());
- }
- index++;
- }
-
- delete textInput;
-#endif
-}
-
-void tst_qquicktextinput::copyAndPasteKeySequence() {
-#ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
- {
- PasteboardRef pasteboard;
- OSStatus status = PasteboardCreate(0, &pasteboard);
- if (status == noErr)
- CFRelease(pasteboard);
- else
- QSKIP("This machine doesn't support the clipboard");
- }
-#endif
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; focus: true }";
- QDeclarativeComponent 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);
-
- // copy and paste
- QVERIFY(textInput->hasActiveFocus());
- QCOMPARE(textInput->text().length(), 12);
- textInput->select(0, textInput->text().length());
- simulateKeys(&canvas, QKeySequence::Copy);
- QCOMPARE(textInput->selectedText(), QString("Hello world!"));
- QCOMPARE(textInput->selectedText().length(), 12);
- textInput->setCursorPosition(0);
- QVERIFY(textInput->canPaste());
- simulateKeys(&canvas, QKeySequence::Paste);
- QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textInput->text().length(), 24);
-
- // select all and cut
- simulateKeys(&canvas, QKeySequence::SelectAll);
- simulateKeys(&canvas, QKeySequence::Cut);
- QCOMPARE(textInput->text().length(), 0);
- simulateKeys(&canvas, QKeySequence::Paste);
- QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
- QCOMPARE(textInput->text().length(), 24);
-
- // clear copy buffer
- QClipboard *clipboard = QGuiApplication::clipboard();
- QVERIFY(clipboard);
- clipboard->clear();
- QVERIFY(!textInput->canPaste());
-
- // test that copy functionality is disabled
- // when echo mode is set to hide text/password mode
- int index = 0;
- while (index < 4) {
- QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
- textInput->setEchoMode(echoMode);
- textInput->setText("My password");
- textInput->select(0, textInput->text().length());;
- simulateKeys(&canvas, QKeySequence::Copy);
- if (echoMode == QQuickTextInput::Normal) {
- QVERIFY(!clipboard->text().isEmpty());
- QCOMPARE(clipboard->text(), QString("My password"));
- clipboard->clear();
- } else {
- QVERIFY(clipboard->text().isEmpty());
- }
- index++;
- }
-
- delete textInput;
-#endif
-}
-
-void tst_qquicktextinput::canPasteEmpty() {
-#ifndef QT_NO_CLIPBOARD
-
- QGuiApplication::clipboard()->clear();
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- QLineControl lc;
- bool cp = !lc.isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
- QCOMPARE(textInput->canPaste(), cp);
-
-#endif
-}
-
-void tst_qquicktextinput::canPaste() {
-#ifndef QT_NO_CLIPBOARD
-
- QGuiApplication::clipboard()->setText("Some text");
-
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- QLineControl lc;
- bool cp = !lc.isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
- QCOMPARE(textInput->canPaste(), cp);
-
-#endif
-}
-
-void tst_qquicktextinput::passwordCharacter()
-{
- QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
- QDeclarativeComponent textInputComponent(&engine);
- textInputComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
-
- textInput->setPasswordCharacter("X");
- qreal implicitWidth = textInput->implicitWidth();
- textInput->setPasswordCharacter(".");
-
- // QTBUG-12383 content is updated and redrawn
- QVERIFY(textInput->implicitWidth() < implicitWidth);
-
- delete textInput;
-}
-
-void tst_qquicktextinput::cursorDelegate()
-{
- QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorTest.qml")));
- view.show();
- view.requestActivateWindow();
- QQuickTextInput *textInputObject = view.rootObject()->findChild<QQuickTextInput*>("textInputObject");
- QVERIFY(textInputObject != 0);
- QVERIFY(textInputObject->findChild<QQuickItem*>("cursorInstance"));
- //Test Delegate gets created
- textInputObject->setFocus(true);
- QQuickItem* delegateObject = textInputObject->findChild<QQuickItem*>("cursorInstance");
- QVERIFY(delegateObject);
- QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
- //Test Delegate gets moved
- for (int i=0; i<= textInputObject->text().length(); i++) {
- textInputObject->setCursorPosition(i);
- QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
- }
- textInputObject->setCursorPosition(0);
- QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
- QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
- //Test Delegate gets deleted
- textInputObject->setCursorDelegate(0);
- QVERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
-}
-
-void tst_qquicktextinput::cursorVisible()
-{
- QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorVisible.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QQuickTextInput input;
- QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
-
- QCOMPARE(input.isCursorVisible(), false);
-
- input.setCursorVisible(true);
- QCOMPARE(input.isCursorVisible(), true);
- QCOMPARE(spy.count(), 1);
-
- input.setCursorVisible(false);
- QCOMPARE(input.isCursorVisible(), false);
- QCOMPARE(spy.count(), 2);
-
- input.setFocus(true);
- QCOMPARE(input.isCursorVisible(), false);
- QCOMPARE(spy.count(), 2);
-
- input.setParentItem(view.rootObject());
- QCOMPARE(input.isCursorVisible(), true);
- QCOMPARE(spy.count(), 3);
-
- input.setFocus(false);
- QCOMPARE(input.isCursorVisible(), false);
- QCOMPARE(spy.count(), 4);
-
- input.setFocus(true);
- QCOMPARE(input.isCursorVisible(), true);
- QCOMPARE(spy.count(), 5);
-
- QQuickView alternateView;
- alternateView.show();
- alternateView.requestActivateWindow();
- QTest::qWaitForWindowShown(&alternateView);
-
- QCOMPARE(input.isCursorVisible(), false);
- QCOMPARE(spy.count(), 6);
-
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QCOMPARE(input.isCursorVisible(), true);
- QCOMPARE(spy.count(), 7);
-}
-
-void tst_qquicktextinput::cursorRectangle()
-{
- QSKIP("QTBUG-21689");
-
- QString text = "Hello World!";
-
- QQuickTextInput input;
- input.setText(text);
- QFontMetricsF fm(input.font());
- input.setWidth(fm.width(text.mid(0, 5)));
-
- QRect 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) {
- input.setCursorPosition(i);
- r = input.cursorRectangle();
- int textWidth = fm.width(text.mid(0, i));
-
- QVERIFY(r.left() < textWidth + error);
- QVERIFY(r.right() > textWidth - error);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
- }
-
- // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
- QVERIFY(r.left() < input.boundingRect().width());
- QVERIFY(r.right() >= input.width() - error);
-
- for (int i = 6; i < text.length(); ++i) {
- input.setCursorPosition(i);
- QCOMPARE(r, input.cursorRectangle());
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
- }
-
- for (int i = text.length() - 2; i >= 0; --i) {
- input.setCursorPosition(i);
- r = input.cursorRectangle();
- QVERIFY(r.right() >= 0);
- QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
- }
-
- input.setText("Hi!");
- input.setHAlign(QQuickTextInput::AlignRight);
- r = input.cursorRectangle();
- QVERIFY(r.left() < input.boundingRect().width());
- QVERIFY(r.right() >= input.width() - error);
-}
-
-void tst_qquicktextinput::readOnly()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("readOnly.qml")));
- canvas.show();
- canvas.requestActivateWindow();
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
- QVERIFY(input->isReadOnly() == true);
- QString initial = input->text();
- for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
- simulateKey(&canvas, k);
- simulateKey(&canvas, Qt::Key_Return);
- simulateKey(&canvas, Qt::Key_Space);
- simulateKey(&canvas, Qt::Key_Escape);
- QCOMPARE(input->text(), initial);
-
- input->setCursorPosition(3);
- input->setReadOnly(false);
- QCOMPARE(input->isReadOnly(), false);
- QCOMPARE(input->cursorPosition(), input->text().length());
-}
-
-void tst_qquicktextinput::echoMode()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("echoMode.qml")));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
- QString initial = input->text();
- Qt::InputMethodHints ref;
- QCOMPARE(initial, QLatin1String("ABCDefgh"));
- QCOMPARE(input->echoMode(), QQuickTextInput::Normal);
- QCOMPARE(input->displayText(), input->text());
- //Normal
- ref &= ~Qt::ImhHiddenText;
- ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- QCOMPARE(input->inputMethodHints(), ref);
- input->setEchoMode(QQuickTextInput::NoEcho);
- QCOMPARE(input->text(), initial);
- QCOMPARE(input->displayText(), QLatin1String(""));
- QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
- //NoEcho
- ref |= Qt::ImhHiddenText;
- ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- QCOMPARE(input->inputMethodHints(), ref);
- input->setEchoMode(QQuickTextInput::Password);
- //Password
- ref |= Qt::ImhHiddenText;
- ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- QCOMPARE(input->text(), initial);
- QCOMPARE(input->displayText(), QLatin1String("********"));
- QCOMPARE(input->inputMethodHints(), ref);
- input->setPasswordCharacter(QChar('Q'));
- QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
- QCOMPARE(input->text(), initial);
- QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
- input->setEchoMode(QQuickTextInput::PasswordEchoOnEdit);
- //PasswordEchoOnEdit
- ref &= ~Qt::ImhHiddenText;
- ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- QCOMPARE(input->inputMethodHints(), ref);
- QCOMPARE(input->text(), initial);
- QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
- QTest::keyPress(&canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
- QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
- QCOMPARE(input->text(), QLatin1String("a"));
- QCOMPARE(input->displayText(), QLatin1String("a"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
- input->setFocus(false);
- QVERIFY(input->hasActiveFocus() == false);
- QCOMPARE(input->displayText(), QLatin1String("Q"));
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
- input->setFocus(true);
- QVERIFY(input->hasActiveFocus());
- QInputMethodEvent inputEvent;
- inputEvent.setCommitString(initial);
- QGuiApplication::sendEvent(input, &inputEvent);
- QCOMPARE(input->text(), initial);
- QCOMPARE(input->displayText(), initial);
- QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
-}
-
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
-void tst_qdeclarativetextinput::passwordEchoDelay()
-{
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA("echoMode.qml")));
- canvas.show();
- canvas.setFocus();
- QGuiApplication::setActiveWindow(&canvas);
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-
- QVERIFY(canvas.rootObject() != 0);
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
-
- QChar fillChar = QLatin1Char('*');
-
- input->setEchoMode(QDeclarativeTextInput::Password);
- QCOMPARE(input->displayText(), QString(8, fillChar));
- input->setText(QString());
- QCOMPARE(input->displayText(), QString());
-
- QTest::keyPress(&canvas, '0');
- QTest::keyPress(&canvas, '1');
- QTest::keyPress(&canvas, '2');
- QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
- QTest::keyPress(&canvas, '3');
- QTest::keyPress(&canvas, '4');
- QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
- QTest::keyPress(&canvas, Qt::Key_Backspace);
- QCOMPARE(input->displayText(), QString(4, fillChar));
- QTest::keyPress(&canvas, '4');
- QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
- QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
- QTRY_COMPARE(input->displayText(), QString(5, fillChar));
- QTest::keyPress(&canvas, '5');
- QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
- input->setFocus(false);
- QVERIFY(!input->hasFocus());
- QCOMPARE(input->displayText(), QString(6, fillChar));
- input->setFocus(true);
- QTRY_VERIFY(input->hasFocus());
- QCOMPARE(input->displayText(), QString(6, fillChar));
- QTest::keyPress(&canvas, '6');
- QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
-
- QInputMethodEvent ev;
- ev.setCommitString(QLatin1String("7"));
- QGuiApplication::sendEvent(&canvas, &ev);
- QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
-}
-#endif
-
-
-void tst_qquicktextinput::simulateKey(QQuickView *view, int key)
-{
- QKeyEvent press(QKeyEvent::KeyPress, key, 0);
- QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
-
- QGuiApplication::sendEvent(view, &press);
- QGuiApplication::sendEvent(view, &release);
-}
-
-class PlatformInputContext : public QPlatformInputContext
-{
-public:
- PlatformInputContext()
- : m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
- m_invokeActionCallCount(0)
- {
- }
-
- virtual void showInputPanel()
- {
- m_visible = true;
- }
- virtual void hideInputPanel()
- {
- m_visible = false;
- }
- virtual bool isInputPanelVisible() const
- {
- return m_visible;
- }
- virtual void invokeAction(QInputPanel::Action action, int cursorPosition)
- {
- m_invokeActionCallCount++;
- m_action = action;
- m_cursorPosition = cursorPosition;
- }
-
- bool m_visible;
- QInputPanel::Action m_action;
- int m_cursorPosition;
- int m_invokeActionCallCount;
-};
-
-void tst_qquicktextinput::openInputPanel()
-{
- PlatformInputContext platformInputContext;
- QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
- inputPanelPrivate->testContext = &platformInputContext;
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("openInputPanel.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
- QVERIFY(input);
-
- // check default values
- QVERIFY(input->focusOnPress());
- QVERIFY(!input->hasActiveFocus());
- qDebug() << &input << qApp->inputPanel()->inputItem();
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should open on focus
- QPoint centerPoint(view.width()/2, view.height()/2);
- Qt::KeyboardModifiers noModifiers = 0;
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QVERIFY(input->hasActiveFocus());
- QCOMPARE(qApp->inputPanel()->inputItem(), input);
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
-
- // input panel should be re-opened when pressing already focused TextInput
- qApp->inputPanel()->hide();
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QVERIFY(input->hasActiveFocus());
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
-
- // input panel should stay visible if focus is lost to another text inputor
- QSignalSpy inputPanelVisibilitySpy(qApp->inputPanel(), SIGNAL(visibleChanged()));
- QQuickTextInput anotherInput;
- anotherInput.setParentItem(view.rootObject());
- anotherInput.setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), true);
- QCOMPARE(qApp->inputPanel()->inputItem(), qobject_cast<QObject*>(&anotherInput));
- QCOMPARE(inputPanelVisibilitySpy.count(), 0);
-
- anotherInput.setFocus(false);
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
- QCOMPARE(view.activeFocusItem(), view.rootItem());
- anotherInput.setFocus(true);
-
- // input item should be null if focus is lost to an item that doesn't accept inputs
- QQuickItem item;
- item.setParentItem(view.rootObject());
- item.setFocus(true);
- QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
- QCOMPARE(view.activeFocusItem(), &item);
-
- qApp->inputPanel()->hide();
-
- // input panel should not be opened if TextInput is read only
- input->setReadOnly(true);
- input->setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
- QGuiApplication::processEvents();
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should not be opened if focusOnPress is set to false
- input->setFocusOnPress(false);
- input->setFocus(false);
- input->setFocus(true);
- QCOMPARE(qApp->inputPanel()->visible(), false);
- QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
- QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
- QCOMPARE(qApp->inputPanel()->visible(), false);
-
- // input panel should open when openSoftwareInputPanel is called
- input->openSoftwareInputPanel();
- QCOMPARE(qApp->inputPanel()->visible(), true);
-
- // input panel should close when closeSoftwareInputPanel is called
- input->closeSoftwareInputPanel();
- QCOMPARE(qApp->inputPanel()->visible(), false);
-}
-
-class MyTextInput : public QQuickTextInput
-{
-public:
- MyTextInput(QQuickItem *parent = 0) : QQuickTextInput(parent)
- {
- nbPaint = 0;
- }
- virtual QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data)
- {
- nbPaint++;
- return QQuickTextInput::updatePaintNode(node, data);
- }
- int nbPaint;
-};
-
-void tst_qquicktextinput::setHAlignClearCache()
-{
- QQuickView view;
- MyTextInput input;
- input.setText("Hello world");
- input.setParentItem(view.rootItem());
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(input.nbPaint, 1);
- input.setHAlign(QQuickTextInput::AlignRight);
- //Changing the alignment should trigger a repaint
- QTRY_COMPARE(input.nbPaint, 2);
-}
-
-void tst_qquicktextinput::focusOutClearSelection()
-{
- QQuickView view;
- QQuickTextInput input;
- QQuickTextInput input2;
- input.setText(QLatin1String("Hello world"));
- input.setFocus(true);
- input2.setParentItem(view.rootItem());
- input.setParentItem(view.rootItem());
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- input.select(2,5);
- //The selection should work
- QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
- input2.setFocus(true);
- QGuiApplication::processEvents();
- //The input lost the focus selection should be cleared
- QTRY_COMPARE(input.selectedText(), QLatin1String(""));
-}
-
-void tst_qquicktextinput::geometrySignals()
-{
- QDeclarativeComponent component(&engine, TESTDATA("geometrySignals.qml"));
- QObject *o = component.create();
- QVERIFY(o);
- QCOMPARE(o->property("bindingWidth").toInt(), 400);
- QCOMPARE(o->property("bindingHeight").toInt(), 500);
- delete o;
-}
-
-void tst_qquicktextinput::testQtQuick11Attributes()
-{
- QFETCH(QString, code);
- QFETCH(QString, warning);
- QFETCH(QString, error);
-
- QDeclarativeEngine engine;
- QObject *obj;
-
- QDeclarativeComponent valid(&engine);
- valid.setData("import QtQuick 2.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
- obj = valid.create();
- QVERIFY(obj);
- QVERIFY(valid.errorString().isEmpty());
- delete obj;
-
- QDeclarativeComponent invalid(&engine);
- invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
- QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
- obj = invalid.create();
- QCOMPARE(invalid.errorString(), error);
- delete obj;
-}
-
-void tst_qquicktextinput::testQtQuick11Attributes_data()
-{
- QTest::addColumn<QString>("code");
- QTest::addColumn<QString>("warning");
- QTest::addColumn<QString>("error");
-
- QTest::newRow("canPaste") << "property bool foo: canPaste"
- << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
- << "";
-
- QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
- << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
- << "";
-
- QTest::newRow("deselect") << "Component.onCompleted: deselect()"
- << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
- << "";
-}
-
-static void sendPreeditText(const QString &text, int cursor)
-{
- QInputMethodEvent event(text, QList<QInputMethodEvent::Attribute>()
- << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
-}
-
-void tst_qquicktextinput::preeditAutoScroll()
-{
- QString preeditText = "califragisiticexpialidocious!";
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("preeditAutoScroll.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
- QVERIFY(input);
- QVERIFY(input->hasActiveFocus());
-
- input->setWidth(input->implicitWidth());
-
- QSignalSpy cursorRectangleSpy(input, SIGNAL(cursorRectangleChanged()));
- int cursorRectangleChanges = 0;
-
- // test the text is scrolled so the preedit is visible.
- sendPreeditText(preeditText.mid(0, 3), 1);
- QVERIFY(input->positionAt(0) != 0);
- QVERIFY(input->cursorRectangle().left() < input->boundingRect().width());
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
-
- // test the text is scrolled back when the preedit is removed.
- QInputMethodEvent imEvent;
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- QCOMPARE(input->positionAt(0), 0);
- QCOMPARE(input->positionAt(input->width()), 5);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
-
- QTextLayout layout(preeditText);
- if (!qmlDisableDistanceField()) {
- QTextOption option;
- option.setUseDesignMetrics(true);
- layout.setTextOption(option);
- }
- layout.beginLayout();
- QTextLine line = layout.createLine();
- layout.endLayout();
-
- // test if the preedit is larger than the text input that the
- // character preceding the cursor is still visible.
- qreal x = input->positionToRectangle(0).x();
- for (int i = 0; i < 3; ++i) {
- sendPreeditText(preeditText, i + 1);
- int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
- QVERIFY(input->cursorRectangle().right() >= width - 3);
- QVERIFY(input->positionToRectangle(0).x() < x);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
- x = input->positionToRectangle(0).x();
- }
- for (int i = 1; i >= 0; --i) {
- sendPreeditText(preeditText, i + 1);
- int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
- QVERIFY(input->cursorRectangle().right() >= width - 3);
- QVERIFY(input->positionToRectangle(0).x() > x);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
- x = input->positionToRectangle(0).x();
- }
-
- // Test incrementing the preedit cursor doesn't cause further
- // scrolling when right most text is visible.
- sendPreeditText(preeditText, preeditText.length() - 3);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
- x = input->positionToRectangle(0).x();
- for (int i = 2; i >= 0; --i) {
- sendPreeditText(preeditText, preeditText.length() - i);
- QCOMPARE(input->positionToRectangle(0).x(), x);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
- }
- for (int i = 1; i < 3; ++i) {
- sendPreeditText(preeditText, preeditText.length() - i);
- QCOMPARE(input->positionToRectangle(0).x(), x);
- QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
- }
-
- // Test disabling auto scroll.
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
-
- input->setAutoScroll(false);
- sendPreeditText(preeditText.mid(0, 3), 1);
- QCOMPARE(input->positionAt(0), 0);
- QCOMPARE(input->positionAt(input->width()), 5);
-}
-
-void tst_qquicktextinput::preeditCursorRectangle()
-{
- QString preeditText = "super";
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
- QVERIFY(input);
-
- QRect currentRect;
-
- QInputMethodQueryEvent query(Qt::ImCursorRectangle);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
-
- // Verify that the micro focus rect is positioned the same for position 0 as
- // it would be if there was no preedit text.
- sendPreeditText(preeditText, 0);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QCOMPARE(currentRect, previousRect);
-
- QSignalSpy inputSpy(input, SIGNAL(cursorRectangleChanged()));
- QSignalSpy panelSpy(qGuiApp->inputPanel(), SIGNAL(cursorRectangleChanged()));
-
- // Verify that the micro focus rect moves to the left as the cursor position
- // is incremented.
- for (int i = 1; i <= 5; ++i) {
- sendPreeditText(preeditText, i);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QVERIFY(previousRect.left() < currentRect.left());
- QVERIFY(inputSpy.count() > 0); inputSpy.clear();
- QVERIFY(panelSpy.count() > 0); panelSpy.clear();
- previousRect = currentRect;
- }
-
- // Verify that if there is no preedit cursor then the micro focus rect is the
- // same as it would be if it were positioned at the end of the preedit text.
- sendPreeditText(preeditText, 0);
- QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
- QCOMPARE(currentRect, previousRect);
- QVERIFY(inputSpy.count() > 0);
- QVERIFY(panelSpy.count() > 0);
-}
-
-void tst_qquicktextinput::inputContextMouseHandler()
-{
- PlatformInputContext platformInputContext;
- QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
- inputPanelPrivate->testContext = &platformInputContext;
-
- QString text = "supercalifragisiticexpialidocious!";
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
- QVERIFY(input);
-
- input->setFocus(true);
- input->setText("");
-
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QFontMetricsF fm(input->font());
- const qreal y = fm.height() / 2;
- QPoint position = QPointF(fm.width(text.mid(0, 2)), y).toPoint();
-
- QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
- QApplication::sendEvent(input, &inputEvent);
-
- QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
- QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
- QGuiApplication::processEvents();
-
- QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
- QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
- QCOMPARE(platformInputContext.m_cursorPosition, 2);
-}
-
-void tst_qquicktextinput::inputMethodComposing()
-{
- QString text = "supercalifragisiticexpialidocious!";
-
- QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
- QVERIFY(input);
- QSignalSpy spy(input, SIGNAL(inputMethodComposingChanged()));
-
- QCOMPARE(input->isInputMethodComposing(), false);
- {
- QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(input, &event);
- }
- QCOMPARE(input->isInputMethodComposing(), true);
- QCOMPARE(spy.count(), 1);
-
- {
- QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(input, &event);
- }
- QCOMPARE(spy.count(), 1);
-
- {
- QInputMethodEvent event;
- QGuiApplication::sendEvent(input, &event);
- }
- QCOMPARE(input->isInputMethodComposing(), false);
- QCOMPARE(spy.count(), 2);
-}
-
-void tst_qquicktextinput::cursorRectangleSize()
-{
- QQuickView *canvas = new QQuickView(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
- QVERIFY(canvas->rootObject() != 0);
- QQuickTextInput *textInput = qobject_cast<QQuickTextInput *>(canvas->rootObject());
-
- // make sure cursor rectangle is not at (0,0)
- textInput->setX(10);
- textInput->setY(10);
- textInput->setCursorPosition(3);
- QVERIFY(textInput != 0);
- textInput->setFocus(true);
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
-
- QInputMethodQueryEvent event(Qt::ImCursorRectangle);
- qApp->sendEvent(qApp->inputPanel()->inputItem(), &event);
- QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
-
- QRect cursorRectFromItem = textInput->cursorRectangle();
- QRectF cursorRectFromPositionToRectangle = textInput->positionToRectangle(textInput->cursorPosition());
-
- // item and input query cursor rectangles match
- QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
-
- // item cursor rectangle and positionToRectangle calculations match
- QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
-
- // item-canvas transform and input item transform match
- QCOMPARE(QQuickItemPrivate::get(textInput)->itemToCanvasTransform(), qApp->inputPanel()->inputItemTransform());
-
- // input panel cursorRectangle property and tranformed item cursor rectangle match
- QRectF sceneCursorRect = QQuickItemPrivate::get(textInput)->itemToCanvasTransform().mapRect(cursorRectFromItem);
- QCOMPARE(sceneCursorRect, qApp->inputPanel()->cursorRectangle());
-
- delete canvas;
-}
-
-void tst_qquicktextinput::tripleClickSelectsAll()
-{
- QString qmlfile = TESTDATA("positionAt.qml");
- QQuickView view(QUrl::fromLocalFile(qmlfile));
- view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
-
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
-
- QQuickTextInput* input = qobject_cast<QQuickTextInput*>(view.rootObject());
- QVERIFY(input);
-
- QLatin1String hello("Hello world!");
- input->setSelectByMouse(true);
- input->setText(hello);
-
- // Clicking on the same point inside TextInput three times in a row
- // should trigger a triple click, thus selecting all the text.
- QPoint pointInside = input->pos().toPoint() + QPoint(2,2);
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
- QGuiApplication::processEvents();
- QCOMPARE(input->selectedText(), hello);
-
- // Now it simulates user moving the mouse between the second and the third click.
- // In this situation, we don't expect a triple click.
- QPoint pointInsideButFar = QPoint(input->width(),input->height()) - QPoint(2,2);
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInsideButFar);
- QGuiApplication::processEvents();
- QVERIFY(input->selectedText().isEmpty());
-
- // And now we press the third click too late, so no triple click event is triggered.
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
- QGuiApplication::processEvents();
- QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 1);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
- QGuiApplication::processEvents();
- QVERIFY(input->selectedText().isEmpty());
-}
-
-void tst_qquicktextinput::QTBUG_19956_data()
-{
- QTest::addColumn<QString>("url");
- QTest::newRow("intvalidator") << "qtbug-19956int.qml";
- QTest::newRow("doublevalidator") << "qtbug-19956double.qml";
-}
-
-void tst_qquicktextinput::keySequence_data()
-{
- QTest::addColumn<QString>("text");
- QTest::addColumn<QKeySequence>("sequence");
- QTest::addColumn<int>("selectionStart");
- QTest::addColumn<int>("selectionEnd");
- QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<QString>("expectedText");
- QTest::addColumn<QString>("selectedText");
-
- // 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);
- QTest::newRow("select end of line")
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
- << 44 << standard.at(0) << standard.at(0).mid(5);
- QTest::newRow("select end of document") // ### Not handled.
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
- << 3 << standard.at(0) << QString();
- QTest::newRow("select end of block")
- << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
- << 44 << standard.at(0) << standard.at(0).mid(18);
- QTest::newRow("delete end of line")
- << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
- << 24 << standard.at(0).mid(0, 24) << QString();
- QTest::newRow("move to start of line")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
- << 0 << standard.at(0) << QString();
- QTest::newRow("move to start of block")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
- << 0 << standard.at(0) << QString();
- 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")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
- << 2 << standard.at(0) << QString();
- QTest::newRow("select next char")
- << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
- << 24 << standard.at(0) << standard.at(0).mid(23, 1);
- QTest::newRow("select previous char")
- << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
- << 18 << standard.at(0) << standard.at(0).mid(18, 1);
- QTest::newRow("move to next word")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
- << 10 << standard.at(0) << QString();
- QTest::newRow("move to previous word")
- << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
- << 4 << standard.at(0) << QString();
- QTest::newRow("select previous word")
- << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
- << 10 << standard.at(0) << standard.at(0).mid(10, 1);
- 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();
- 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();
- 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();
- 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();
-}
-
-void tst_qquicktextinput::keySequence()
-{
- QFETCH(QString, text);
- QFETCH(QKeySequence, sequence);
- QFETCH(int, selectionStart);
- QFETCH(int, selectionEnd);
- QFETCH(int, cursorPosition);
- QFETCH(QString, expectedText);
- QFETCH(QString, selectedText);
-
- if (sequence.isEmpty()) {
- QSKIP("Key sequence is undefined");
- }
-
- QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; text: \"" + text + "\" }";
- QDeclarativeComponent 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);
-
- textInput->select(selectionStart, selectionEnd);
-
- simulateKeys(&canvas, sequence);
-
- QCOMPARE(textInput->cursorPosition(), cursorPosition);
- QCOMPARE(textInput->text(), expectedText);
- QCOMPARE(textInput->selectedText(), selectedText);
-}
-
-#define NORMAL 0
-#define REPLACE_UNTIL_END 1
-
-void tst_qquicktextinput::undo_data()
-{
- QTest::addColumn<QStringList>("insertString");
- QTest::addColumn<IntList>("insertIndex");
- QTest::addColumn<IntList>("insertMode");
- QTest::addColumn<QStringList>("expectedString");
- QTest::addColumn<bool>("use_keys");
-
- for (int i=0; i<2; i++) {
- QString keys_str = "keyboard";
- bool use_keys = true;
- if (i==0) {
- keys_str = "insert";
- use_keys = false;
- }
-
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "1";
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "5";
-
- insertIndex << 1;
- insertMode << NORMAL;
- insertString << "3";
-
- insertIndex << 1;
- insertMode << NORMAL;
- insertString << "2";
-
- insertIndex << 3;
- insertMode << NORMAL;
- insertString << "4";
-
- expectedString << "12345";
- expectedString << "1235";
- expectedString << "135";
- expectedString << "15";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "World"; // World
-
- insertIndex << 0;
- insertMode << NORMAL;
- insertString << "Hello"; // HelloWorld
-
- insertIndex << 0;
- insertMode << NORMAL;
- insertString << "Well"; // WellHelloWorld
-
- insertIndex << 9;
- insertMode << NORMAL;
- insertString << "There"; // WellHelloThereWorld;
-
- expectedString << "WellHelloThereWorld";
- expectedString << "WellHelloWorld";
- expectedString << "HelloWorld";
- expectedString << "World";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- {
- IntList insertIndex;
- IntList insertMode;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << "Ensuring";
-
- insertIndex << -1;
- insertMode << NORMAL;
- insertString << " instan";
-
- insertIndex << 9;
- insertMode << NORMAL;
- insertString << "an ";
-
- insertIndex << 10;
- insertMode << REPLACE_UNTIL_END;
- insertString << " unique instance.";
-
- expectedString << "Ensuring a unique instance.";
- expectedString << "Ensuring an instan";
- expectedString << "Ensuring instan";
- expectedString << "";
-
- QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
- insertString <<
- insertIndex <<
- insertMode <<
- expectedString <<
- bool(use_keys);
- }
- }
-}
-
-void tst_qquicktextinput::undo()
-{
- QFETCH(QStringList, insertString);
- QFETCH(IntList, insertIndex);
- QFETCH(IntList, insertMode);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
- QDeclarativeComponent 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);
-
- int i;
-
-// STEP 1: First build up an undo history by inserting or typing some strings...
- for (i = 0; i < insertString.size(); ++i) {
- if (insertIndex[i] > -1)
- textInput->setCursorPosition(insertIndex[i]);
-
- // experimental stuff
- if (insertMode[i] == REPLACE_UNTIL_END) {
- textInput->select(insertIndex[i], insertIndex[i] + 8);
-
- // This is what I actually want...
- // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
- }
-
- for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
- }
-
-// STEP 2: Next call undo several times and see if we can restore to the previous state
- for (i = 0; i < expectedString.size() - 1; ++i) {
- QCOMPARE(textInput->text(), expectedString[i]);
- simulateKeys(&canvas, QKeySequence::Undo);
- }
-
-// STEP 3: Verify that we have undone everything
- QVERIFY(textInput->text().isEmpty());
-}
-
-void tst_qquicktextinput::redo_data()
-{
- QTest::addColumn<QStringList>("insertString");
- QTest::addColumn<IntList>("insertIndex");
- QTest::addColumn<QStringList>("expectedString");
-
- {
- IntList insertIndex;
- QStringList insertString;
- QStringList expectedString;
-
- insertIndex << -1;
- insertString << "World"; // World
- insertIndex << 0;
- insertString << "Hello"; // HelloWorld
- insertIndex << 0;
- insertString << "Well"; // WellHelloWorld
- insertIndex << 9;
- insertString << "There"; // WellHelloThereWorld;
-
- expectedString << "World";
- expectedString << "HelloWorld";
- expectedString << "WellHelloWorld";
- expectedString << "WellHelloThereWorld";
-
- QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
- }
-}
-
-void tst_qquicktextinput::redo()
-{
- QFETCH(QStringList, insertString);
- QFETCH(IntList, insertIndex);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
- QDeclarativeComponent 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);
-
- int i;
- // inserts the diff strings at diff positions
- for (i = 0; i < insertString.size(); ++i) {
- if (insertIndex[i] > -1)
- textInput->setCursorPosition(insertIndex[i]);
- for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
- }
-
- // undo everything
- while (!textInput->text().isEmpty())
- simulateKeys(&canvas, QKeySequence::Undo);
-
- for (i = 0; i < expectedString.size(); ++i) {
- simulateKeys(&canvas, QKeySequence::Redo);
- QCOMPARE(textInput->text() , expectedString[i]);
- }
-}
-
-void tst_qquicktextinput::undo_keypressevents_data()
-{
- QTest::addColumn<KeyList>("keys");
- QTest::addColumn<QStringList>("expectedString");
-
- {
- KeyList keys;
- QStringList expectedString;
-
- keys << "AFRAID"
- << Qt::Key_Home
- << "VERY"
- << Qt::Key_Left
- << Qt::Key_Left
- << Qt::Key_Left
- << Qt::Key_Left
- << "BE"
- << Qt::Key_End
- << "!";
-
- expectedString << "BEVERYAFRAID!";
- expectedString << "BEVERYAFRAID";
- expectedString << "VERYAFRAID";
- expectedString << "AFRAID";
-
- QTest::newRow("Inserts and moving cursor") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting '1234'
- keys << "1234" << Qt::Key_Home
- // skipping '12'
- << Qt::Key_Right << Qt::Key_Right
- // selecting '34'
- << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
- // deleting '34'
- << Qt::Key_Delete;
-
- expectedString << "12";
- expectedString << "1234";
-
- QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'AB12'
- keys << "AB12"
- << Qt::Key_Home
- // selecting 'AB'
- << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
- << 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;
-
- expectedString << "AB";
- expectedString << "AB12";
-
- QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'ABCD'
- keys << "abcd"
- //move left two
- << Qt::Key_Left << Qt::Key_Left
- // inserting '1234'
- << "1234"
- // selecting '1234'
- << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
- // overwriting '1234' with '5'
- << "5"
- // undoing deletion of 'AB'
- << QKeySequence::Undo
- // overwriting '1234' with '6'
- << "6";
-
- expectedString << "ab6cd";
- // for versions previous to 3.2 we overwrite needed two undo operations
- expectedString << "ab1234cd";
- expectedString << "abcd";
-
- QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting 'ABC'
- keys << "ABC"
- // removes 'C'
- << Qt::Key_Backspace;
-
- expectedString << "AB";
- expectedString << "ABC";
-
- QTest::newRow("Inserts,backspace") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- keys << "ABC"
- // removes 'C'
- << Qt::Key_Backspace
- // inserting 'Z'
- << "Z";
-
- expectedString << "ABZ";
- expectedString << "AB";
- expectedString << "ABC";
-
- QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
- } {
- KeyList keys;
- QStringList expectedString;
-
- // inserting '123'
- keys << "123" << Qt::Key_Home
- // selecting '123'
- << (Qt::Key_End | Qt::ShiftModifier)
- // overwriting '123' with 'ABC'
- << "ABC";
-
- expectedString << "ABC";
- // for versions previous to 3.2 we overwrite needed two undo operations
- expectedString << "123";
-
- QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
- }
-}
-
-void tst_qquicktextinput::undo_keypressevents()
-{
- QFETCH(KeyList, keys);
- QFETCH(QStringList, expectedString);
-
- QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
- QDeclarativeComponent 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);
-
- for (int i = 0; i < expectedString.size(); ++i) {
- QCOMPARE(textInput->text() , expectedString[i]);
- simulateKeys(&canvas, QKeySequence::Undo);
- }
- QVERIFY(textInput->text().isEmpty());
-}
-
-void tst_qquicktextinput::QTBUG_19956()
-{
- QFETCH(QString, url);
-
- QQuickView canvas(QUrl::fromLocalFile(TESTDATA(url)));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
- QVERIFY(input);
- input->setFocus(true);
- QVERIFY(input->hasActiveFocus());
-
- QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 30);
- QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
- QCOMPARE(canvas.rootObject()->property("text").toString(), QString("20"));
- QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("topvalue", 15);
- QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 15);
- QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("topvalue", 25);
- QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 25);
- QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("bottomvalue", 21);
- QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 21);
- QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("bottomvalue", 10);
- QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
- QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
-}
-
-void tst_qquicktextinput::QTBUG_19956_regexp()
-{
- QUrl url = QUrl::fromLocalFile(TESTDATA("qtbug-19956regexp.qml"));
-
- QString warning = url.toString() + ":11: Unable to assign [undefined] to QRegExp";
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
-
- QQuickView canvas(url);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
- QVERIFY(input);
- input->setFocus(true);
- QVERIFY(input->hasActiveFocus());
-
- canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
- QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
- QCOMPARE(canvas.rootObject()->property("text").toString(), QString("abc"));
- QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("regexvalue", QRegExp("abcd"));
- QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abcd"));
- QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
-
- canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
- QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
- QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
-}
-
-QTEST_MAIN(tst_qquicktextinput)
-
-#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/declarative/qquickview/qquickview.pro b/tests/auto/declarative/qquickview/qquickview.pro
deleted file mode 100644
index c5cc3ce6a7..0000000000
--- a/tests/auto/declarative/qquickview/qquickview.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickview
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickview.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-QT += core-private gui-private declarative-private testlib
diff --git a/tests/auto/declarative/qquickview/tst_qquickview.cpp b/tests/auto/declarative/qquickview/tst_qquickview.cpp
deleted file mode 100644
index fc480b5fca..0000000000
--- a/tests/auto/declarative/qquickview/tst_qquickview.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 <qtest.h>
-#include <QtTest/QSignalSpy>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qquickview.h>
-#include <QtDeclarative/qquickitem.h>
-#include "../shared/util.h"
-#include <QtGui/QWindow>
-#include <QtCore/QDebug>
-
-class tst_QQuickView : public QObject
-{
- Q_OBJECT
-public:
- tst_QQuickView();
-
-private slots:
- void resizemodeitem();
- void errors();
-};
-
-
-tst_QQuickView::tst_QQuickView()
-{
-}
-
-void tst_QQuickView::resizemodeitem()
-{
- QWindow window;
- window.setGeometry(0, 0, 400, 400);
-
- QQuickView *canvas = new QQuickView(&window);
- QVERIFY(canvas);
- canvas->setResizeMode(QQuickView::SizeRootObjectToView);
- QCOMPARE(QSize(0,0), canvas->initialSize());
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
- QQuickItem* item = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(item);
- window.show();
-
- canvas->show();
-
- // initial size from root object
- QCOMPARE(item->width(), 200.0);
- QCOMPARE(item->height(), 200.0);
- QCOMPARE(canvas->size(), QSize(200, 200));
- QCOMPARE(canvas->size(), canvas->sizeHint());
- QCOMPARE(canvas->size(), canvas->initialSize());
-
- // size update from view
- canvas->resize(QSize(80,100));
-
- QTRY_COMPARE(item->width(), 80.0);
- QCOMPARE(item->height(), 100.0);
- QCOMPARE(canvas->size(), QSize(80, 100));
- QCOMPARE(canvas->size(), canvas->sizeHint());
-
- canvas->setResizeMode(QQuickView::SizeViewToRootObject);
-
- // size update from view disabled
- canvas->resize(QSize(60,80));
- QCOMPARE(item->width(), 80.0);
- QCOMPARE(item->height(), 100.0);
- QTest::qWait(50);
- QCOMPARE(canvas->size(), QSize(60, 80));
-
- // size update from root object
- item->setWidth(250);
- item->setHeight(350);
- QCOMPARE(item->width(), 250.0);
- QCOMPARE(item->height(), 350.0);
- QTRY_COMPARE(canvas->size(), QSize(250, 350));
- QCOMPARE(canvas->size(), QSize(250, 350));
- QCOMPARE(canvas->size(), canvas->sizeHint());
-
- // reset canvas
- window.hide();
- delete canvas;
- canvas = new QQuickView(&window);
- QVERIFY(canvas);
- canvas->setResizeMode(QQuickView::SizeViewToRootObject);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
- item = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(item);
- window.show();
-
- canvas->show();
-
- // initial size for root object
- QCOMPARE(item->width(), 200.0);
- QCOMPARE(item->height(), 200.0);
- QCOMPARE(canvas->size(), canvas->sizeHint());
- QCOMPARE(canvas->size(), canvas->initialSize());
-
- // size update from root object
- item->setWidth(80);
- item->setHeight(100);
- QCOMPARE(item->width(), 80.0);
- QCOMPARE(item->height(), 100.0);
- QTRY_COMPARE(canvas->size(), QSize(80, 100));
- QCOMPARE(canvas->size(), QSize(80, 100));
- QCOMPARE(canvas->size(), canvas->sizeHint());
-
- // size update from root object disabled
- canvas->setResizeMode(QQuickView::SizeRootObjectToView);
- item->setWidth(60);
- item->setHeight(80);
- QCOMPARE(canvas->width(), 80);
- QCOMPARE(canvas->height(), 100);
- QCOMPARE(QSize(item->width(), item->height()), canvas->sizeHint());
-
- // size update from view
- canvas->resize(QSize(200,300));
- QTest::qWait(50);
- QCOMPARE(item->width(), 200.0);
- QCOMPARE(item->height(), 300.0);
- QCOMPARE(canvas->size(), QSize(200, 300));
- QCOMPARE(canvas->size(), canvas->sizeHint());
-
- window.hide();
- delete canvas;
-
- // if we set a specific size for the view then it should keep that size
- // for SizeRootObjectToView mode.
- canvas = new QQuickView(&window);
- canvas->resize(300, 300);
- canvas->setResizeMode(QQuickView::SizeRootObjectToView);
- QCOMPARE(QSize(0,0), canvas->initialSize());
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
- canvas->resize(300, 300);
- item = qobject_cast<QQuickItem*>(canvas->rootObject());
- QVERIFY(item);
- window.show();
-
- canvas->show();
- QTest::qWait(50);
-
- // initial size from root object
- QCOMPARE(item->width(), 300.0);
- QCOMPARE(item->height(), 300.0);
- QCOMPARE(canvas->size(), QSize(300, 300));
- QCOMPARE(canvas->size(), canvas->sizeHint());
- QCOMPARE(canvas->initialSize(), QSize(200, 200)); // initial object size
-
- delete canvas;
-}
-
-static void silentErrorsMsgHandler(QtMsgType, const char *)
-{
-}
-
-void tst_QQuickView::errors()
-{
- QQuickView *canvas = new QQuickView;
- QVERIFY(canvas);
- QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
- canvas->setSource(QUrl::fromLocalFile(TESTDATA("error1.qml")));
- qInstallMsgHandler(old);
- QVERIFY(canvas->status() == QQuickView::Error);
- QVERIFY(canvas->errors().count() == 1);
- delete canvas;
-}
-
-
-QTEST_MAIN(tst_QQuickView)
-
-#include "tst_qquickview.moc"
diff --git a/tests/auto/declarative/qquickvisualdatamodel/qquickvisualdatamodel.pro b/tests/auto/declarative/qquickvisualdatamodel/qquickvisualdatamodel.pro
deleted file mode 100644
index 35e627c1ad..0000000000
--- a/tests/auto/declarative/qquickvisualdatamodel/qquickvisualdatamodel.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickvisualdatamodel
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickvisualdatamodel.cpp
-
-testDataFiles.files = data
-testDataFiles.path = .
-DEPLOYMENT += testDataFiles
-
-CONFIG += parallel_test
-
-QT += core-private gui-private v8-private declarative-private widgets testlib
diff --git a/tests/auto/declarative/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/declarative/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
deleted file mode 100644
index 0278b0cf2c..0000000000
--- a/tests/auto/declarative/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ /dev/null
@@ -1,1865 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** 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 "../shared/util.h"
-#include <qtest.h>
-#include <QtTest/QSignalSpy>
-#include <QStandardItemModel>
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativecontext.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qquickview.h>
-#include <private/qquicklistview_p.h>
-#include <private/qquicktext_p.h>
-#include <private/qquickvisualdatamodel_p.h>
-#include <private/qdeclarativevaluetype_p.h>
-#include <private/qdeclarativechangeset_p.h>
-#include <private/qdeclarativeengine_p.h>
-#include <math.h>
-
-template <typename T, int N> int lengthOf(const T (&)[N]) { return N; }
-
-static void initStandardTreeModel(QStandardItemModel *model)
-{
- QStandardItem *item;
- item = new QStandardItem(QLatin1String("Row 1 Item"));
- model->insertRow(0, item);
-
- item = new QStandardItem(QLatin1String("Row 2 Item"));
- item->setCheckable(true);
- model->insertRow(1, item);
-
- QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
- item->setChild(0, childItem);
-
- item = new QStandardItem(QLatin1String("Row 3 Item"));
- item->setIcon(QIcon());
- model->insertRow(2, item);
-}
-
-class SingleRoleModel : public QAbstractListModel
-{
- Q_OBJECT
-
-public:
- SingleRoleModel(const QByteArray &role = "name", QObject * /* parent */ = 0) {
- QHash<int, QByteArray> roles;
- roles.insert(Qt::DisplayRole , role);
- setRoleNames(roles);
- list << "one" << "two" << "three" << "four";
- }
-
- void emitMove(int sourceFirst, int sourceLast, int destinationChild) {
- emit beginMoveRows(QModelIndex(), sourceFirst, sourceLast, QModelIndex(), destinationChild);
- emit endMoveRows();
- }
-
- QStringList list;
-
-public slots:
- void set(int idx, QString string) {
- list[idx] = string;
- emit dataChanged(index(idx,0), index(idx,0));
- }
-
-protected:
- int rowCount(const QModelIndex & /* parent */ = QModelIndex()) const {
- return list.count();
- }
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
- if (role == Qt::DisplayRole)
- return list.at(index.row());
- return QVariant();
- }
-};
-
-
-class tst_qquickvisualdatamodel : public QObject
-{
- Q_OBJECT
-public:
- tst_qquickvisualdatamodel();
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void rootIndex();
- void updateLayout_data();
- void updateLayout();
- void childChanged_data();
- void childChanged();
- void objectListModel();
- void singleRole();
- void modelProperties();
- void noDelegate_data();
- void noDelegate();
- void itemsDestroyed_data();
- void itemsDestroyed();
- void qaimRowsMoved();
- void qaimRowsMoved_data();
- void remove_data();
- void remove();
- void move_data();
- void move();
- void groups_data();
- void groups();
- void invalidGroups();
- void get();
- void onChanged_data();
- void onChanged();
- void create();
- void incompleteModel();
-
-private:
- template <int N> void groups_verify(
- const SingleRoleModel &model,
- QQuickItem *contentItem,
- const int (&mIndex)[N],
- const int (&iIndex)[N],
- const int (&vIndex)[N],
- const int (&sIndex)[N],
- const bool (&vMember)[N],
- const bool (&sMember)[N]);
-
- template <int N> void get_verify(
- const SingleRoleModel &model,
- QQuickVisualDataModel *visualModel,
- QQuickVisualDataGroup *visibleItems,
- QQuickVisualDataGroup *selectedItems,
- const int (&mIndex)[N],
- const int (&iIndex)[N],
- const int (&vIndex)[N],
- const int (&sIndex)[N],
- const bool (&vMember)[N],
- const bool (&sMember)[N]);
-
- bool failed;
- QDeclarativeEngine engine;
- template<typename T>
- T *findItem(QQuickItem *parent, const QString &objectName, int index);
-};
-
-Q_DECLARE_METATYPE(QDeclarativeChangeSet)
-
-void tst_qquickvisualdatamodel::initTestCase()
-{
- qRegisterMetaType<QDeclarativeChangeSet>();
-}
-
-void tst_qquickvisualdatamodel::cleanupTestCase()
-{
-
-}
-class DataObject : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
-
-public:
- DataObject(QObject *parent=0) : QObject(parent) {}
- DataObject(const QString &name, const QString &color, QObject *parent=0)
- : QObject(parent), m_name(name), m_color(color) { }
-
-
- QString name() const { return m_name; }
- void setName(const QString &name) {
- if (name != m_name) {
- m_name = name;
- emit nameChanged();
- }
- }
-
- QString color() const { return m_color; }
- void setColor(const QString &color) {
- if (color != m_color) {
- m_color = color;
- emit colorChanged();
- }
- }
-
-signals:
- void nameChanged();
- void colorChanged();
-
-private:
- QString m_name;
- QString m_color;
-};
-
-template <typename T> static T evaluate(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- T result = expr.evaluate().value<T>();
- if (expr.hasError())
- qWarning() << expr.error().toString();
- return result;
-}
-
-template <> void evaluate<void>(QObject *scope, const QString &expression)
-{
- QDeclarativeExpression expr(qmlContext(scope), scope, expression);
- expr.evaluate();
- if (expr.hasError())
- qWarning() << expr.error().toString();
-}
-
-tst_qquickvisualdatamodel::tst_qquickvisualdatamodel()
-{
-}
-
-void tst_qquickvisualdatamodel::rootIndex()
-{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
-
- engine.rootContext()->setContextProperty("myModel", &model);
-
- QQuickVisualDataModel *obj = qobject_cast<QQuickVisualDataModel*>(c.create());
- QVERIFY(obj != 0);
-
- QMetaObject::invokeMethod(obj, "setRoot");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
-
- QMetaObject::invokeMethod(obj, "setRootToParent");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
-
- QMetaObject::invokeMethod(obj, "setRoot");
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
- model.clear(); // will emit modelReset()
- QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
-
- delete obj;
-}
-
-void tst_qquickvisualdatamodel::updateLayout_data()
-{
- QTest::addColumn<QUrl>("source");
-
- QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
- QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
-}
-
-void tst_qquickvisualdatamodel::updateLayout()
-{
- QFETCH(QUrl, source);
-
- QQuickView view;
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
-
- view.rootContext()->setContextProperty("myModel", &model);
-
- view.setSource(source);
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 1 Item"));
- name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 2 Item"));
- name = findItem<QQuickText>(contentItem, "display", 2);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 3 Item"));
-
- model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
-
- name = findItem<QQuickText>(contentItem, "display", 0);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 3 Item"));
- name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 2 Item"));
- name = findItem<QQuickText>(contentItem, "display", 2);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 1 Item"));
-}
-
-void tst_qquickvisualdatamodel::childChanged_data()
-{
- QTest::addColumn<QUrl>("source");
-
- QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
- QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
-}
-
-void tst_qquickvisualdatamodel::childChanged()
-{
- QFETCH(QUrl, source);
-
- QQuickView view;
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
-
- view.rootContext()->setContextProperty("myModel", &model);
-
- view.setSource(source);
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *vdm = listview->findChild<QQuickVisualDataModel*>("visualModel");
- vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
- QCOMPARE(listview->count(), 1);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 2 Child Item"));
-
- model.item(1,0)->child(0,0)->setText("Row 2 updated child");
-
- name = findItem<QQuickText>(contentItem, "display", 0);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 2 updated child"));
-
- model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
- QCOMPARE(listview->count(), 2);
-
- name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name != 0);
- QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
-
- model.item(1,0)->takeRow(1);
- name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name == 0);
-
- vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
- QCOMPARE(listview->count(), 3);
- name = findItem<QQuickText>(contentItem, "display", 0);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 1 Item"));
- name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 2 Item"));
- name = findItem<QQuickText>(contentItem, "display", 2);
- QVERIFY(name);
- QCOMPARE(name->text(), QString("Row 3 Item"));
-}
-
-void tst_qquickvisualdatamodel::objectListModel()
-{
- QQuickView view;
-
- QList<QObject*> dataList;
- dataList.append(new DataObject("Item 1", "red"));
- dataList.append(new DataObject("Item 2", "green"));
- dataList.append(new DataObject("Item 3", "blue"));
- dataList.append(new DataObject("Item 4", "yellow"));
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("objectlist.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "name", 0);
- QCOMPARE(name->text(), QString("Item 1"));
-
- QQuickText *section = findItem<QQuickText>(contentItem, "section", 0);
- QCOMPARE(section->text(), QString("Item 1"));
-
- dataList[0]->setProperty("name", QLatin1String("Changed"));
- QCOMPARE(name->text(), QString("Changed"));
-}
-
-void tst_qquickvisualdatamodel::singleRole()
-{
- {
- QQuickView view;
-
- SingleRoleModel model;
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole1.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
- QCOMPARE(name->text(), QString("two"));
-
- model.set(1, "Changed");
- QCOMPARE(name->text(), QString("Changed"));
- }
- {
- QQuickView view;
-
- SingleRoleModel model;
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
- QCOMPARE(name->text(), QString("two"));
-
- model.set(1, "Changed");
- QCOMPARE(name->text(), QString("Changed"));
- }
- {
- QQuickView view;
-
- SingleRoleModel model("modelData");
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
- QCOMPARE(name->text(), QString("two"));
-
- model.set(1, "Changed");
- QCOMPARE(name->text(), QString("Changed"));
- }
-}
-
-void tst_qquickvisualdatamodel::modelProperties()
-{
- {
- QQuickView view;
-
- SingleRoleModel model;
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(),QString("two"));
- QCOMPARE(delegate->property("test2").toString(),QString("two"));
- QCOMPARE(delegate->property("test3").toString(),QString("two"));
- QCOMPARE(delegate->property("test4").toString(),QString("two"));
- QVERIFY(!delegate->property("test9").isValid());
- QCOMPARE(delegate->property("test5").toString(),QString(""));
- QVERIFY(delegate->property("test6").value<QObject*>() != 0);
- QCOMPARE(delegate->property("test7").toInt(),1);
- QCOMPARE(delegate->property("test8").toInt(),1);
- }
-
- {
- QQuickView view;
-
- QList<QObject*> dataList;
- dataList.append(new DataObject("Item 1", "red"));
- dataList.append(new DataObject("Item 2", "green"));
- dataList.append(new DataObject("Item 3", "blue"));
- dataList.append(new DataObject("Item 4", "yellow"));
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
- QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
- QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
- QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
- QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
- QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
- QVERIFY(delegate->property("test6").value<QObject*>() != 0);
- QCOMPARE(delegate->property("test7").toInt(),1);
- QCOMPARE(delegate->property("test8").toInt(),1);
- }
-
- {
- QQuickView view;
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
-
- view.rootContext()->setContextProperty("myModel", &model);
-
- QUrl source(QUrl::fromLocalFile(TESTDATA("modelproperties2.qml")));
-
- //3 items, 3 i each
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
- QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
-
- view.setSource(source);
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
- QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
- QVERIFY(!delegate->property("test3").isValid());
- QVERIFY(!delegate->property("test4").isValid());
- QVERIFY(!delegate->property("test5").isValid());
- QVERIFY(!delegate->property("test9").isValid());
- QVERIFY(delegate->property("test6").value<QObject*>() != 0);
- QCOMPARE(delegate->property("test7").toInt(),1);
- QCOMPARE(delegate->property("test8").toInt(),1);
- }
-
- //### should also test QStringList and QVariantList
-}
-
-void tst_qquickvisualdatamodel::noDelegate_data()
-{
- QTest::addColumn<QUrl>("source");
-
- QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
- QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
-}
-
-void tst_qquickvisualdatamodel::noDelegate()
-{
- QFETCH(QUrl, source);
-
- QQuickView view;
-
- QStandardItemModel model;
- initStandardTreeModel(&model);
-
- view.rootContext()->setContextProperty("myModel", &model);
-
- view.setSource(source);
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickVisualDataModel *vdm = listview->findChild<QQuickVisualDataModel*>("visualModel");
- QVERIFY(vdm != 0);
- QCOMPARE(vdm->count(), 3);
-
- vdm->setDelegate(0);
- QCOMPARE(vdm->count(), 0);
-}
-
-void tst_qquickvisualdatamodel::itemsDestroyed_data()
-{
- QTest::addColumn<QUrl>("source");
-
- QTest::newRow("listView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_listView.qml"));
- QTest::newRow("package") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_package.qml"));
- QTest::newRow("pathView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_pathView.qml"));
- QTest::newRow("repeater") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_repeater.qml"));
-}
-
-void tst_qquickvisualdatamodel::itemsDestroyed()
-{
- QFETCH(QUrl, source);
-
- QDeclarativeGuard<QQuickItem> delegate;
-
- {
- QQuickView view;
- QStandardItemModel model;
- initStandardTreeModel(&model);
- view.rootContext()->setContextProperty("myModel", &model);
- view.setSource(source);
-
- view.show();
- QTest::qWaitForWindowShown(&view);
-
- QVERIFY(delegate = findItem<QQuickItem>(view.rootItem(), "delegate", 1));
- }
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- QVERIFY(!delegate);
-}
-
-void tst_qquickvisualdatamodel::qaimRowsMoved()
-{
- // Test parameters passed in QAIM::rowsMoved() signal are converted correctly
- // when translated and emitted as the QListModelInterface::itemsMoved() signal
- QFETCH(int, sourceFirst);
- QFETCH(int, sourceLast);
- QFETCH(int, destinationChild);
- QFETCH(int, expectFrom);
- QFETCH(int, expectTo);
- QFETCH(int, expectCount);
-
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
-
- SingleRoleModel model;
- model.list.clear();
- for (int i=0; i<30; i++)
- model.list << ("item " + i);
- engine.rootContext()->setContextProperty("myModel", &model);
-
- QQuickVisualDataModel *obj = qobject_cast<QQuickVisualDataModel*>(c.create());
- QVERIFY(obj != 0);
-
- QSignalSpy spy(obj, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)));
- model.emitMove(sourceFirst, sourceLast, destinationChild);
- // QAbstractItemModel also emits the changed signal when items are moved.
- QCOMPARE(spy.count(), 2);
-
- bool move = false;
- for (int i = 0; i < 2; ++i) {
- QCOMPARE(spy[1].count(), 2);
- QDeclarativeChangeSet changeSet = spy[i][0].value<QDeclarativeChangeSet>();
- if (!changeSet.changes().isEmpty())
- continue;
- move = true;
- QCOMPARE(changeSet.removes().count(), 1);
- QCOMPARE(changeSet.removes().at(0).index, expectFrom);
- QCOMPARE(changeSet.removes().at(0).count, expectCount);
- QCOMPARE(changeSet.inserts().count(), 1);
- QCOMPARE(changeSet.inserts().at(0).index, expectTo);
- QCOMPARE(changeSet.inserts().at(0).count, expectCount);
- QCOMPARE(changeSet.removes().at(0).moveId, changeSet.inserts().at(0).moveId);
- QCOMPARE(spy[i][1].toBool(), false);
- }
- QVERIFY(move);
-
- delete obj;
-}
-
-void tst_qquickvisualdatamodel::qaimRowsMoved_data()
-{
- QTest::addColumn<int>("sourceFirst");
- QTest::addColumn<int>("sourceLast");
- QTest::addColumn<int>("destinationChild");
- QTest::addColumn<int>("expectFrom");
- QTest::addColumn<int>("expectTo");
- QTest::addColumn<int>("expectCount");
-
- QTest::newRow("move 1 forward")
- << 1 << 1 << 6
- << 1 << 5 << 1;
-
- QTest::newRow("move 1 backwards")
- << 4 << 4 << 1
- << 4 << 1 << 1;
-
- QTest::newRow("move multiple forwards")
- << 0 << 2 << 13
- << 0 << 10 << 3;
-
- QTest::newRow("move multiple forwards, with same to")
- << 0 << 1 << 3
- << 0 << 1 << 2;
-
- QTest::newRow("move multiple backwards")
- << 10 << 14 << 1
- << 10 << 1 << 5;
-}
-
-void tst_qquickvisualdatamodel::remove_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<QString>("package delegate");
-
- QTest::newRow("item delegate")
- << QUrl::fromLocalFile(TESTDATA("groups.qml"))
- << QString();
- QTest::newRow("package")
- << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
- << QString("package.");
-}
-
-void tst_qquickvisualdatamodel::remove()
-{
- QQuickView view;
-
- SingleRoleModel model;
- model.list = QStringList()
- << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six"
- << "seven"
- << "eight"
- << "nine"
- << "ten"
- << "eleven"
- << "twelve";
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
- QVERIFY(visualModel);
-
- {
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.remove(2)");
- QCOMPARE(listview->count(), 11);
- QCOMPARE(visualModel->items()->count(), 11);
- static const int mIndex[] = { 0, 1, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.remove(1, 4)");
- QCOMPARE(listview->count(), 7);
- QCOMPARE(visualModel->items()->count(), 7);
- static const int mIndex[] = { 0, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
- evaluate<void>(visualModel, "items.remove(-8, 4)");
- QCOMPARE(listview->count(), 7);
- QCOMPARE(visualModel->items()->count(), 7);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
- evaluate<void>(visualModel, "items.remove(12, 2)");
- QCOMPARE(listview->count(), 7);
- QCOMPARE(visualModel->items()->count(), 7);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
- evaluate<void>(visualModel, "items.remove(5, 3)");
- QCOMPARE(listview->count(), 7);
- QCOMPARE(visualModel->items()->count(), 7);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: invalid count");
- evaluate<void>(visualModel, "items.remove(5, -2)");
- QCOMPARE(listview->count(), 7);
- QCOMPARE(visualModel->items()->count(), 7);
- }
-}
-
-void tst_qquickvisualdatamodel::move_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<QString>("package delegate");
-
- QTest::newRow("item delegate")
- << QUrl::fromLocalFile(TESTDATA("groups.qml"))
- << QString();
- QTest::newRow("package")
- << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
- << QString("package.");
-}
-
-void tst_qquickvisualdatamodel::move()
-{
- QQuickView view;
-
- SingleRoleModel model;
- model.list = QStringList()
- << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six"
- << "seven"
- << "eight"
- << "nine"
- << "ten"
- << "eleven"
- << "twelve";
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
- QVERIFY(visualModel);
-
- {
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.move(2, 4)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 0, 1, 3, 4, 2, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.move(4, 2)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.move(8, 0, 4)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 8, 9,10,11, 0, 1, 2, 3, 4, 5, 6, 7 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- evaluate<void>(visualModel, "items.move(3, 4, 5)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- static const int mIndex[] = { 8, 9,10,4, 11, 0, 1, 2, 3, 5, 6, 7 };
- static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
-
- for (int i = 0; i < lengthOf(mIndex); ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
- QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
- QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
- }
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: invalid count");
- evaluate<void>(visualModel, "items.move(5, 2, -2)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
- evaluate<void>(visualModel, "items.move(-6, 2, 1)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
- evaluate<void>(visualModel, "items.move(15, 2, 1)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
- evaluate<void>(visualModel, "items.move(11, 1, 3)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
- evaluate<void>(visualModel, "items.move(2, -5, 1)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
- evaluate<void>(visualModel, "items.move(2, 14, 1)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
- evaluate<void>(visualModel, "items.move(2, 11, 4)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- }
-}
-
-void tst_qquickvisualdatamodel::groups_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<QString>("part");
-
- QTest::newRow("item delegate")
- << QUrl::fromLocalFile(TESTDATA("groups.qml"))
- << QString();
- QTest::newRow("package")
- << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
- << QString("visualModel.parts.package.");
-}
-
-template <int N> void tst_qquickvisualdatamodel::groups_verify(
- const SingleRoleModel &model,
- QQuickItem *contentItem,
- const int (&mIndex)[N],
- const int (&iIndex)[N],
- const int (&vIndex)[N],
- const int (&sIndex)[N],
- const bool (&vMember)[N],
- const bool (&sMember)[N])
-{
- failed = true;
- for (int i = 0; i < N; ++i) {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
- QVERIFY(delegate);
- QCOMPARE(evaluate<QString>(delegate, "test1"), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<int>(delegate, "test2") , mIndex[i]);
- QCOMPARE(evaluate<int>(delegate, "test3") , iIndex[i]);
- QCOMPARE(evaluate<bool>(delegate, "test4"), true);
- QCOMPARE(evaluate<int>(delegate, "test5") , vIndex[i]);
- QCOMPARE(evaluate<bool>(delegate, "test6"), vMember[i]);
- QCOMPARE(evaluate<int>(delegate, "test7") , sIndex[i]);
- QCOMPARE(evaluate<bool>(delegate, "test8"), sMember[i]);
- QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("items") , QBool(true));
- QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("visible") , QBool(vMember[i]));
- QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("selected"), QBool(sMember[i]));
- }
- failed = false;
-}
-
-#define VERIFY_GROUPS \
- groups_verify(model, contentItem, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
- QVERIFY(!failed)
-
-
-void tst_qquickvisualdatamodel::groups()
-{
- QFETCH(QUrl, source);
- QFETCH(QString, part);
-
- QQuickView view;
-
- SingleRoleModel model;
- model.list = QStringList()
- << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six"
- << "seven"
- << "eight"
- << "nine"
- << "ten"
- << "eleven"
- << "twelve";
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(source);
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *visualModel = listview->findChild<QQuickVisualDataModel *>("visualModel");
- QVERIFY(visualModel);
-
- QQuickVisualDataGroup *visibleItems = listview->findChild<QQuickVisualDataGroup *>("visibleItems");
- QVERIFY(visibleItems);
-
- QQuickVisualDataGroup *selectedItems = listview->findChild<QQuickVisualDataGroup *>("selectedItems");
- QVERIFY(selectedItems);
-
- const bool f = false;
- const bool t = true;
-
- {
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 0);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
- VERIFY_GROUPS;
- } {
- evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 1);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
- VERIFY_GROUPS;
- } {
- evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 4);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
- static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
- VERIFY_GROUPS;
- } {
- evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 11);
- QCOMPARE(selectedItems->count(), 5);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
- static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
- static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
- VERIFY_GROUPS;
- } {
- evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
- static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
- VERIFY_GROUPS;
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: invalid count");
- evaluate<void>(visualModel, "items.addGroups(11, -4, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
- evaluate<void>(visualModel, "items.addGroups(-1, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
- evaluate<void>(visualModel, "items.addGroups(14, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
- evaluate<void>(visualModel, "items.addGroups(11, 5, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: invalid count");
- evaluate<void>(visualModel, "items.setGroups(11, -4, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
- evaluate<void>(visualModel, "items.setGroups(-1, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
- evaluate<void>(visualModel, "items.setGroups(14, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
- evaluate<void>(visualModel, "items.setGroups(11, 5, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: invalid count");
- evaluate<void>(visualModel, "items.removeGroups(11, -4, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
- evaluate<void>(visualModel, "items.removeGroups(-1, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
- evaluate<void>(visualModel, "items.removeGroups(14, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
- evaluate<void>(visualModel, "items.removeGroups(11, 5, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- } {
- evaluate<void>(visualModel, part + "filterOnGroup = \"visible\"");
- QCOMPARE(listview->count(), 9);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("visible"));
- } {
- evaluate<void>(visualModel, part + "filterOnGroup = \"selected\"");
- QCOMPARE(listview->count(), 2);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("selected"));
- } {
- evaluate<void>(visualModel, part + "filterOnGroup = undefined");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("items"));
- } {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 5);
- QVERIFY(delegate);
-
- evaluate<void>(delegate, "hide()");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 8);
- QCOMPARE(selectedItems->count(), 2);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
- static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
- VERIFY_GROUPS;
- } {
- QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 5);
- QVERIFY(delegate);
-
- evaluate<void>(delegate, "select()");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 8);
- QCOMPARE(selectedItems->count(), 3);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
- static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
- static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
- VERIFY_GROUPS;
- } {
- evaluate<void>(visualModel, "items.move(2, 6, 3)");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 8);
- QCOMPARE(selectedItems->count(), 3);
- static const int mIndex [] = { 0, 1, 5, 6, 7, 8, 2, 3, 4, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7 };
- static const bool vMember[] = { t, t, f, f, f, t, f, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 };
- static const bool sMember[] = { f, f, t, f, f, t, f, f, f, t, f, f };
- VERIFY_GROUPS;
- }
-}
-
-template <int N> void tst_qquickvisualdatamodel::get_verify(
- const SingleRoleModel &model,
- QQuickVisualDataModel *visualModel,
- QQuickVisualDataGroup *visibleItems,
- QQuickVisualDataGroup *selectedItems,
- const int (&mIndex)[N],
- const int (&iIndex)[N],
- const int (&vIndex)[N],
- const int (&sIndex)[N],
- const bool (&vMember)[N],
- const bool (&sMember)[N])
-{
- failed = true;
- for (int i = 0; i < N; ++i) {
- QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.name").arg(i)), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.modelData").arg(i)), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).model.index").arg(i)), mIndex[i]);
- QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).itemsIndex").arg(i)), iIndex[i]);
- QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inItems").arg(i)), true);
- QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).visibleIndex").arg(i)), vIndex[i]);
- QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inVisible").arg(i)), vMember[i]);
- QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).selectedIndex").arg(i)), sIndex[i]);
- QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inSelected").arg(i)), sMember[i]);
- QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"items\")").arg(i)), true);
- QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"visible\")").arg(i)), vMember[i]);
- QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"selected\")").arg(i)), sMember[i]);
-
- if (vMember[i]) {
- QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.name").arg(vIndex[i])), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.modelData").arg(vIndex[i])), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).model.index").arg(vIndex[i])), mIndex[i]);
- QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).itemsIndex").arg(vIndex[i])), iIndex[i]);
- QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inItems").arg(vIndex[i])), true);
- QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).visibleIndex").arg(vIndex[i])), vIndex[i]);
- QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inVisible").arg(vIndex[i])), vMember[i]);
- QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).selectedIndex").arg(vIndex[i])), sIndex[i]);
- QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inSelected").arg(vIndex[i])), sMember[i]);
-
- QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"items\")").arg(vIndex[i])), true);
- QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"visible\")").arg(vIndex[i])), vMember[i]);
- QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"selected\")").arg(vIndex[i])), sMember[i]);
- }
- if (sMember[i]) {
- QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.name").arg(sIndex[i])), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.modelData").arg(sIndex[i])), model.list.at(mIndex[i]));
- QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).model.index").arg(sIndex[i])), mIndex[i]);
- QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).itemsIndex").arg(sIndex[i])), iIndex[i]);
- QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inItems").arg(sIndex[i])), true);
- QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).visibleIndex").arg(sIndex[i])), vIndex[i]);
- QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inVisible").arg(sIndex[i])), vMember[i]);
- QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).selectedIndex").arg(sIndex[i])), sIndex[i]);
- QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inSelected").arg(sIndex[i])), sMember[i]);
- QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"items\")").arg(sIndex[i])), true);
- QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"visible\")").arg(sIndex[i])), vMember[i]);
- QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"selected\")").arg(sIndex[i])), sMember[i]);
- }
- }
- failed = false;
-}
-
-#define VERIFY_GET \
- get_verify(model, visualModel, visibleItems, selectedItems, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
- QVERIFY(!failed)
-
-void tst_qquickvisualdatamodel::get()
-{
- QQuickView view;
-
- SingleRoleModel model;
- model.list = QStringList()
- << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six"
- << "seven"
- << "eight"
- << "nine"
- << "ten"
- << "eleven"
- << "twelve";
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
- QVERIFY(visualModel);
-
- QQuickVisualDataGroup *visibleItems = visualModel->findChild<QQuickVisualDataGroup *>("visibleItems");
- QVERIFY(visibleItems);
-
- QQuickVisualDataGroup *selectedItems = visualModel->findChild<QQuickVisualDataGroup *>("selectedItems");
- QVERIFY(selectedItems);
-
- QV8Engine *v8Engine = QDeclarativeEnginePrivate::getV8Engine(ctxt->engine());
- QVERIFY(v8Engine);
-
- const bool f = false;
- const bool t = true;
-
- {
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 0);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 1);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 12);
- QCOMPARE(selectedItems->count(), 4);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
- static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 11);
- QCOMPARE(selectedItems->count(), 5);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
- static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
- static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
- static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.get(5).inVisible = false");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 8);
- QCOMPARE(selectedItems->count(), 2);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
- static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.get(5).inSelected = true");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 8);
- QCOMPARE(selectedItems->count(), 3);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
- static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
- static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
- VERIFY_GET;
- } {
- evaluate<void>(visualModel, "items.get(5).groups = [\"visible\", \"items\"]");
- QCOMPARE(listview->count(), 12);
- QCOMPARE(visualModel->items()->count(), 12);
- QCOMPARE(visibleItems->count(), 9);
- QCOMPARE(selectedItems->count(), 2);
- static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
- static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
- static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
- static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
- static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
- VERIFY_GET;
- }
-}
-
-void tst_qquickvisualdatamodel::invalidGroups()
-{
- QUrl source = QUrl::fromLocalFile(TESTDATA("groups-invalid.qml"));
- QTest::ignoreMessage(QtWarningMsg, (source.toString() + ":12:9: QML VisualDataGroup: " + QQuickVisualDataGroup::tr("Group names must start with a lower case letter")).toUtf8());
-
- QDeclarativeComponent component(&engine, source);
- QScopedPointer<QObject> object(component.create());
- QVERIFY(object);
-
- QCOMPARE(evaluate<int>(object.data(), "groups.length"), 4);
- QCOMPARE(evaluate<QString>(object.data(), "groups[0].name"), QString("items"));
- QCOMPARE(evaluate<QString>(object.data(), "groups[1].name"), QString("persistedItems"));
- QCOMPARE(evaluate<QString>(object.data(), "groups[2].name"), QString("visible"));
- QCOMPARE(evaluate<QString>(object.data(), "groups[3].name"), QString("selected"));
-}
-
-void tst_qquickvisualdatamodel::onChanged_data()
-{
- QTest::addColumn<QString>("expression");
- QTest::addColumn<QStringList>("tests");
-
- QTest::newRow("item appended")
- << QString("listModel.append({\"number\": \"five\"})")
- << (QStringList()
- << "verify(vm.removed, [], [], [])"
- << "verify(vm.inserted, [4], [1], [undefined])"
- << "verify(vi.removed, [], [], [])"
- << "verify(vi.inserted, [4], [1], [undefined])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
- QTest::newRow("item prepended")
- << QString("listModel.insert(0, {\"number\": \"five\"})")
- << (QStringList()
- << "verify(vm.removed, [], [], [])"
- << "verify(vm.inserted, [0], [1], [undefined])"
- << "verify(vi.removed, [], [], [])"
- << "verify(vi.inserted, [0], [1], [undefined])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
- QTest::newRow("item inserted")
- << QString("listModel.insert(2, {\"number\": \"five\"})")
- << (QStringList()
- << "verify(vm.removed, [], [], [])"
- << "verify(vm.inserted, [2], [1], [undefined])"
- << "verify(vi.removed, [], [], [])"
- << "verify(vi.inserted, [2], [1], [undefined])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
-
- QTest::newRow("item removed tail")
- << QString("listModel.remove(3)")
- << (QStringList()
- << "verify(vm.removed, [3], [1], [undefined])"
- << "verify(vm.inserted, [], [], [])"
- << "verify(vi.removed, [3], [1], [undefined])"
- << "verify(vi.inserted, [], [], [])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
- QTest::newRow("item removed head")
- << QString("listModel.remove(0)")
- << (QStringList()
- << "verify(vm.removed, [0], [1], [undefined])"
- << "verify(vm.inserted, [], [], [])"
- << "verify(vi.removed, [0], [1], [undefined])"
- << "verify(vi.inserted, [], [], [])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
- QTest::newRow("item removed middle")
- << QString("listModel.remove(1)")
- << (QStringList()
- << "verify(vm.removed, [1], [1], [undefined])"
- << "verify(vm.inserted, [], [], [])"
- << "verify(vi.removed, [1], [1], [undefined])"
- << "verify(vi.inserted, [], [], [])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
-
-
- QTest::newRow("item moved from tail")
- << QString("listModel.move(3, 0, 1)")
- << (QStringList()
- << "verify(vm.removed, [3], [1], [vm.inserted[0].moveId])"
- << "verify(vm.inserted, [0], [1], [vm.removed[0].moveId])"
- << "verify(vi.removed, [3], [1], [vi.inserted[0].moveId])"
- << "verify(vi.inserted, [0], [1], [vi.removed[0].moveId])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
- QTest::newRow("item moved from head")
- << QString("listModel.move(0, 2, 2)")
- << (QStringList()
- << "verify(vm.removed, [0], [2], [vm.inserted[0].moveId])"
- << "verify(vm.inserted, [2], [2], [vm.removed[0].moveId])"
- << "verify(vi.removed, [0], [2], [vi.inserted[0].moveId])"
- << "verify(vi.inserted, [2], [2], [vi.removed[0].moveId])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
-
- QTest::newRow("groups changed")
- << QString("items.setGroups(1, 2, [\"items\", \"selected\"])")
- << (QStringList()
- << "verify(vm.inserted, [], [], [])"
- << "verify(vm.removed, [], [], [])"
- << "verify(vi.removed, [1], [2], [undefined])"
- << "verify(vi.inserted, [], [], [])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [0], [2], [undefined])");
-
- QTest::newRow("multiple removes")
- << QString("{ vi.remove(1, 1); "
- "vi.removeGroups(0, 2, \"items\") }")
- << (QStringList()
- << "verify(vm.removed, [0, 1], [1, 1], [undefined, undefined])"
- << "verify(vm.inserted, [], [], [])"
- << "verify(vi.removed, [1], [1], [undefined])"
- << "verify(vi.inserted, [], [], [])"
- << "verify(si.removed, [], [], [])"
- << "verify(si.inserted, [], [], [])");
-}
-
-void tst_qquickvisualdatamodel::onChanged()
-{
- QFETCH(QString, expression);
- QFETCH(QStringList, tests);
-
- QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("onChanged.qml")));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(object);
-
- evaluate<void>(object.data(), expression);
-
- foreach (const QString &test, tests) {
- bool passed = evaluate<bool>(object.data(), test);
- if (!passed)
- qWarning() << test;
- QVERIFY(passed);
- }
-}
-
-void tst_qquickvisualdatamodel::create()
-{
- QQuickView view;
-
- SingleRoleModel model;
- model.list = QStringList()
- << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six"
- << "seven"
- << "eight"
- << "nine"
- << "ten"
- << "eleven"
- << "twelve"
- << "thirteen"
- << "fourteen"
- << "fifteen"
- << "sixteen"
- << "seventeen"
- << "eighteen"
- << "nineteen"
- << "twenty";
-
- QDeclarativeContext *ctxt = view.rootContext();
- ctxt->setContextProperty("myModel", &model);
-
- view.setSource(QUrl::fromLocalFile(TESTDATA("create.qml")));
-
- QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
-
- QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
-
- QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
- QVERIFY(visualModel);
-
- QCOMPARE(listview->count(), 20);
-
- QQuickItem *delegate;
-
- // persistedItems.includeByDefault is true, so all items belong to persistedItems initially.
- QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 1));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
-
- // changing include by default doesn't remove persistance.
- evaluate<void>(visualModel, "persistedItems.includeByDefault = false");
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
-
- // removing from persistedItems does.
- evaluate<void>(visualModel, "persistedItems.remove(0, 20)");
- QCOMPARE(listview->count(), 20);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
-
- // Request an item instantiated by the view.
- QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(1)")));
- QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 1));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
-
- evaluate<void>(delegate, "VisualDataModel.inPersistedItems = false");
- QCOMPARE(listview->count(), 20);
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
-
- // Request an item not instantiated by the view.
- QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 15));
- QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(15)")));
- QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 15));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
-
- evaluate<void>(visualModel, "persistedItems.remove(0)");
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
-
- // Request an item not instantiated by the view, then scroll the view so it will request it.
- QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 16));
- QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(16)")));
- QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 16));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
-
- evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
- QCOMPARE(listview->count(), 20);
- evaluate<void>(delegate, "VisualDataModel.groups = [\"items\"]");
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
-
- // Request and release an item instantiated by the view, then scroll the view so it releases it.
- QVERIFY(findItem<QQuickItem>(contentItem, "delegate", 17));
- QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(17)")));
- QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 17));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
-
- evaluate<void>(visualModel, "items.removeGroups(17, \"persistedItems\")");
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
- evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
- QCOMPARE(listview->count(), 20);
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
-
- // Adding an item to the persistedItems group won't instantiate it, but if later requested by
- // the view it will be persisted.
- evaluate<void>(visualModel, "items.addGroups(18, \"persistedItems\")");
- QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
- QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 18));
- evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
- QCOMPARE(listview->count(), 20);
- QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 18));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
- evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
- QCOMPARE(listview->count(), 20);
- QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
-}
-
-
-void tst_qquickvisualdatamodel::incompleteModel()
-{
- // VisualDataModel is first populated in componentComplete. Verify various functions are
- // harmlessly ignored until then.
-
- QDeclarativeComponent component(&engine);
- component.setData("import QtQuick 2.0\n VisualDataModel {}", QUrl::fromLocalFile(TESTDATA("")));
-
- QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
-
- QQuickVisualDataModel *model = qobject_cast<QQuickVisualDataModel *>(object.data());
- QVERIFY(model);
-
- QSignalSpy itemsSpy(model->items(), SIGNAL(countChanged()));
- QSignalSpy persistedItemsSpy(model->items(), SIGNAL(countChanged()));
-
- evaluate<void>(model, "items.removeGroups(0, items.count, \"items\")");
- QCOMPARE(itemsSpy.count(), 0);
- QCOMPARE(persistedItemsSpy.count(), 0);
-
- evaluate<void>(model, "items.setGroups(0, items.count, \"persistedItems\")");
- QCOMPARE(itemsSpy.count(), 0);
- QCOMPARE(persistedItemsSpy.count(), 0);
-
- evaluate<void>(model, "items.addGroups(0, items.count, \"persistedItems\")");
- QCOMPARE(itemsSpy.count(), 0);
- QCOMPARE(persistedItemsSpy.count(), 0);
-
- evaluate<void>(model, "items.remove(0, items.count)");
- QCOMPARE(itemsSpy.count(), 0);
- QCOMPARE(persistedItemsSpy.count(), 0);
-
- evaluate<void>(model, "items.insert([ \"color\": \"blue\" ])");
- QCOMPARE(itemsSpy.count(), 0);
- QCOMPARE(persistedItemsSpy.count(), 0);
-
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: get: index out of range");
- QVERIFY(evaluate<bool>(model, "items.get(0) === undefined"));
-
- component.completeCreate();
-}
-
-template<typename T>
-T *tst_qquickvisualdatamodel::findItem(QQuickItem *parent, const QString &objectName, int index)
-{
- const QMetaObject &mo = T::staticMetaObject;
- //qDebug() << parent->childItems().count() << "children";
- for (int i = 0; i < parent->childItems().count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
- if (!item)
- continue;
- //qDebug() << "try" << item;
- if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
- if (index != -1) {
- QDeclarativeExpression e(qmlContext(item), item, "index");
- if (e.evaluate().toInt() == index)
- return static_cast<T*>(item);
- } else {
- return static_cast<T*>(item);
- }
- }
- item = findItem<T>(item, objectName, index);
- if (item)
- return static_cast<T*>(item);
- }
-
- return 0;
-}
-
-QTEST_MAIN(tst_qquickvisualdatamodel)
-
-#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/declarative/v4/tst_v4.cpp b/tests/auto/declarative/v4/tst_v4.cpp
index 69fa4bbf0c..791610d541 100644
--- a/tests/auto/declarative/v4/tst_v4.cpp
+++ b/tests/auto/declarative/v4/tst_v4.cpp
@@ -48,7 +48,7 @@
#include <private/qv4compiler_p.h>
-#include "../shared/util.h"
+#include "../../shared/util.h"
#include "testtypes.h"
inline QUrl TEST_FILE(const QString &filename)
diff --git a/tests/auto/particles/qquickage/qquickage.pro b/tests/auto/particles/qquickage/qquickage.pro
index 980d390953..e03e3d47d1 100644
--- a/tests/auto/particles/qquickage/qquickage.pro
+++ b/tests/auto/particles/qquickage/qquickage.pro
@@ -9,5 +9,5 @@ DEPLOYMENT += testDataFiles
CONFIG += insignificant_test
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickangleddirection/qquickangleddirection.pro b/tests/auto/particles/qquickangleddirection/qquickangleddirection.pro
index 2a4ee5237a..235f0d81b0 100644
--- a/tests/auto/particles/qquickangleddirection/qquickangleddirection.pro
+++ b/tests/auto/particles/qquickangleddirection/qquickangleddirection.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickcumulativedirection/qquickcumulativedirection.pro b/tests/auto/particles/qquickcumulativedirection/qquickcumulativedirection.pro
index 160f63f3bc..09fe1aa06a 100644
--- a/tests/auto/particles/qquickcumulativedirection/qquickcumulativedirection.pro
+++ b/tests/auto/particles/qquickcumulativedirection/qquickcumulativedirection.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickcustomaffector/qquickcustomaffector.pro b/tests/auto/particles/qquickcustomaffector/qquickcustomaffector.pro
index e1293312b1..6d3ecaa6f4 100644
--- a/tests/auto/particles/qquickcustomaffector/qquickcustomaffector.pro
+++ b/tests/auto/particles/qquickcustomaffector/qquickcustomaffector.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickcustomparticle/qquickcustomparticle.pro b/tests/auto/particles/qquickcustomparticle/qquickcustomparticle.pro
index 3476a66ca2..e9bcc1e373 100644
--- a/tests/auto/particles/qquickcustomparticle/qquickcustomparticle.pro
+++ b/tests/auto/particles/qquickcustomparticle/qquickcustomparticle.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickellipseextruder/qquickellipseextruder.pro b/tests/auto/particles/qquickellipseextruder/qquickellipseextruder.pro
index 9f5147be33..803a366429 100644
--- a/tests/auto/particles/qquickellipseextruder/qquickellipseextruder.pro
+++ b/tests/auto/particles/qquickellipseextruder/qquickellipseextruder.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickfriction/qquickfriction.pro b/tests/auto/particles/qquickfriction/qquickfriction.pro
index d6726724ff..889b2d9505 100644
--- a/tests/auto/particles/qquickfriction/qquickfriction.pro
+++ b/tests/auto/particles/qquickfriction/qquickfriction.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickgravity/qquickgravity.pro b/tests/auto/particles/qquickgravity/qquickgravity.pro
index bc503d932a..3bdd8c1efa 100644
--- a/tests/auto/particles/qquickgravity/qquickgravity.pro
+++ b/tests/auto/particles/qquickgravity/qquickgravity.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickimageparticle/qquickimageparticle.pro b/tests/auto/particles/qquickimageparticle/qquickimageparticle.pro
index 14d28fd43d..fa43b28407 100644
--- a/tests/auto/particles/qquickimageparticle/qquickimageparticle.pro
+++ b/tests/auto/particles/qquickimageparticle/qquickimageparticle.pro
@@ -7,4 +7,4 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickitemparticle/qquickitemparticle.pro b/tests/auto/particles/qquickitemparticle/qquickitemparticle.pro
index 8e8eadd463..9d78c2b49d 100644
--- a/tests/auto/particles/qquickitemparticle/qquickitemparticle.pro
+++ b/tests/auto/particles/qquickitemparticle/qquickitemparticle.pro
@@ -9,5 +9,5 @@ DEPLOYMENT += testDataFiles
CONFIG += insignificant_test #temporary
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquicklineextruder/qquicklineextruder.pro b/tests/auto/particles/qquicklineextruder/qquicklineextruder.pro
index 255c9a4104..fae5203961 100644
--- a/tests/auto/particles/qquicklineextruder/qquicklineextruder.pro
+++ b/tests/auto/particles/qquicklineextruder/qquicklineextruder.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickmaskextruder/qquickmaskextruder.pro b/tests/auto/particles/qquickmaskextruder/qquickmaskextruder.pro
index b53d3610fa..d82adf8b4a 100644
--- a/tests/auto/particles/qquickmaskextruder/qquickmaskextruder.pro
+++ b/tests/auto/particles/qquickmaskextruder/qquickmaskextruder.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickparticlegroup/qquickparticlegroup.pro b/tests/auto/particles/qquickparticlegroup/qquickparticlegroup.pro
index b100ffaf75..27547c16b1 100644
--- a/tests/auto/particles/qquickparticlegroup/qquickparticlegroup.pro
+++ b/tests/auto/particles/qquickparticlegroup/qquickparticlegroup.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickparticlesystem/qquickparticlesystem.pro b/tests/auto/particles/qquickparticlesystem/qquickparticlesystem.pro
index 65472e23f9..6fd13ec01e 100644
--- a/tests/auto/particles/qquickparticlesystem/qquickparticlesystem.pro
+++ b/tests/auto/particles/qquickparticlesystem/qquickparticlesystem.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickpointattractor/qquickpointattractor.pro b/tests/auto/particles/qquickpointattractor/qquickpointattractor.pro
index 13b512791a..a9d390aab8 100644
--- a/tests/auto/particles/qquickpointattractor/qquickpointattractor.pro
+++ b/tests/auto/particles/qquickpointattractor/qquickpointattractor.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickpointdirection/qquickpointdirection.pro b/tests/auto/particles/qquickpointdirection/qquickpointdirection.pro
index 6adab3d75d..04fe1617de 100644
--- a/tests/auto/particles/qquickpointdirection/qquickpointdirection.pro
+++ b/tests/auto/particles/qquickpointdirection/qquickpointdirection.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickrectangleextruder/qquickrectangleextruder.pro b/tests/auto/particles/qquickrectangleextruder/qquickrectangleextruder.pro
index fee29efcf3..e45c43a587 100644
--- a/tests/auto/particles/qquickrectangleextruder/qquickrectangleextruder.pro
+++ b/tests/auto/particles/qquickrectangleextruder/qquickrectangleextruder.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquicktargetdirection/qquicktargetdirection.pro b/tests/auto/particles/qquicktargetdirection/qquicktargetdirection.pro
index 0de6007283..0a887d1fb3 100644
--- a/tests/auto/particles/qquicktargetdirection/qquicktargetdirection.pro
+++ b/tests/auto/particles/qquicktargetdirection/qquicktargetdirection.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquicktrailemitter/qquicktrailemitter.pro b/tests/auto/particles/qquicktrailemitter/qquicktrailemitter.pro
index 7b8075d625..9139dd39fb 100644
--- a/tests/auto/particles/qquicktrailemitter/qquicktrailemitter.pro
+++ b/tests/auto/particles/qquicktrailemitter/qquicktrailemitter.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickturbulence/qquickturbulence.pro b/tests/auto/particles/qquickturbulence/qquickturbulence.pro
index 405e8a6f2a..16d85445f5 100644
--- a/tests/auto/particles/qquickturbulence/qquickturbulence.pro
+++ b/tests/auto/particles/qquickturbulence/qquickturbulence.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/qquickwander/qquickwander.pro b/tests/auto/particles/qquickwander/qquickwander.pro
index cf6f08e2dc..a9c48ece78 100644
--- a/tests/auto/particles/qquickwander/qquickwander.pro
+++ b/tests/auto/particles/qquickwander/qquickwander.pro
@@ -7,5 +7,5 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/particles/shared/particlestestsshared.h b/tests/auto/particles/shared/particlestestsshared.h
index ab6b5f16af..5989efe937 100644
--- a/tests/auto/particles/shared/particlestestsshared.h
+++ b/tests/auto/particles/shared/particlestestsshared.h
@@ -41,7 +41,7 @@
#ifndef PARTICLES_TESTS_SHARED
#define PARTICLES_TESTS_SHARED
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QtTest>
#include <QAbstractAnimation>
const qreal EPSILON = 0.0001;
diff --git a/tests/auto/qtquick1/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro b/tests/auto/qtquick1/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro
index c5ec23e17e..21c846b4eb 100644
--- a/tests/auto/qtquick1/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro
+++ b/tests/auto/qtquick1/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qdeclarativeanimatedimage
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativeanimatedimage.cpp ../../declarative/shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativeanimatedimage.cpp ../../shared/testhttpserver.cpp
macx:CONFIG -= app_bundle
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp b/tests/auto/qtquick1/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp
index 275b8d0fb4..3d81d669f4 100644
--- a/tests/auto/qtquick1/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp
+++ b/tests/auto/qtquick1/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp
@@ -48,7 +48,7 @@
#include <QSignalSpy>
#include <QtDeclarative/qdeclarativecontext.h>
-#include "../../declarative/shared/testhttpserver.h"
+#include "../../shared/testhttpserver.h"
class tst_qdeclarativeanimatedimage : public QObject
{
diff --git a/tests/auto/qtquick1/qdeclarativeborderimage/qdeclarativeborderimage.pro b/tests/auto/qtquick1/qdeclarativeborderimage/qdeclarativeborderimage.pro
index 83319faf8a..a8c8b18a37 100644
--- a/tests/auto/qtquick1/qdeclarativeborderimage/qdeclarativeborderimage.pro
+++ b/tests/auto/qtquick1/qdeclarativeborderimage/qdeclarativeborderimage.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
TARGET = tst_qdeclarativeborderimage
macx:CONFIG -= app_bundle
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativeborderimage.cpp ../../declarative/shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativeborderimage.cpp ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/qtquick1/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp
index 4b82fe0a4e..4346c75850 100644
--- a/tests/auto/qtquick1/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp
+++ b/tests/auto/qtquick1/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp
@@ -54,7 +54,7 @@
#include <private/qdeclarativeloader_p.h>
#include <QtDeclarative/qdeclarativecontext.h>
-#include "../../declarative/shared/testhttpserver.h"
+#include "../../shared/testhttpserver.h"
#define SERVER_PORT 14446
#define SERVER_ADDR "http://127.0.0.1:14446"
diff --git a/tests/auto/qtquick1/qdeclarativefontloader/qdeclarativefontloader.pro b/tests/auto/qtquick1/qdeclarativefontloader/qdeclarativefontloader.pro
index fc48544fa0..fbe72b072c 100644
--- a/tests/auto/qtquick1/qdeclarativefontloader/qdeclarativefontloader.pro
+++ b/tests/auto/qtquick1/qdeclarativefontloader/qdeclarativefontloader.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
TARGET = tst_qdeclarativefontloader
macx:CONFIG -= app_bundle
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativefontloader.cpp ../../declarative/shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativefontloader.cpp ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativefontloader/tst_qdeclarativefontloader.cpp b/tests/auto/qtquick1/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
index 3bcbe1b67c..addd6516f5 100644
--- a/tests/auto/qtquick1/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
+++ b/tests/auto/qtquick1/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
@@ -44,7 +44,7 @@
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativecontext.h>
#include <QtQuick1/private/qdeclarativefontloader_p.h>
-#include "../../declarative/shared/testhttpserver.h"
+#include "../../shared/testhttpserver.h"
#define SERVER_PORT 14448
diff --git a/tests/auto/qtquick1/qdeclarativeimage/qdeclarativeimage.pro b/tests/auto/qtquick1/qdeclarativeimage/qdeclarativeimage.pro
index 5c9b9db5c8..28570ab093 100644
--- a/tests/auto/qtquick1/qdeclarativeimage/qdeclarativeimage.pro
+++ b/tests/auto/qtquick1/qdeclarativeimage/qdeclarativeimage.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
TARGET = tst_qdeclarativeimage
macx:CONFIG -= app_bundle
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativeimage.cpp ../../declarative/shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativeimage.cpp ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/qtquick1/qdeclarativeimage/tst_qdeclarativeimage.cpp
index e93c373bf1..107ba89c77 100644
--- a/tests/auto/qtquick1/qdeclarativeimage/tst_qdeclarativeimage.cpp
+++ b/tests/auto/qtquick1/qdeclarativeimage/tst_qdeclarativeimage.cpp
@@ -54,7 +54,7 @@
#include <QtDeclarative/qdeclarativeexpression.h>
#include <QtTest/QSignalSpy>
-#include "../../declarative/shared/testhttpserver.h"
+#include "../../shared/testhttpserver.h"
#define SERVER_PORT 14451
#define SERVER_ADDR "http://127.0.0.1:14451"
diff --git a/tests/auto/qtquick1/qdeclarativeloader/qdeclarativeloader.pro b/tests/auto/qtquick1/qdeclarativeloader/qdeclarativeloader.pro
index 7f3cfb20b1..0e4df8d3da 100644
--- a/tests/auto/qtquick1/qdeclarativeloader/qdeclarativeloader.pro
+++ b/tests/auto/qtquick1/qdeclarativeloader/qdeclarativeloader.pro
@@ -2,10 +2,10 @@ CONFIG += testcase
TARGET = tst_qdeclarativeloader
macx:CONFIG -= app_bundle
-INCLUDEPATH += ../../declarative/shared/
-HEADERS += ../../declarative/shared/testhttpserver.h
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
SOURCES += tst_qdeclarativeloader.cpp \
- ../../declarative/shared/testhttpserver.cpp
+ ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativemousearea/qdeclarativemousearea.pro b/tests/auto/qtquick1/qdeclarativemousearea/qdeclarativemousearea.pro
index f7e6a5b292..6f426c50c5 100644
--- a/tests/auto/qtquick1/qdeclarativemousearea/qdeclarativemousearea.pro
+++ b/tests/auto/qtquick1/qdeclarativemousearea/qdeclarativemousearea.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
TARGET = tst_qdeclarativemousearea
macx:CONFIG -= app_bundle
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += tst_qdeclarativemousearea.cpp ../../declarative/shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativemousearea.cpp ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro b/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro
index 0989aab14f..1957bdd9fd 100644
--- a/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro
+++ b/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro
@@ -4,9 +4,9 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qdeclarativetext.cpp
-INCLUDEPATH += ../../declarative/shared/
-HEADERS += ../../declarative/shared/testhttpserver.h
-SOURCES += ../../declarative/shared/testhttpserver.cpp
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += ../../shared/testhttpserver.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro b/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro
index 74c4215579..5c86e111e8 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro
+++ b/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
TARGET = tst_qdeclarativetextedit
macx:CONFIG -= app_bundle
-SOURCES += tst_qdeclarativetextedit.cpp ../../declarative/shared/testhttpserver.cpp
-HEADERS += ../../declarative/shared/testhttpserver.h
+SOURCES += tst_qdeclarativetextedit.cpp ../../shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
index 621c1753b2..54b8567161 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
+++ b/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <qtest.h>
#include <QtTest/QSignalSpy>
-#include "../../declarative/shared/testhttpserver.h"
+#include "../../shared/testhttpserver.h"
#include <math.h>
#include <QFile>
#include <QTextDocument>
diff --git a/tests/auto/declarative/examples/data/dummytest.qml b/tests/auto/qtquick2/examples/data/dummytest.qml
index b20e907f27..b20e907f27 100644
--- a/tests/auto/declarative/examples/data/dummytest.qml
+++ b/tests/auto/qtquick2/examples/data/dummytest.qml
diff --git a/tests/auto/declarative/examples/data/webbrowser/webbrowser.qml b/tests/auto/qtquick2/examples/data/webbrowser/webbrowser.qml
index d31787b939..d31787b939 100644
--- a/tests/auto/declarative/examples/data/webbrowser/webbrowser.qml
+++ b/tests/auto/qtquick2/examples/data/webbrowser/webbrowser.qml
diff --git a/tests/auto/qtquick2/examples/examples.pro b/tests/auto/qtquick2/examples/examples.pro
new file mode 100644
index 0000000000..ca169242e1
--- /dev/null
+++ b/tests/auto/qtquick2/examples/examples.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_examples
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_examples.cpp
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+CONFIG += parallel_test
+#temporary
+QT += core-private gui-private declarative-private quick-private qtquick1-private widgets-private v8-private testlib
diff --git a/tests/auto/qtquick2/examples/tst_examples.cpp b/tests/auto/qtquick2/examples/tst_examples.cpp
new file mode 100644
index 0000000000..050ae49cfc
--- /dev/null
+++ b/tests/auto/qtquick2/examples/tst_examples.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QLibraryInfo>
+#include <QDir>
+#include <QProcess>
+#include <QDebug>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickView>
+#include <QDeclarativeComponent>
+#include <QDeclarativeEngine>
+#include <QDeclarativeError>
+
+class tst_examples : public QObject
+{
+ Q_OBJECT
+public:
+ tst_examples();
+
+private slots:
+ void sgexamples_data();
+ void sgexamples();
+
+ void namingConvention();
+private:
+ QStringList excludedDirs;
+ QStringList excludedFiles;
+
+ void namingConvention(const QDir &);
+ QStringList findQmlFiles(const QDir &);
+
+ QDeclarativeEngine engine;
+};
+
+tst_examples::tst_examples()
+{
+ // Add files to exclude here
+ excludedFiles << "doc/src/snippets/declarative/listmodel.qml"; //Just a ListModel, no root QQuickItem
+
+ // Add directories you want excluded here
+ excludedDirs << "examples/declarative/text/fonts"; // QTBUG-21415
+
+ // Not run in QQuickView
+ excludedDirs << "examples/declarative/qtquick1";
+
+ // These snippets are not expected to run on their own.
+ excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex";
+ excludedDirs << "doc/src/snippets/declarative/qtbinding";
+ excludedDirs << "doc/src/snippets/declarative/imports";
+ excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
+ excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
+ excludedDirs << "doc/src/snippets/qtquick1/imports";
+
+#ifdef QT_NO_WEBKIT
+ excludedDirs << "examples/declarative/modelviews/webview";
+ excludedDirs << "examples/declarative/webbrowser";
+ excludedDirs << "doc/src/snippets/declarative/webview";
+ excludedDirs << "doc/src/snippets/qtquick1/webview";
+#endif
+
+#ifdef QT_NO_XMLPATTERNS
+ excludedDirs << "examples/declarative/xml/xmldata";
+ excludedDirs << "examples/declarative/twitter";
+ excludedDirs << "examples/declarative/flickr";
+ excludedDirs << "examples/declarative/photoviewer";
+#endif
+}
+
+/*
+This tests that the examples follow the naming convention required
+to have them tested by the examples() test.
+*/
+void tst_examples::namingConvention(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = excludedDirs.at(ii);
+ if (d.absolutePath().endsWith(s))
+ return;
+ }
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+
+ bool seenQml = !files.isEmpty();
+ bool seenLowercase = false;
+
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower())
+ seenLowercase = true;
+ }
+
+ if (!seenQml) {
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ namingConvention(sub);
+ }
+ } else if(!seenLowercase) {
+ QFAIL(qPrintable(QString(
+ "Directory %1 violates naming convention; expected at least one qml file "
+ "starting with lower case, got: %2"
+ ).arg(d.absolutePath()).arg(files.join(","))));
+ }
+}
+
+void tst_examples::namingConvention()
+{
+ QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
+
+ namingConvention(QDir(examples));
+}
+
+QStringList tst_examples::findQmlFiles(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = excludedDirs.at(ii);
+ if (d.absolutePath().endsWith(s))
+ return QStringList();
+ }
+
+ QStringList rv;
+
+ QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
+ if (cppfiles.isEmpty()) {
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower()) {
+ bool superContinue = false;
+ for (int ii = 0; ii < excludedFiles.count(); ++ii) {
+ QString e = excludedFiles.at(ii);
+ if (d.absoluteFilePath(file).endsWith(e)) {
+ superContinue = true;
+ break;
+ }
+ }
+ if (superContinue)
+ continue;
+ rv << d.absoluteFilePath(file);
+ }
+ }
+ }
+
+
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ rv << findQmlFiles(sub);
+ }
+
+ return rv;
+}
+
+/*
+This test runs all the examples in the declarative UI source tree and ensures
+that they start and exit cleanly.
+
+Examples are any .qml files under the examples/ directory that start
+with a lower case letter.
+*/
+static void silentErrorsMsgHandler(QtMsgType, const char *)
+{
+}
+
+
+void tst_examples::sgexamples_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QString examples = QLatin1String(SRCDIR) + "/../../../../examples/declarative/";
+ QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/declarative";
+
+ QStringList files;
+ files << findQmlFiles(QDir(examples));
+ files << findQmlFiles(QDir(snippets));
+
+ foreach (const QString &file, files)
+ QTest::newRow(qPrintable(file)) << file;
+}
+
+void tst_examples::sgexamples()
+{
+ QFETCH(QString, file);
+
+ QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
+ qInstallMsgHandler(old);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(file));
+ if (component.status() == QDeclarativeComponent::Error)
+ qWarning() << component.errors();
+ QCOMPARE(component.status(), QDeclarativeComponent::Ready);
+
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
+ if (!root)
+ component.completeCreate();
+ QVERIFY(root);
+
+ QQuickCanvas canvas;
+ root->setParentItem(canvas.rootItem());
+ component.completeCreate();
+ canvas.show();
+
+ QTest::qWaitForWindowShown(&canvas);
+
+}
+
+QTEST_MAIN(tst_examples)
+
+#include "tst_examples.moc"
diff --git a/tests/auto/qtquick2/geometry/geometry.pro b/tests/auto/qtquick2/geometry/geometry.pro
new file mode 100644
index 0000000000..04d529cfb8
--- /dev/null
+++ b/tests/auto/qtquick2/geometry/geometry.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_geometry
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_geometry.cpp
+
+CONFIG+=parallel_test
+
+QT += core-private gui-private declarative-private quick-private opengl testlib
diff --git a/tests/auto/qtquick2/geometry/tst_geometry.cpp b/tests/auto/qtquick2/geometry/tst_geometry.cpp
new file mode 100644
index 0000000000..23e37dae2f
--- /dev/null
+++ b/tests/auto/qtquick2/geometry/tst_geometry.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt scene graph research project.
+**
+** $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 <QtCore/QString>
+#include <QtTest/QtTest>
+
+#include <QtQuick/qsggeometry.h>
+
+class GeometryTest : public QObject
+{
+ Q_OBJECT
+
+public:
+
+private Q_SLOTS:
+ void testPoint2D();
+ void testTexturedPoint2D();
+ void testCustomGeometry();
+
+private:
+};
+
+void GeometryTest::testPoint2D()
+{
+ QSGGeometry geometry(QSGGeometry::defaultAttributes_Point2D(), 4, 0);
+
+ QCOMPARE(geometry.attributeCount(), 1);
+ QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 2);
+ QCOMPARE(geometry.vertexCount(), 4);
+ QCOMPARE(geometry.indexCount(), 0);
+ QVERIFY(geometry.indexData() == 0);
+
+ QSGGeometry::updateRectGeometry(&geometry, QRectF(1, 2, 3, 4));
+
+ QSGGeometry::Point2D *pts = geometry.vertexDataAsPoint2D();
+ QVERIFY(pts != 0);
+
+ QCOMPARE(pts[0].x, (float) 1);
+ QCOMPARE(pts[0].y, (float) 2);
+ QCOMPARE(pts[3].x, (float) 4);
+ QCOMPARE(pts[3].y, (float) 6);
+
+ // Verify that resize gives me enough allocated data without crashing...
+ geometry.allocate(100, 100);
+ pts = geometry.vertexDataAsPoint2D();
+ quint16 *is = geometry.indexDataAsUShort();
+ for (int i=0; i<100; ++i) {
+ pts[i].x = i;
+ pts[i].y = i + 100;
+ is[i] = i;
+ }
+ QVERIFY(true);
+}
+
+
+void GeometryTest::testTexturedPoint2D()
+{
+ QSGGeometry geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4, 0);
+
+ QCOMPARE(geometry.attributeCount(), 2);
+ QCOMPARE(geometry.sizeOfVertex(), (int) sizeof(float) * 4);
+ QCOMPARE(geometry.vertexCount(), 4);
+ QCOMPARE(geometry.indexCount(), 0);
+ QVERIFY(geometry.indexData() == 0);
+
+ QSGGeometry::updateTexturedRectGeometry(&geometry, QRectF(1, 2, 3, 4), QRectF(5, 6, 7, 8));
+
+ QSGGeometry::TexturedPoint2D *pts = geometry.vertexDataAsTexturedPoint2D();
+ QVERIFY(pts != 0);
+
+ QCOMPARE(pts[0].x, (float) 1);
+ QCOMPARE(pts[0].y, (float) 2);
+ QCOMPARE(pts[0].tx, (float) 5);
+ QCOMPARE(pts[0].ty, (float) 6);
+
+ QCOMPARE(pts[3].x, (float) 4);
+ QCOMPARE(pts[3].y, (float) 6);
+ QCOMPARE(pts[3].tx, (float) 12);
+ QCOMPARE(pts[3].ty, (float) 14);
+
+ // Verify that resize gives me enough allocated data without crashing...
+ geometry.allocate(100, 100);
+ pts = geometry.vertexDataAsTexturedPoint2D();
+ quint16 *is = geometry.indexDataAsUShort();
+ for (int i=0; i<100; ++i) {
+ pts[i].x = i;
+ pts[i].y = i + 100;
+ pts[i].tx = i + 200;
+ pts[i].ty = i + 300;
+ is[i] = i;
+ }
+ QVERIFY(true);
+}
+
+void GeometryTest::testCustomGeometry()
+{
+ struct V {
+ float x, y;
+ unsigned char r, g, b, a;
+ float v1, v2, v3, v4;
+ };
+
+ static QSGGeometry::Attribute attributes[] = {
+ { 0, 2, GL_FLOAT },
+ { 1, 4, GL_UNSIGNED_BYTE },
+ { 2, 4, GL_FLOAT },
+ };
+ static QSGGeometry::AttributeSet set = { 4, 6 * sizeof(float) + 4 * sizeof(unsigned char), attributes };
+
+ QSGGeometry geometry(set, 1000, 4000);
+
+ // Verify that space has been allocated.
+ quint16 *ii = geometry.indexDataAsUShort();
+ for (int i=0; i<geometry.indexCount(); ++i) {
+ ii[i] = i;
+ }
+
+ V *v = (V *) geometry.vertexData();
+ for (int i=0; i<geometry.vertexCount(); ++i) {
+ v[i].x = 0;
+ v[i].y = 1;
+ v[i].r = 2;
+ v[i].g = 3;
+ v[i].b = 4;
+ v[i].a = 5;
+ v[i].v1 = 6;
+ v[i].v2 = 7;
+ v[i].v3 = 8;
+ v[i].v4 = 9;
+ }
+
+ // Verify the data's integrity
+ for (int i=0; i<4000; ++i)
+ QCOMPARE(ii[i], (quint16) i);
+ for (int i=0; i<1000; ++i)
+ QVERIFY(v[i].v1 == 6);
+
+}
+
+
+QTEST_MAIN(GeometryTest);
+
+#include "tst_geometry.moc"
diff --git a/tests/auto/qtquick2/nodes/nodes.pro b/tests/auto/qtquick2/nodes/nodes.pro
new file mode 100644
index 0000000000..40eeb2ab78
--- /dev/null
+++ b/tests/auto/qtquick2/nodes/nodes.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_nodestest
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_nodestest.cpp
+
+CONFIG+=parallel_test
+
+QT += core-private gui-private declarative-private quick-private opengl widgets testlib
diff --git a/tests/auto/qtquick2/nodes/tst_nodestest.cpp b/tests/auto/qtquick2/nodes/tst_nodestest.cpp
new file mode 100644
index 0000000000..3036bbf2dd
--- /dev/null
+++ b/tests/auto/qtquick2/nodes/tst_nodestest.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt scene graph research project.
+**
+** $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 <QtCore/QString>
+#include <QtTest/QtTest>
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/private/qsgnodeupdater_p.h>
+
+#include <QtQuick/qsgsimplerectnode.h>
+#include <QtOpenGL/QGLWidget>
+class NodesTest : public QObject
+{
+ Q_OBJECT
+
+public:
+ NodesTest();
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase() {
+ delete widget;
+ }
+
+ // Root nodes
+ void propegate();
+ void propegateWithMultipleRoots();
+ void simulatedEffect_data();
+ void simulatedEffect();
+
+ // Opacity nodes
+ void basicOpacityNode();
+ void opacityPropegation();
+
+ // QSGNodeUpdater
+ void isBlockedCheck();
+
+private:
+ QGLWidget *widget;
+
+ QSGNodeUpdater updater;
+};
+
+void NodesTest::initTestCase()
+{
+ widget = new QGLWidget();
+ widget->resize(100, 30);
+ widget->show();
+}
+
+class DummyRenderer : public QSGRenderer
+{
+public:
+ DummyRenderer(QSGRootNode *root)
+ : QSGRenderer(QSGContext::createDefaultContext())
+ , changedNode(0)
+ , changedFlags(0)
+ , renderCount(0)
+ {
+ setRootNode(root);
+ }
+
+ void render() {
+ ++renderCount;
+ renderingOrder = ++globalRendereringOrder;
+ }
+
+ void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) {
+ changedNode = node;
+ changedFlags = flags;
+ QSGRenderer::nodeChanged(node, flags);
+ }
+
+ QSGNode *changedNode;
+ QSGNode::DirtyFlags changedFlags;
+
+ int renderCount;
+ int renderingOrder;
+ static int globalRendereringOrder;
+};
+
+int DummyRenderer::globalRendereringOrder;
+
+NodesTest::NodesTest()
+{
+}
+
+
+void NodesTest::propegate()
+{
+ QSGRootNode root;
+ QSGNode child; child.setFlag(QSGNode::OwnedByParent, false);
+ root.appendChildNode(&child);
+
+ DummyRenderer renderer(&root);
+
+ child.markDirty(QSGNode::DirtyGeometry);
+
+ QCOMPARE(&child, renderer.changedNode);
+ QCOMPARE((int) renderer.changedFlags, (int) QSGNode::DirtyGeometry);
+}
+
+
+void NodesTest::propegateWithMultipleRoots()
+{
+ QSGRootNode root1;
+ QSGNode child2; child2.setFlag(QSGNode::OwnedByParent, false);
+ QSGRootNode root3; root3.setFlag(QSGNode::OwnedByParent, false);
+ QSGNode child4; child4.setFlag(QSGNode::OwnedByParent, false);
+
+ root1.appendChildNode(&child2);
+ child2.appendChildNode(&root3);
+ root3.appendChildNode(&child4);
+
+ DummyRenderer ren1(&root1);
+ DummyRenderer ren2(&root3);
+
+ child4.markDirty(QSGNode::DirtyGeometry);
+
+ QCOMPARE(ren1.changedNode, &child4);
+ QCOMPARE(ren2.changedNode, &child4);
+
+ QCOMPARE((int) ren1.changedFlags, (int) QSGNode::DirtyGeometry);
+ QCOMPARE((int) ren2.changedFlags, (int) QSGNode::DirtyGeometry);
+}
+
+
+
+class SimulatedEffectRenderer : public DummyRenderer
+{
+public:
+ SimulatedEffectRenderer(QSGRootNode *root, QSGBasicGeometryNode *c)
+ : DummyRenderer(root)
+ {
+ child = c;
+ }
+
+ void render() {
+ matrix = child->matrix() ? *child->matrix() : QMatrix4x4();
+ DummyRenderer::render();
+ }
+
+ QSGBasicGeometryNode *child;
+ QMatrix4x4 matrix;
+};
+
+
+class PseudoEffectNode : public QSGNode {
+public:
+ PseudoEffectNode(QSGRenderer *r)
+ : renderer(r)
+ {
+ setFlag(UsePreprocess);
+ }
+
+ void preprocess() {
+
+ if (renderer->rootNode()->parent()) {
+ // Mark the root dirty to build a clean state from the root and down
+ renderer->rootNode()->markDirty(QSGNode::DirtyForceUpdate);
+ }
+
+ renderer->renderScene();
+
+ if (renderer->rootNode()->parent()) {
+ // Mark the parent of the root dirty to force the root and down to be updated.
+ renderer->rootNode()->parent()->markDirty(QSGNode::DirtyForceUpdate);
+ }
+ }
+
+ QSGRenderer *renderer;
+};
+
+void NodesTest::simulatedEffect_data()
+{
+ QTest::addColumn<bool>("connected");
+
+ QTest::newRow("connected") << true;
+ QTest::newRow("disconnected") << false;
+}
+
+void NodesTest::simulatedEffect()
+{
+ QFETCH(bool, connected);
+
+ QSGRootNode root;
+ QSGRootNode source;
+ QSGTransformNode xform;
+ QSGSimpleRectNode geometry;
+ geometry.setRect(QRectF(0, 0, 1, 1));
+ geometry.setColor(Qt::red);
+
+ root.setFlag(QSGNode::OwnedByParent, false);
+ source.setFlag(QSGNode::OwnedByParent, false);
+ xform.setFlag(QSGNode::OwnedByParent, false);
+ geometry.setFlag(QSGNode::OwnedByParent, false);
+
+ SimulatedEffectRenderer rootRenderer(&root, &geometry);
+ SimulatedEffectRenderer sourceRenderer(&source, &geometry);
+
+ PseudoEffectNode effect(&sourceRenderer);
+
+ /*
+ root Source is redirected into effect using the SimulatedEffectRenderer
+ / \
+ xform effect
+ |
+ source
+ |
+ geometry
+ */
+
+ root.appendChildNode(&xform);
+ root.appendChildNode(&effect);
+ if (connected)
+ xform.appendChildNode(&source);
+ source.appendChildNode(&geometry);
+ QMatrix4x4 m; m.translate(1, 2, 3);
+ xform.setMatrix(m);
+
+ // Clear all dirty states...
+ updater.updateStates(&root);
+
+ rootRenderer.renderScene();
+
+ // compare that we got one render call to each
+ QCOMPARE(rootRenderer.renderCount, 1);
+ QCOMPARE(sourceRenderer.renderCount, 1);
+ QVERIFY(sourceRenderer.renderingOrder < rootRenderer.renderingOrder);
+ if (connected) // geometry is not rendered in this case, so skip it...
+ QCOMPARE(rootRenderer.matrix, xform.matrix());
+ QCOMPARE(sourceRenderer.matrix, QMatrix4x4());
+}
+
+void NodesTest::basicOpacityNode()
+{
+ QSGOpacityNode n;
+ QCOMPARE(n.opacity(), 1.);
+
+ n.setOpacity(0.5);
+ QCOMPARE(n.opacity(), 0.5);
+
+ n.setOpacity(-1);
+ QCOMPARE(n.opacity(), 0.);
+
+ n.setOpacity(2);
+ QCOMPARE(n.opacity(), 1.);
+}
+
+void NodesTest::opacityPropegation()
+{
+ QSGRootNode root;
+ QSGOpacityNode *a = new QSGOpacityNode;
+ QSGOpacityNode *b = new QSGOpacityNode;
+ QSGOpacityNode *c = new QSGOpacityNode;
+
+ QSGSimpleRectNode *geometry = new QSGSimpleRectNode;
+ geometry->setRect(0, 0, 100, 100);
+
+ root.appendChildNode(a);
+ a->appendChildNode(b);
+ b->appendChildNode(c);
+ c->appendChildNode(geometry);
+
+ a->setOpacity(0.9);
+ b->setOpacity(0.8);
+ c->setOpacity(0.7);
+
+ updater.updateStates(&root);
+
+ QCOMPARE(a->combinedOpacity(), 0.9);
+ QCOMPARE(b->combinedOpacity(), 0.9 * 0.8);
+ QCOMPARE(c->combinedOpacity(), 0.9 * 0.8 * 0.7);
+ QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.8 * 0.7);
+
+ b->setOpacity(0.1);
+ updater.updateStates(&root);
+
+ QCOMPARE(a->combinedOpacity(), 0.9);
+ QCOMPARE(b->combinedOpacity(), 0.9 * 0.1);
+ QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
+ QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
+
+ b->setOpacity(0);
+ updater.updateStates(&root);
+
+ QVERIFY(b->isSubtreeBlocked());
+
+ // Verify that geometry did not get updated as it is in a blocked
+ // subtree
+ QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
+ QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
+}
+
+void NodesTest::isBlockedCheck()
+{
+ QSGRootNode root;
+ QSGOpacityNode *opacity = new QSGOpacityNode();
+ QSGNode *node = new QSGNode();
+
+ root.appendChildNode(opacity);
+ opacity->appendChildNode(node);
+
+ QSGNodeUpdater updater;
+
+ opacity->setOpacity(0);
+ QVERIFY(updater.isNodeBlocked(node, &root));
+
+ opacity->setOpacity(1);
+ QVERIFY(!updater.isNodeBlocked(node, &root));
+}
+
+QTEST_MAIN(NodesTest);
+
+#include "tst_nodestest.moc"
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/Double.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/Double.qml
index 99ffca1d62..99ffca1d62 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/Double.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/Double.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/attached.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/attached.qml
index 9dcfcd8752..9dcfcd8752 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/attached.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/attached.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badproperty1.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badproperty1.qml
index 9634c2c169..9634c2c169 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badproperty1.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badproperty1.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badproperty2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badproperty2.qml
index c121172a99..c121172a99 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badproperty2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badproperty2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badtype1.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype1.qml
index 43e1ec8572..43e1ec8572 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badtype1.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype1.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badtype2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype2.qml
index 5341cb3d1c..5341cb3d1c 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badtype2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badtype3.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype3.qml
index 182efa0840..182efa0840 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badtype3.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype3.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/badtype4.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype4.qml
index f091e2430f..f091e2430f 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/badtype4.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/badtype4.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/disabledTransition.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/disabledTransition.qml
index 0fbafead8b..0fbafead8b 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/disabledTransition.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/disabledTransition.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/dontAutoStart.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/dontAutoStart.qml
index c0c0c65e3f..c0c0c65e3f 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/dontAutoStart.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/dontAutoStart.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/dontStart.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/dontStart.qml
index 3eee0cfd35..3eee0cfd35 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/dontStart.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/dontStart.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/dontStart2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/dontStart2.qml
index e7b4164e4e..e7b4164e4e 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/dontStart2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/dontStart2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/dotproperty.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/dotproperty.qml
index e0e46dcef5..e0e46dcef5 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/dotproperty.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/dotproperty.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/doubleRegistrationBug.qml
index 9ef3da20c0..9ef3da20c0 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/doubleRegistrationBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/mixedtype1.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype1.qml
index 76129dd15e..76129dd15e 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/mixedtype1.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype1.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/mixedtype2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype2.qml
index 1a7166e3f3..1a7166e3f3 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/mixedtype2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/mixedtype2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/nonTransitionBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/nonTransitionBug.qml
index 909c533e7b..909c533e7b 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/nonTransitionBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/nonTransitionBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation.qml
index d2006a1c6a..d2006a1c6a 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml
index 951c5b2e57..951c5b2e57 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimation2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimationNoStart.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimationNoStart.qml
index be3501fabb..be3501fabb 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimationNoStart.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathAnimationNoStart.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolator.qml
index 0104412d7c..0104412d7c 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolator.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolatorBack.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack.qml
index 41366ef798..41366ef798 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolatorBack.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathTransition.qml
index 55ffc33f95..55ffc33f95 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathTransition.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pauseBindingBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pauseBindingBug.qml
index 359cda166f..359cda166f 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pauseBindingBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pauseBindingBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pauseBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pauseBug.qml
index fa2c4be4ba..fa2c4be4ba 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/pauseBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pauseBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/properties.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/properties.qml
index f0f730967c..f0f730967c 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/properties.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/properties.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/properties2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/properties2.qml
index 6b7f026e0b..6b7f026e0b 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/properties2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/properties2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/properties3.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/properties3.qml
index 5eb65496d4..5eb65496d4 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/properties3.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/properties3.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/properties4.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/properties4.qml
index dfe8ad17e7..dfe8ad17e7 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/properties4.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/properties4.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/properties5.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/properties5.qml
index 075fc9bc5a..075fc9bc5a 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/properties5.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/properties5.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition.qml
index 968c5f6285..968c5f6285 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition2.qml
index f06165604a..f06165604a 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition2.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition3.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition3.qml
index 7d3b3b9c6d..7d3b3b9c6d 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition3.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition3.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition4.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition4.qml
index 1c31a79634..1c31a79634 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition4.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition4.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition5.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition5.qml
index a2ff746900..a2ff746900 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition5.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition5.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition6.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition6.qml
index d3db01efb0..d3db01efb0 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition6.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition6.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition7.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition7.qml
index 98898de8ef..98898de8ef 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/propertiesTransition7.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/propertiesTransition7.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/registrationBug.qml
index 633da4e17f..633da4e17f 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/registrationBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/rotation.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/rotation.qml
index 4dc42a1bd2..4dc42a1bd2 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/rotation.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/rotation.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/runningTrueBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/runningTrueBug.qml
index bec6fab368..bec6fab368 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/runningTrueBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/runningTrueBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/transitionAssignmentBug.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/transitionAssignmentBug.qml
index 508693e0fc..508693e0fc 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/transitionAssignmentBug.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/transitionAssignmentBug.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/valuesource.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/valuesource.qml
index 7a636b4003..7a636b4003 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/valuesource.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/valuesource.qml
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/valuesource2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/valuesource2.qml
index 9788761ee8..9788761ee8 100644
--- a/tests/auto/declarative/qdeclarativeanimations/data/valuesource2.qml
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/valuesource2.qml
diff --git a/tests/auto/qtquick2/qdeclarativeanimations/qdeclarativeanimations.pro b/tests/auto/qtquick2/qdeclarativeanimations/qdeclarativeanimations.pro
new file mode 100644
index 0000000000..fd35266f66
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativeanimations/qdeclarativeanimations.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativeanimations
+SOURCES += tst_qdeclarativeanimations.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
new file mode 100644
index 0000000000..ca329263e9
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
@@ -0,0 +1,1106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qdeclarativeanimation_p.h>
+#include <QtQuick/private/qdeclarativetransition_p.h>
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qdeclarativepathinterpolator_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QVariantAnimation>
+#include <QEasingCurve>
+
+#include <limits.h>
+#include <math.h>
+
+#include "../../shared/util.h"
+
+class tst_qdeclarativeanimations : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativeanimations() {}
+
+private slots:
+ void initTestCase() { QDeclarativeEngine engine; } // ensure types are registered
+
+ void simpleProperty();
+ void simpleNumber();
+ void simpleColor();
+ void simpleRotation();
+ void simplePath();
+ void pathInterpolator();
+ void pathInterpolatorBackwardJump();
+ void pathWithNoStart();
+ void alwaysRunToEnd();
+ void complete();
+ void resume();
+ void dotProperty();
+ void badTypes();
+ void badProperties();
+ void mixedTypes();
+ void properties();
+ void propertiesTransition();
+ void pathTransition();
+ void disabledTransition();
+ void invalidDuration();
+ void attached();
+ void propertyValueSourceDefaultStart();
+ void dontStart();
+ void easingProperties();
+ void rotation();
+ void runningTrueBug();
+ void nonTransitionBug();
+ void registrationBug();
+ void doubleRegistrationBug();
+ void alwaysRunToEndRestartBug();
+ void transitionAssignmentBug();
+ void pauseBindingBug();
+ void pauseBug();
+};
+
+#define QTIMED_COMPARE(lhs, rhs) do { \
+ for (int ii = 0; ii < 5; ++ii) { \
+ if (lhs == rhs) \
+ break; \
+ QTest::qWait(50); \
+ } \
+ QCOMPARE(lhs, rhs); \
+} while (false)
+
+void tst_qdeclarativeanimations::simpleProperty()
+{
+ QQuickRectangle rect;
+ QDeclarativePropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "x");
+ QVERIFY(animation.to().toReal() == 200.0);
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.x(), 200.0);
+
+ rect.setPos(QPointF(0,0));
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.x(),100.0);
+}
+
+void tst_qdeclarativeanimations::simpleNumber()
+{
+ QQuickRectangle rect;
+ QDeclarativeNumberAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "x");
+ QVERIFY(animation.to() == 200);
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.x(), qreal(200));
+
+ rect.setX(0);
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.x(), qreal(100));
+}
+
+void tst_qdeclarativeanimations::simpleColor()
+{
+ QQuickRectangle rect;
+ QDeclarativeColorAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("color");
+ animation.setTo(QColor("red"));
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "color");
+ QVERIFY(animation.to() == QColor("red"));
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.color(), QColor("red"));
+
+ rect.setColor(QColor("blue"));
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
+
+ rect.setColor(QColor("green"));
+ animation.setFrom(QColor("blue"));
+ QVERIFY(animation.from() == QColor("blue"));
+ animation.restart();
+ QCOMPARE(rect.color(), QColor("blue"));
+ QVERIFY(animation.isRunning());
+ animation.setCurrentTime(125);
+ QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
+}
+
+void tst_qdeclarativeanimations::simpleRotation()
+{
+ QQuickRectangle rect;
+ QDeclarativeRotationAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("rotation");
+ animation.setTo(270);
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "rotation");
+ QVERIFY(animation.to() == 270);
+ QVERIFY(animation.direction() == QDeclarativeRotationAnimation::Numerical);
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTIMED_COMPARE(rect.rotation(), qreal(270));
+
+ rect.setRotation(0);
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.rotation(), qreal(135));
+}
+
+void tst_qdeclarativeanimations::simplePath()
+{
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimation.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
+ QVERIFY(redRect);
+ QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
+ QVERIFY(pathAnim);
+
+ pathAnim->start();
+ pathAnim->pause();
+
+ pathAnim->setCurrentTime(30);
+ QCOMPARE(redRect->x(), qreal(167));
+ QCOMPARE(redRect->y(), qreal(104));
+
+ pathAnim->setCurrentTime(100);
+ QCOMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+
+ //verify animation runs to end
+ pathAnim->start();
+ QCOMPARE(redRect->x(), qreal(50));
+ QCOMPARE(redRect->y(), qreal(50));
+ QTRY_COMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+
+ pathAnim->setOrientation(QQuickPathAnimation::RightFirst);
+ QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
+ pathAnim->start();
+ QTRY_VERIFY(redRect->rotation() != 0);
+ pathAnim->stop();
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimation2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
+ QVERIFY(redRect);
+ QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
+ QVERIFY(pathAnim);
+
+ QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
+
+ pathAnim->start();
+ pathAnim->pause();
+ QCOMPARE(redRect->x(), qreal(50));
+ QCOMPARE(redRect->y(), qreal(50));
+ QCOMPARE(redRect->rotation(), qreal(-360));
+
+ pathAnim->setCurrentTime(50);
+ QCOMPARE(redRect->x(), qreal(175));
+ QCOMPARE(redRect->y(), qreal(175));
+ QCOMPARE(redRect->rotation(), qreal(-315));
+
+ pathAnim->setCurrentTime(100);
+ QCOMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+ QCOMPARE(redRect->rotation(), qreal(0));
+ }
+}
+
+void tst_qdeclarativeanimations::pathInterpolator()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathInterpolator.qml")));
+ QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
+ QVERIFY(interpolator);
+
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(0));
+
+ interpolator->setProgress(.5);
+ QCOMPARE(interpolator->progress(), qreal(.5));
+ QCOMPARE(interpolator->x(), qreal(175));
+ QCOMPARE(interpolator->y(), qreal(175));
+ QCOMPARE(interpolator->angle(), qreal(270));
+
+ interpolator->setProgress(1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+ QCOMPARE(interpolator->x(), qreal(300));
+ QCOMPARE(interpolator->y(), qreal(300));
+ QCOMPARE(interpolator->angle(), qreal(0));
+}
+
+void tst_qdeclarativeanimations::pathInterpolatorBackwardJump()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathInterpolatorBack.qml")));
+ QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
+ QVERIFY(interpolator);
+
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(270));
+
+ interpolator->setProgress(.5);
+ QCOMPARE(interpolator->progress(), qreal(.5));
+ QCOMPARE(interpolator->x(), qreal(100));
+ QCOMPARE(interpolator->y(), qreal(75));
+ QCOMPARE(interpolator->angle(), qreal(90));
+
+ interpolator->setProgress(1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+ QCOMPARE(interpolator->x(), qreal(200));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(0));
+
+ //make sure we don't get caught in infinite loop here
+ interpolator->setProgress(0);
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(270));
+}
+
+void tst_qdeclarativeanimations::pathWithNoStart()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathAnimationNoStart.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
+ QVERIFY(redRect);
+ QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
+ QVERIFY(pathAnim);
+
+ pathAnim->start();
+ pathAnim->pause();
+ QCOMPARE(redRect->x(), qreal(50));
+ QCOMPARE(redRect->y(), qreal(50));
+
+ pathAnim->setCurrentTime(50);
+ QCOMPARE(redRect->x(), qreal(175));
+ QCOMPARE(redRect->y(), qreal(175));
+
+ pathAnim->setCurrentTime(100);
+ QCOMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+
+ redRect->setX(100);
+ redRect->setY(100);
+ pathAnim->start();
+ QCOMPARE(redRect->x(), qreal(100));
+ QCOMPARE(redRect->y(), qreal(100));
+ QTRY_COMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+}
+
+void tst_qdeclarativeanimations::alwaysRunToEnd()
+{
+ QQuickRectangle rect;
+ QDeclarativePropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ animation.setDuration(1000);
+ animation.setLoops(-1);
+ animation.setAlwaysRunToEnd(true);
+ QVERIFY(animation.loops() == -1);
+ QVERIFY(animation.alwaysRunToEnd() == true);
+ animation.start();
+ QTest::qWait(1500);
+ animation.stop();
+ QVERIFY(rect.x() != qreal(200));
+ QTest::qWait(500);
+ QTIMED_COMPARE(rect.x(), qreal(200));
+}
+
+void tst_qdeclarativeanimations::complete()
+{
+ QQuickRectangle rect;
+ QDeclarativePropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setFrom(1);
+ animation.setTo(200);
+ animation.setDuration(500);
+ QVERIFY(animation.from() == 1);
+ animation.start();
+ QTest::qWait(50);
+ animation.stop();
+ QVERIFY(rect.x() != qreal(200));
+ animation.start();
+ QTest::qWait(50);
+ QVERIFY(animation.isRunning());
+ animation.complete();
+ QCOMPARE(rect.x(), qreal(200));
+}
+
+void tst_qdeclarativeanimations::resume()
+{
+ QQuickRectangle rect;
+ QDeclarativePropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setFrom(10);
+ animation.setTo(200);
+ animation.setDuration(1000);
+ QVERIFY(animation.from() == 10);
+
+ animation.start();
+ QTest::qWait(400);
+ animation.pause();
+ qreal x = rect.x();
+ QVERIFY(x != qreal(200) && x != qreal(10));
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+
+ animation.resume();
+ QVERIFY(animation.isRunning());
+ QVERIFY(!animation.isPaused());
+ QTest::qWait(400);
+ animation.stop();
+ QVERIFY(rect.x() > x);
+}
+
+void tst_qdeclarativeanimations::dotProperty()
+{
+ QQuickRectangle rect;
+ QDeclarativeNumberAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("border.width");
+ animation.setTo(10);
+ animation.start();
+ QTest::qWait(animation.duration()+50);
+ QTIMED_COMPARE(rect.border()->width(), 10.0);
+
+ rect.border()->setWidth(0);
+ animation.start();
+ animation.pause();
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.border()->width(), 5.0);
+}
+
+void tst_qdeclarativeanimations::badTypes()
+{
+ //don't crash
+ {
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("badtype1.qml")));
+
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ //make sure we get a compiler error
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype2.qml")));
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ c.create();
+
+ QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
+ }
+
+ //make sure we get a compiler error
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype3.qml")));
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ c.create();
+
+ QVERIFY(c.errors().count() == 1);
+ QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
+ }
+
+ //don't crash
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("badtype4.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QTest::qWait(1000 + 50);
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
+ QVERIFY(myRect);
+ QCOMPARE(myRect->x(),qreal(200));
+ }
+}
+
+void tst_qdeclarativeanimations::badProperties()
+{
+ //make sure we get a runtime error
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c1(&engine, QUrl::fromLocalFile(TESTDATA("badproperty1.qml")));
+ QByteArray message = QUrl::fromLocalFile(TESTDATA("badproperty1.qml")).toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate non-existent property \"border.colr\"";
+ QTest::ignoreMessage(QtWarningMsg, message);
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c1.create());
+ QVERIFY(rect);
+
+ QDeclarativeComponent c2(&engine, QUrl::fromLocalFile(TESTDATA("badproperty2.qml")));
+ message = QUrl::fromLocalFile(TESTDATA("badproperty2.qml")).toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate read-only property \"border\"";
+ QTest::ignoreMessage(QtWarningMsg, message);
+ rect = qobject_cast<QQuickRectangle*>(c2.create());
+ QVERIFY(rect);
+
+ //### should we warn here are well?
+ //rect->setState("state1");
+ }
+}
+
+//test animating mixed types with property animation in a transition
+//for example, int + real; color + real; etc
+void tst_qdeclarativeanimations::mixedTypes()
+{
+ //assumes border.width stays a real -- not real robust
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("mixedtype1.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QTest::qWait(500);
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
+ QVERIFY(myRect);
+
+ //rather inexact -- is there a better way?
+ QVERIFY(myRect->x() > 100 && myRect->x() < 200);
+ QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10);
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("mixedtype2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QTest::qWait(500);
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
+ QVERIFY(myRect);
+
+ //rather inexact -- is there a better way?
+ QVERIFY(myRect->x() > 100 && myRect->x() < 200);
+ QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue"));
+ }
+}
+
+void tst_qdeclarativeanimations::properties()
+{
+ const int waitDuration = 300;
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties3.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(300));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties4.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->y(),qreal(200));
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties5.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+ QTIMED_COMPARE(myRect->y(),qreal(200));
+ }
+}
+
+void tst_qdeclarativeanimations::propertiesTransition()
+{
+ const int waitDuration = 300;
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ QCOMPARE(myRect->y(),qreal(100));
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->y(),qreal(200));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition3.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+ QCOMPARE(myRect->y(),qreal(100));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition4.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(100));
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition5.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(100));
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+ /*{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition6.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(100));
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+ }*/
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("propertiesTransition7.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+ QTest::qWait(waitDuration);
+ QTIMED_COMPARE(myRect->x(),qreal(200));
+ }
+
+}
+
+void tst_qdeclarativeanimations::pathTransition()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathTransition.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("redRect");
+ QVERIFY(myRect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
+ QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(100)) && qFuzzyCompare(myRect->y(), qreal(700)));
+ QTest::qWait(100);
+
+ QQuickItemPrivate::get(rect)->setState("");
+ QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
+ QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(500)) && qFuzzyCompare(myRect->y(), qreal(50)));
+}
+
+void tst_qdeclarativeanimations::disabledTransition()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("disabledTransition.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
+ QVERIFY(myRect);
+
+ QDeclarativeTransition *trans = rect->findChild<QDeclarativeTransition*>();
+ QVERIFY(trans);
+
+ QCOMPARE(trans->enabled(), false);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QCOMPARE(myRect->x(),qreal(200));
+
+ trans->setEnabled(true);
+
+ QQuickItemPrivate::get(rect)->setState("");
+ QCOMPARE(myRect->x(),qreal(200));
+ QTest::qWait(300);
+ QTIMED_COMPARE(myRect->x(),qreal(100));
+}
+
+void tst_qdeclarativeanimations::invalidDuration()
+{
+ QDeclarativePropertyAnimation *animation = new QDeclarativePropertyAnimation;
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PropertyAnimation: Cannot set a duration of < 0");
+ animation->setDuration(-1);
+ QCOMPARE(animation->duration(), 250);
+
+ QDeclarativePauseAnimation *pauseAnimation = new QDeclarativePauseAnimation;
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PauseAnimation: Cannot set a duration of < 0");
+ pauseAnimation->setDuration(-1);
+ QCOMPARE(pauseAnimation->duration(), 250);
+}
+
+void tst_qdeclarativeanimations::attached()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("attached.qml")));
+ QTest::ignoreMessage(QtDebugMsg, "off");
+ QTest::ignoreMessage(QtDebugMsg, "on");
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+}
+
+void tst_qdeclarativeanimations::propertyValueSourceDefaultStart()
+{
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valuesource.qml")));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim);
+ QVERIFY(myAnim->isRunning());
+ }
+
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valuesource2.qml")));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim);
+ QVERIFY(myAnim->isRunning() == false);
+ }
+
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontAutoStart.qml")));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim && myAnim->qtAnimation());
+ QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
+ }
+}
+
+
+void tst_qdeclarativeanimations::dontStart()
+{
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart.qml")));
+
+ QString warning = c.url().toString() + ":14:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim && myAnim->qtAnimation());
+ QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
+ }
+
+ {
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart2.qml")));
+
+ QString warning = c.url().toString() + ":15:17: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim && myAnim->qtAnimation());
+ QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
+ }
+}
+
+void tst_qdeclarativeanimations::easingProperties()
+{
+ {
+ QDeclarativeEngine engine;
+ QString componentStr = "import QtQuick 2.0\nNumberAnimation { easing.type: \"InOutQuad\" }";
+ QDeclarativeComponent animationComponent(&engine);
+ animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
+
+ QVERIFY(animObject != 0);
+ QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutBounce\"; easing.amplitude: 5.0 }";
+ QDeclarativeComponent animationComponent(&engine);
+ animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
+
+ QVERIFY(animObject != 0);
+ QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
+ QCOMPARE(animObject->easing().amplitude(), 5.0);
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutElastic\"; easing.amplitude: 5.0; easing.period: 3.0}";
+ QDeclarativeComponent animationComponent(&engine);
+ animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
+
+ QVERIFY(animObject != 0);
+ QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
+ QCOMPARE(animObject->easing().amplitude(), 5.0);
+ QCOMPARE(animObject->easing().period(), 3.0);
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"InOutBack\"; easing.overshoot: 2 }";
+ QDeclarativeComponent animationComponent(&engine);
+ animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativePropertyAnimation *animObject = qobject_cast<QDeclarativePropertyAnimation*>(animationComponent.create());
+
+ QVERIFY(animObject != 0);
+ QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
+ QCOMPARE(animObject->easing().overshoot(), 2.0);
+ }
+}
+
+void tst_qdeclarativeanimations::rotation()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("rotation.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *rr = rect->findChild<QQuickRectangle*>("rr");
+ QQuickRectangle *rr2 = rect->findChild<QQuickRectangle*>("rr2");
+ QQuickRectangle *rr3 = rect->findChild<QQuickRectangle*>("rr3");
+ QQuickRectangle *rr4 = rect->findChild<QQuickRectangle*>("rr4");
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QTest::qWait(800);
+ qreal r1 = rr->rotation();
+ qreal r2 = rr2->rotation();
+ qreal r3 = rr3->rotation();
+ qreal r4 = rr4->rotation();
+
+ QVERIFY(r1 > qreal(0) && r1 < qreal(370));
+ QVERIFY(r2 > qreal(0) && r2 < qreal(370));
+ QVERIFY(r3 < qreal(0) && r3 > qreal(-350));
+ QVERIFY(r4 > qreal(0) && r4 < qreal(10));
+ QCOMPARE(r1,r2);
+ QVERIFY(r4 < r2);
+
+ QTest::qWait(800);
+ QTIMED_COMPARE(rr->rotation() + rr2->rotation() + rr3->rotation() + rr4->rotation(), qreal(370*4));
+}
+
+void tst_qdeclarativeanimations::runningTrueBug()
+{
+ //ensure we start correctly when "running: true" is explicitly set
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("runningTrueBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *cloud = rect->findChild<QQuickRectangle*>("cloud");
+ QVERIFY(cloud);
+ QTest::qWait(1000);
+ QVERIFY(cloud->x() > qreal(0));
+}
+
+//QTBUG-12805
+void tst_qdeclarativeanimations::nonTransitionBug()
+{
+ //tests that the animation values from the previous transition are properly cleared
+ //in the case where an animation in the transition doesn't match anything (but previously did)
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("nonTransitionBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
+
+ mover->setX(100);
+ QCOMPARE(mover->x(), qreal(100));
+
+ rectPrivate->setState("left");
+ QTRY_COMPARE(mover->x(), qreal(0));
+
+ mover->setX(100);
+ QCOMPARE(mover->x(), qreal(100));
+
+ //make sure we don't try to animate back to 0
+ rectPrivate->setState("free");
+ QTest::qWait(300);
+ QCOMPARE(mover->x(), qreal(100));
+}
+
+//QTBUG-14042
+void tst_qdeclarativeanimations::registrationBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("registrationBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
+}
+
+void tst_qdeclarativeanimations::doubleRegistrationBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("doubleRegistrationBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QDeclarativeAbstractAnimation *anim = rect->findChild<QDeclarativeAbstractAnimation*>("animation");
+ QVERIFY(anim != 0);
+ QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Stopped);
+}
+
+//QTBUG-16736
+void tst_qdeclarativeanimations::alwaysRunToEndRestartBug()
+{
+ QQuickRectangle rect;
+ QDeclarativePropertyAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ animation.setDuration(1000);
+ animation.setLoops(-1);
+ animation.setAlwaysRunToEnd(true);
+ QVERIFY(animation.loops() == -1);
+ QVERIFY(animation.alwaysRunToEnd() == true);
+ animation.start();
+ animation.stop();
+ animation.start();
+ animation.stop();
+ QTest::qWait(500);
+ QVERIFY(rect.x() != qreal(200));
+ QTest::qWait(800);
+ QTIMED_COMPARE(rect.x(), qreal(200));
+ QCOMPARE(static_cast<QDeclarativeAbstractAnimation*>(&animation)->qtAnimation()->state(), QAbstractAnimation::Stopped);
+}
+
+//QTBUG-20227
+void tst_qdeclarativeanimations::transitionAssignmentBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("transitionAssignmentBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->property("nullObject").toBool(), false);
+}
+
+//QTBUG-19080
+void tst_qdeclarativeanimations::pauseBindingBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pauseBindingBug.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QDeclarativeAbstractAnimation *anim = rect->findChild<QDeclarativeAbstractAnimation*>("animation");
+ QVERIFY(anim->qtAnimation()->state() == QAbstractAnimation::Paused);
+
+ delete rect;
+}
+
+//QTBUG-13598
+void tst_qdeclarativeanimations::pauseBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pauseBug.qml")));
+ QDeclarativeAbstractAnimation *anim = qobject_cast<QDeclarativeAbstractAnimation*>(c.create());
+ QVERIFY(anim != 0);
+ QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Paused);
+ QCOMPARE(anim->isPaused(), true);
+ QCOMPARE(anim->isRunning(), true);
+
+ delete anim;
+}
+
+QTEST_MAIN(tst_qdeclarativeanimations)
+
+#include "tst_qdeclarativeanimations.moc"
diff --git a/tests/auto/qtquick2/qdeclarativeapplication/qdeclarativeapplication.pro b/tests/auto/qtquick2/qdeclarativeapplication/qdeclarativeapplication.pro
new file mode 100644
index 0000000000..b86f431d31
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativeapplication/qdeclarativeapplication.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativeapplication
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativeapplication.cpp
+QT += core-private gui-private declarative-private quick-private testlib
+
diff --git a/tests/auto/qtquick2/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/qtquick2/qdeclarativeapplication/tst_qdeclarativeapplication.cpp
new file mode 100644
index 0000000000..be822d8f7f
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativeapplication/tst_qdeclarativeapplication.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+#include <QtGui/qinputpanel.h>
+
+class tst_qdeclarativeapplication : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativeapplication();
+
+private slots:
+ void active();
+ void layoutDirection();
+ void inputPanel();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qdeclarativeapplication::tst_qdeclarativeapplication()
+{
+}
+
+void tst_qdeclarativeapplication::active()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Item { property bool active: Qt.application.active }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickView view;
+ item->setParentItem(view.rootObject());
+
+ // not active
+ QVERIFY(!item->property("active").toBool());
+ QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
+
+ // active
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWait(50);
+ QEXPECT_FAIL("", "QTBUG-21573", Abort);
+ QTRY_COMPARE(view.status(), QQuickView::Ready);
+ QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
+
+#if 0
+ // QGuiApplication has no equivalent of setActiveWindow(0). QTBUG-21573
+ // Is this different to clearing the active state of the window or can it be removed?
+ // On Mac, setActiveWindow(0) on mac does not deactivate the current application,
+ // must switch to a different app or hide the current app to trigger this
+ // on mac, setActiveWindow(0) on mac does not deactivate the current application
+ // (you have to switch to a different app or hide the current app to trigger this)
+
+ // not active again
+ QGuiApplication::setActiveWindow(0);
+ QVERIFY(!item->property("active").toBool());
+ QCOMPARE(item->property("active").toBool(), QGuiApplication::activeWindow() != 0);
+#endif
+
+}
+
+void tst_qdeclarativeapplication::layoutDirection()
+{
+
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Item { property bool layoutDirection: Qt.application.layoutDirection }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickView view;
+ item->setParentItem(view.rootObject());
+
+ // not mirrored
+ QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight);
+
+ // mirrored
+ QGuiApplication::setLayoutDirection(Qt::RightToLeft);
+ QEXPECT_FAIL("", "QTBUG-21573", Abort);
+ QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::RightToLeft);
+
+ // not mirrored again
+ QGuiApplication::setLayoutDirection(Qt::LeftToRight);
+ QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight);
+}
+
+void tst_qdeclarativeapplication::inputPanel()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Item { property variant inputPanel: Qt.application.inputPanel }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
+ QVERIFY(item);
+ QQuickView view;
+ item->setParentItem(view.rootObject());
+
+ // check that the inputPanel property maches with application's input panel
+ QCOMPARE(qvariant_cast<QObject*>(item->property("inputPanel")), qApp->inputPanel());
+}
+
+QTEST_MAIN(tst_qdeclarativeapplication)
+
+#include "tst_qdeclarativeapplication.moc"
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/binding.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/binding.qml
index 5aceefa743..5aceefa743 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/binding.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/binding.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/color.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/color.qml
index a318578a9b..a318578a9b 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/color.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/color.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/cpptrigger.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/cpptrigger.qml
index f033ec5aeb..f033ec5aeb 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/cpptrigger.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/cpptrigger.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/delayedRegistration.qml
index ed35a308f7..ed35a308f7 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/delayedRegistration.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/disabled.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/disabled.qml
index 20860d8dde..20860d8dde 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/disabled.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/disabled.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/dontStart.qml
index 38e1ea9d9e..38e1ea9d9e 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/dontStart.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/empty.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/empty.qml
index d8f115390a..d8f115390a 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/empty.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/empty.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/explicit.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/explicit.qml
index 20875c30e3..20875c30e3 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/explicit.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/explicit.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/groupProperty.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty.qml
index a05ab7d54b..a05ab7d54b 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/groupProperty.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/groupProperty2.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty2.qml
index 2f3de5131c..2f3de5131c 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/groupProperty2.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupProperty2.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/groupedPropertyCrash.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupedPropertyCrash.qml
index 6835902bc5..6835902bc5 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/groupedPropertyCrash.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/groupedPropertyCrash.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/loop.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/loop.qml
index 3e8d88734d..3e8d88734d 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/loop.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/loop.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/nonSelecting2.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/nonSelecting2.qml
index 6357094cfe..6357094cfe 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/nonSelecting2.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/nonSelecting2.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/parent.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/parent.qml
index f8c2731d86..f8c2731d86 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/parent.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/parent.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/qtbug12295.qml
index c6bef581a4..c6bef581a4 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/qtbug12295.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/reassignedAnimation.qml
index 5731cb3efd..5731cb3efd 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/reassignedAnimation.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/runningTrue.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/runningTrue.qml
index 4fd1136f3a..4fd1136f3a 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/runningTrue.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/runningTrue.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/scripttrigger.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/scripttrigger.qml
index ff71f2b1b0..ff71f2b1b0 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/scripttrigger.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/scripttrigger.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/simple.qml
index c64a6e1928..c64a6e1928 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/simple.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/startOnCompleted.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/startOnCompleted.qml
index fdc3779a5c..fdc3779a5c 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/startOnCompleted.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/startOnCompleted.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/startup.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/startup.qml
index 9fa74ca39e..9fa74ca39e 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/startup.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/startup.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/startup2.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/startup2.qml
index 0654ef3644..0654ef3644 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/startup2.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/startup2.qml
diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/valueType.qml b/tests/auto/qtquick2/qdeclarativebehaviors/data/valueType.qml
index 7bc8297dc7..7bc8297dc7 100644
--- a/tests/auto/declarative/qdeclarativebehaviors/data/valueType.qml
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/data/valueType.qml
diff --git a/tests/auto/qtquick2/qdeclarativebehaviors/qdeclarativebehaviors.pro b/tests/auto/qtquick2/qdeclarativebehaviors/qdeclarativebehaviors.pro
new file mode 100644
index 0000000000..3ac9446a4c
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/qdeclarativebehaviors.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativebehaviors
+SOURCES += tst_qdeclarativebehaviors.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp b/tests/auto/qtquick2/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp
new file mode 100644
index 0000000000..526a23f262
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <qsignalspy.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qdeclarativebehavior_p.h>
+#include <QtQuick/private/qdeclarativeanimation_p.h>
+#include <private/qquickitem_p.h>
+#include "../../shared/util.h"
+
+class tst_qdeclarativebehaviors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativebehaviors() {}
+
+private slots:
+ void init() { qApp->processEvents(); } //work around animation timer bug (QTBUG-22865)
+ void simpleBehavior();
+ void scriptTriggered();
+ void cppTriggered();
+ void loop();
+ void colorBehavior();
+ void parentBehavior();
+ void replaceBinding();
+ //void transitionOverrides();
+ void group();
+ void valueType();
+ void emptyBehavior();
+ void explicitSelection();
+ void nonSelectingBehavior();
+ void reassignedAnimation();
+ void disabled();
+ void dontStart();
+ void startup();
+ void groupedPropertyCrash();
+ void runningTrue();
+ void sameValue();
+ void delayedRegistration();
+ void startOnCompleted();
+};
+
+void tst_qdeclarativebehaviors::simpleBehavior()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("simple.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+ QTRY_VERIFY(qobject_cast<QDeclarativeBehavior*>(rect->findChild<QDeclarativeBehavior*>("MyBehavior"))->animation());
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
+ //i.e. the behavior has been triggered
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::scriptTriggered()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("scripttrigger.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ rect->setColor(QColor("red"));
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
+ //i.e. the behavior has been triggered
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::cppTriggered()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("cpptrigger.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QTRY_VERIFY(innerRect);
+
+ innerRect->setProperty("x", 200);
+ QTRY_VERIFY(innerRect->x() > 0);
+ QTRY_VERIFY(innerRect->x() < 200); //i.e. the behavior has been triggered
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::loop()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("loop.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ //don't crash
+ QQuickItemPrivate::get(rect)->setState("moved");
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::colorBehavior()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("color.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("red");
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("red"));
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->color() != QColor("green"));
+ //i.e. the behavior has been triggered
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::parentBehavior()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("parent.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("reparented");
+ QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() != rect->findChild<QQuickItem*>("NewParent"));
+ QTRY_VERIFY(rect->findChild<QQuickRectangle*>("MyRect")->parentItem() == rect->findChild<QQuickItem*>("NewParent"));
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::replaceBinding()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("binding.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QTRY_VERIFY(innerRect);
+ QTRY_VERIFY(innerRect->x() > 0);
+ QTRY_VERIFY(innerRect->x() < 200);
+ //i.e. the behavior has been triggered
+ QTRY_COMPARE(innerRect->x(), (qreal)200);
+ rect->setProperty("basex", 10);
+ QTRY_COMPARE(innerRect->x(), (qreal)200);
+ rect->setProperty("movedx", 210);
+ QTRY_COMPARE(innerRect->x(), (qreal)210);
+
+ QQuickItemPrivate::get(rect)->setState("");
+ QTRY_VERIFY(innerRect->x() > 10);
+ QTRY_VERIFY(innerRect->x() < 210); //i.e. the behavior has been triggered
+ QTRY_COMPARE(innerRect->x(), (qreal)10);
+ rect->setProperty("movedx", 200);
+ QTRY_COMPARE(innerRect->x(), (qreal)10);
+ rect->setProperty("basex", 20);
+ QTRY_COMPARE(innerRect->x(), (qreal)20);
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::group()
+{
+ /* XXX TODO Create a test element for this case.
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupProperty.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ qDebug() << c.errorString();
+ QTRY_VERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ //QTest::qWait(200);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
+ //i.e. the behavior has been triggered
+
+ delete rect;
+ }
+ */
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupProperty2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QTRY_VERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() > 0);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->border()->width() < 4);
+ //i.e. the behavior has been triggered
+
+ delete rect;
+ }
+}
+
+void tst_qdeclarativebehaviors::valueType()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("valueType.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ //QTBUG-20827
+ QCOMPARE(rect->color(), QColor::fromRgb(255,0,255));
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::emptyBehavior()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("empty.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::explicitSelection()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("explicit.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() > 0);
+ QTRY_VERIFY(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x() < 200);
+ //i.e. the behavior has been triggered
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::nonSelectingBehavior()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("nonSelecting2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::reassignedAnimation()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("reassignedAnimation.qml")));
+ QString warning = QUrl::fromLocalFile(TESTDATA("reassignedAnimation.qml")).toString() + ":9:9: QML Behavior: Cannot change the animation assigned to a Behavior.";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+ QCOMPARE(qobject_cast<QDeclarativeNumberAnimation*>(
+ rect->findChild<QDeclarativeBehavior*>("MyBehavior")->animation())->duration(), 200);
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::disabled()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("disabled.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+ QCOMPARE(rect->findChild<QDeclarativeBehavior*>("MyBehavior")->enabled(), false);
+
+ QQuickItemPrivate::get(rect)->setState("moved");
+ qreal x = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::dontStart()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("dontStart.qml")));
+
+ QString warning = c.url().toString() + ":13:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *myAnim = rect->findChild<QDeclarativeAbstractAnimation*>("MyAnim");
+ QVERIFY(myAnim && myAnim->qtAnimation());
+ QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimation::Stopped);
+
+ delete rect;
+}
+
+void tst_qdeclarativebehaviors::startup()
+{
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startup.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
+ QVERIFY(innerRect);
+
+ QCOMPARE(innerRect->x(), qreal(100)); //should be set immediately
+
+ delete rect;
+ }
+
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startup2.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *innerRect = rect->findChild<QQuickRectangle*>("innerRect");
+ QVERIFY(innerRect);
+
+ QQuickText *text = rect->findChild<QQuickText*>();
+ QVERIFY(text);
+
+ QCOMPARE(innerRect->x(), text->width()); //should be set immediately
+
+ delete rect;
+ }
+}
+
+//QTBUG-10799
+void tst_qdeclarativebehaviors::groupedPropertyCrash()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("groupedPropertyCrash.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect); //don't crash
+
+ delete rect;
+}
+
+//QTBUG-5491
+void tst_qdeclarativebehaviors::runningTrue()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("runningTrue.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QDeclarativeAbstractAnimation *animation = rect->findChild<QDeclarativeAbstractAnimation*>("rotAnim");
+ QVERIFY(animation);
+
+ QSignalSpy runningSpy(animation, SIGNAL(runningChanged(bool)));
+ rect->setProperty("myValue", 180);
+ QTRY_VERIFY(runningSpy.count() > 0);
+
+ delete rect;
+}
+
+//QTBUG-12295
+void tst_qdeclarativebehaviors::sameValue()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("qtbug12295.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *target = rect->findChild<QQuickRectangle*>("myRect");
+ QVERIFY(target);
+
+ target->setX(100);
+ QCOMPARE(target->x(), qreal(100));
+
+ target->setProperty("x", 0);
+ QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100));
+ QTRY_VERIFY(target->x() == qreal(0)); //make sure Behavior has finished.
+
+ target->setX(100);
+ QCOMPARE(target->x(), qreal(100));
+
+ //this is the main point of the test -- the behavior needs to be triggered again
+ //even though we set 0 twice in a row.
+ target->setProperty("x", 0);
+ QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100));
+
+ delete rect;
+}
+
+//QTBUG-18362
+void tst_qdeclarativebehaviors::delayedRegistration()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("delayedRegistration.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickItem *innerRect = rect->property("myItem").value<QQuickItem*>();
+ QVERIFY(innerRect != 0);
+
+ QCOMPARE(innerRect->property("x").toInt(), int(0));
+
+ QTRY_COMPARE(innerRect->property("x").toInt(), int(100));
+}
+
+//QTBUG-22555
+void tst_qdeclarativebehaviors::startOnCompleted()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("startOnCompleted.qml")));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickItem *innerRect = rect->findChild<QQuickRectangle*>();
+ QVERIFY(innerRect != 0);
+
+ QCOMPARE(innerRect->property("x").toInt(), int(0));
+
+ QTRY_COMPARE(innerRect->property("x").toInt(), int(100));
+
+ delete rect;
+}
+
+QTEST_MAIN(tst_qdeclarativebehaviors)
+
+#include "tst_qdeclarativebehaviors.moc"
diff --git a/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf b/tests/auto/qtquick2/qdeclarativefontloader/data/daniel.ttf
index aae50d5035..aae50d5035 100644
--- a/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf
+++ b/tests/auto/qtquick2/qdeclarativefontloader/data/daniel.ttf
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf b/tests/auto/qtquick2/qdeclarativefontloader/data/dummy.ttf
index e69de29bb2..e69de29bb2 100644
--- a/tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf
+++ b/tests/auto/qtquick2/qdeclarativefontloader/data/dummy.ttf
diff --git a/tests/auto/declarative/qdeclarativefontloader/data/qtbug-20268.qml b/tests/auto/qtquick2/qdeclarativefontloader/data/qtbug-20268.qml
index 0eafdfa17b..0eafdfa17b 100644
--- a/tests/auto/declarative/qdeclarativefontloader/data/qtbug-20268.qml
+++ b/tests/auto/qtquick2/qdeclarativefontloader/data/qtbug-20268.qml
diff --git a/tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf b/tests/auto/qtquick2/qdeclarativefontloader/data/tarzeau_ocr_a.ttf
index cf93f9651f..cf93f9651f 100644
--- a/tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf
+++ b/tests/auto/qtquick2/qdeclarativefontloader/data/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/tests/auto/qtquick2/qdeclarativefontloader/qdeclarativefontloader.pro b/tests/auto/qtquick2/qdeclarativefontloader/qdeclarativefontloader.pro
new file mode 100644
index 0000000000..de9461f7ac
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativefontloader/qdeclarativefontloader.pro
@@ -0,0 +1,14 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativefontloader
+macx:CONFIG -= app_bundle
+
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qdeclarativefontloader.cpp ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qdeclarativefontloader/tst_qdeclarativefontloader.cpp b/tests/auto/qtquick2/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
new file mode 100644
index 0000000000..86789068ad
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativefontloader/tst_qdeclarativefontloader.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtQuick/private/qdeclarativefontloader_p.h>
+#include "../../shared/util.h"
+#include "../../shared/testhttpserver.h"
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+
+#define SERVER_PORT 14448
+
+class tst_qdeclarativefontloader : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativefontloader();
+
+private slots:
+ void init();
+ void noFont();
+ void namedFont();
+ void localFont();
+ void failLocalFont();
+ void webFont();
+ void redirWebFont();
+ void failWebFont();
+ void changeFont();
+ void changeFontSourceViaState();
+
+private:
+ QDeclarativeEngine engine;
+ TestHTTPServer server;
+};
+
+tst_qdeclarativefontloader::tst_qdeclarativefontloader() :
+ server(SERVER_PORT)
+{
+ server.serveDirectory(TESTDATA(""));
+}
+
+void tst_qdeclarativefontloader::init()
+{
+ QVERIFY(server.isValid());
+}
+
+void tst_qdeclarativefontloader::noFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QCOMPARE(fontObject->name(), QString(""));
+ QCOMPARE(fontObject->source(), QUrl(""));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Null);
+
+ delete fontObject;
+}
+
+void tst_qdeclarativefontloader::namedFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { name: \"Helvetica\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QCOMPARE(fontObject->source(), QUrl(""));
+ QCOMPARE(fontObject->name(), QString("Helvetica"));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+}
+
+void tst_qdeclarativefontloader::localFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + TESTDATA("tarzeau_ocr_a.ttf") + "\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+}
+
+void tst_qdeclarativefontloader::failLocalFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + QUrl::fromLocalFile(TESTDATA("dummy.ttf")).toString() + "\" }";
+ QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + QUrl::fromLocalFile(TESTDATA("dummy.ttf")).toString() + "\"").toUtf8().constData());
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString(""));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error);
+}
+
+void tst_qdeclarativefontloader::webFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }";
+ QDeclarativeComponent component(&engine);
+
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+}
+
+void tst_qdeclarativefontloader::redirWebFont()
+{
+ server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf");
+
+ QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }";
+ QDeclarativeComponent component(&engine);
+
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+}
+
+void tst_qdeclarativefontloader::failWebFont()
+{
+ 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\"");
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString(""));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error);
+}
+
+void tst_qdeclarativefontloader::changeFont()
+{
+ QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("font", QUrl::fromLocalFile(TESTDATA("tarzeau_ocr_a.ttf")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create());
+
+ QVERIFY(fontObject != 0);
+
+ QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged()));
+ QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged()));
+
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QCOMPARE(nameSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+
+ ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf");
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Loading);
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QCOMPARE(nameSpy.count(), 1);
+ QCOMPARE(statusSpy.count(), 2);
+ QTRY_COMPARE(fontObject->name(), QString("Daniel"));
+
+ ctxt->setContextProperty("font", QUrl::fromLocalFile(TESTDATA("tarzeau_ocr_a.ttf")));
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QCOMPARE(nameSpy.count(), 2);
+ QCOMPARE(statusSpy.count(), 2);
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+
+ ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf");
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QCOMPARE(nameSpy.count(), 3);
+ QCOMPARE(statusSpy.count(), 2);
+ QTRY_COMPARE(fontObject->name(), QString("Daniel"));
+}
+
+void tst_qdeclarativefontloader::changeFontSourceViaState()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("qtbug-20268.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(qvariant_cast<QObject *>(canvas.rootObject()->property("fontloader")));
+ QVERIFY(fontObject != 0);
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QVERIFY(fontObject->source() != QUrl(""));
+ QTRY_COMPARE(fontObject->name(), QString("OCRA"));
+
+ canvas.rootObject()->setProperty("usename", true);
+
+ // This warning should probably not be printed once QTBUG-20268 is fixed
+ QString warning = QString(QUrl::fromLocalFile(TESTDATA("qtbug-20268.qml")).toString()) +
+ QLatin1String(":13:5: QML FontLoader: Cannot load font: \"\"");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+
+ QEXPECT_FAIL("", "QTBUG-20268", Abort);
+ QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready);
+ QCOMPARE(canvas.rootObject()->property("name").toString(), QString("Tahoma"));
+}
+
+QTEST_MAIN(tst_qdeclarativefontloader)
+
+#include "tst_qdeclarativefontloader.moc"
diff --git a/tests/auto/declarative/qdeclarativepath/data/arc.qml b/tests/auto/qtquick2/qdeclarativepath/data/arc.qml
index 000221c784..000221c784 100644
--- a/tests/auto/declarative/qdeclarativepath/data/arc.qml
+++ b/tests/auto/qtquick2/qdeclarativepath/data/arc.qml
diff --git a/tests/auto/declarative/qdeclarativepath/data/curve.qml b/tests/auto/qtquick2/qdeclarativepath/data/curve.qml
index c571186496..c571186496 100644
--- a/tests/auto/declarative/qdeclarativepath/data/curve.qml
+++ b/tests/auto/qtquick2/qdeclarativepath/data/curve.qml
diff --git a/tests/auto/declarative/qdeclarativepath/data/svg.qml b/tests/auto/qtquick2/qdeclarativepath/data/svg.qml
index cec0f75061..cec0f75061 100644
--- a/tests/auto/declarative/qdeclarativepath/data/svg.qml
+++ b/tests/auto/qtquick2/qdeclarativepath/data/svg.qml
diff --git a/tests/auto/qtquick2/qdeclarativepath/qdeclarativepath.pro b/tests/auto/qtquick2/qdeclarativepath/qdeclarativepath.pro
new file mode 100644
index 0000000000..9f4204efa3
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativepath/qdeclarativepath.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativepath
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativepath.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp b/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp
new file mode 100644
index 0000000000..bf4f70b292
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/private/qdeclarativepath_p.h>
+
+#include "../../shared/util.h"
+
+class tst_QDeclarativePath : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDeclarativePath() {}
+
+private slots:
+ void arc();
+ void catmullromCurve();
+ void svg();
+};
+
+void tst_QDeclarativePath::arc()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("arc.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 1);
+
+ QDeclarativePathArc* arc = qobject_cast<QDeclarativePathArc*>(list.at(0));
+ QVERIFY(arc != 0);
+ QCOMPARE(arc->x(), 100.);
+ QCOMPARE(arc->y(), 100.);
+ QCOMPARE(arc->radiusX(), 100.);
+ QCOMPARE(arc->radiusY(), 100.);
+ QCOMPARE(arc->useLargeArc(), false);
+ QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(0,0));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(39,8)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(92,61)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(100,100));
+}
+
+void tst_QDeclarativePath::catmullromCurve()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("curve.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 3);
+
+ QDeclarativePathCatmullRomCurve* arc = qobject_cast<QDeclarativePathCatmullRomCurve*>(list.at(0));
+// QVERIFY(arc != 0);
+// QCOMPARE(arc->x(), 100.);
+// QCOMPARE(arc->y(), 100.);
+// QCOMPARE(arc->radiusX(), 100.);
+// QCOMPARE(arc->radiusY(), 100.);
+// QCOMPARE(arc->useLargeArc(), false);
+// QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(0,0));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(63,26)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(51,105)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(100,150));
+}
+
+void tst_QDeclarativePath::svg()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("svg.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 1);
+
+ QDeclarativePathSvg* svg = qobject_cast<QDeclarativePathSvg*>(list.at(0));
+ QVERIFY(svg != 0);
+ QCOMPARE(svg->path(), QLatin1String("M200,300 Q400,50 600,300 T1000,300"));
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(200,300));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(400,175)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(800,425)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(1000,300));
+}
+
+
+QTEST_MAIN(tst_QDeclarativePath)
+
+#include "tst_qdeclarativepath.moc"
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/exists.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/exists.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/exists1.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists1.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/exists1.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists1.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/exists2.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists2.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/exists2.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/exists2.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists1.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists1.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists1.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists1.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists2.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists2.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists2.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists2.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists3.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists3.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists3.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists3.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists4.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists4.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists4.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists4.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists5.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists5.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists5.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists5.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists6.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists6.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists6.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists6.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists7.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists7.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists7.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists7.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists8.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists8.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/http/exists8.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/http/exists8.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativepixmapcache/data/massive.png b/tests/auto/qtquick2/qdeclarativepixmapcache/data/massive.png
index bc6cc9e6ca..bc6cc9e6ca 100644
--- a/tests/auto/declarative/qdeclarativepixmapcache/data/massive.png
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/data/massive.png
Binary files differ
diff --git a/tests/auto/qtquick2/qdeclarativepixmapcache/qdeclarativepixmapcache.pro b/tests/auto/qtquick2/qdeclarativepixmapcache/qdeclarativepixmapcache.pro
new file mode 100644
index 0000000000..391c28c10a
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/qdeclarativepixmapcache.pro
@@ -0,0 +1,20 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativepixmapcache
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativepixmapcache.cpp
+
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += ../../shared/testhttpserver.cpp
+
+importFiles.files = data
+importFiles.path = .
+DEPLOYMENT += importFiles
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp b/tests/auto/qtquick2/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp
new file mode 100644
index 0000000000..2e326263c0
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp
@@ -0,0 +1,458 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QtTest>
+#include <QtQuick/private/qdeclarativepixmapcache_p.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeimageprovider.h>
+#include <QNetworkReply>
+#include "../../shared/util.h"
+#include "testhttpserver.h"
+
+#ifndef QT_NO_CONCURRENT
+#include <qtconcurrentrun.h>
+#include <qfuture.h>
+#endif
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(TESTDATA(filename));
+}
+
+class tst_qdeclarativepixmapcache : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativepixmapcache() :
+ server(14452)
+ {
+ server.serveDirectory(TESTDATA("http"));
+ }
+
+private slots:
+ void single();
+ void single_data();
+ void parallel();
+ void parallel_data();
+ void massive();
+ void cancelcrash();
+ void shrinkcache();
+#ifndef QT_NO_CONCURRENT
+ void networkCrash();
+#endif
+ void lockingCrash();
+ void dataLeak();
+private:
+ QDeclarativeEngine engine;
+ TestHTTPServer server;
+};
+
+static int slotters=0;
+
+class Slotter : public QObject
+{
+ Q_OBJECT
+public:
+ Slotter()
+ {
+ gotslot = false;
+ slotters++;
+ }
+ bool gotslot;
+
+public slots:
+ void got()
+ {
+ gotslot = true;
+ --slotters;
+ if (slotters==0)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+static const bool localfile_optimized = true;
+#else
+static const bool localfile_optimized = false;
+#endif
+
+void tst_qdeclarativepixmapcache::single_data()
+{
+ // Note, since QDeclarativePixmapCache is shared, tests affect each other!
+ // so use different files fore all test functions.
+
+ QTest::addColumn<QUrl>("target");
+ QTest::addColumn<bool>("incache");
+ QTest::addColumn<bool>("exists");
+ QTest::addColumn<bool>("neterror");
+
+ // File URLs are optimized
+ QTest::newRow("local") << TEST_FILE("exists.png") << localfile_optimized << true << false;
+ QTest::newRow("local") << TEST_FILE("notexists.png") << localfile_optimized << false << false;
+ QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/exists.png") << false << true << false;
+ QTest::newRow("remote") << QUrl("http://127.0.0.1:14452/notexists.png") << false << false << true;
+}
+
+void tst_qdeclarativepixmapcache::single()
+{
+ QFETCH(QUrl, target);
+ QFETCH(bool, incache);
+ QFETCH(bool, exists);
+ QFETCH(bool, neterror);
+
+ QString expectedError;
+ if (neterror) {
+ expectedError = "Error downloading " + target.toString() + " - server replied: Not found";
+ } else if (!exists) {
+ expectedError = "Cannot open: " + target.toString();
+ }
+
+ QDeclarativePixmap pixmap;
+ QVERIFY(pixmap.width() <= 0); // Check Qt assumption
+
+ pixmap.load(&engine, target);
+
+ if (incache) {
+ QCOMPARE(pixmap.error(), expectedError);
+ if (exists) {
+ QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
+ QVERIFY(pixmap.width() > 0);
+ } else {
+ QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
+ QVERIFY(pixmap.width() <= 0);
+ }
+ } else {
+ QVERIFY(pixmap.width() <= 0);
+
+ Slotter getter;
+ pixmap.connectFinished(&getter, SLOT(got()));
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(getter.gotslot);
+ if (exists) {
+ QVERIFY(pixmap.status() == QDeclarativePixmap::Ready);
+ QVERIFY(pixmap.width() > 0);
+ } else {
+ QVERIFY(pixmap.status() == QDeclarativePixmap::Error);
+ QVERIFY(pixmap.width() <= 0);
+ }
+ QCOMPARE(pixmap.error(), expectedError);
+ }
+}
+
+void tst_qdeclarativepixmapcache::parallel_data()
+{
+ // Note, since QDeclarativePixmapCache is shared, tests affect each other!
+ // so use different files fore all test functions.
+
+ QTest::addColumn<QUrl>("target1");
+ QTest::addColumn<QUrl>("target2");
+ QTest::addColumn<int>("incache");
+ QTest::addColumn<int>("cancel"); // which one to cancel
+
+ QTest::newRow("local")
+ << TEST_FILE("exists1.png")
+ << TEST_FILE("exists2.png")
+ << (localfile_optimized ? 2 : 0)
+ << -1;
+
+ QTest::newRow("remote")
+ << QUrl("http://127.0.0.1:14452/exists2.png")
+ << QUrl("http://127.0.0.1:14452/exists3.png")
+ << 0
+ << -1;
+
+ QTest::newRow("remoteagain")
+ << QUrl("http://127.0.0.1:14452/exists2.png")
+ << QUrl("http://127.0.0.1:14452/exists3.png")
+ << 2
+ << -1;
+
+ QTest::newRow("remotecopy")
+ << QUrl("http://127.0.0.1:14452/exists4.png")
+ << QUrl("http://127.0.0.1:14452/exists4.png")
+ << 0
+ << -1;
+
+ QTest::newRow("remotecopycancel")
+ << QUrl("http://127.0.0.1:14452/exists5.png")
+ << QUrl("http://127.0.0.1:14452/exists5.png")
+ << 0
+ << 0;
+}
+
+void tst_qdeclarativepixmapcache::parallel()
+{
+ QFETCH(QUrl, target1);
+ QFETCH(QUrl, target2);
+ QFETCH(int, incache);
+ QFETCH(int, cancel);
+
+ QList<QUrl> targets;
+ targets << target1 << target2;
+
+ QList<QDeclarativePixmap *> pixmaps;
+ QList<bool> pending;
+ QList<Slotter*> getters;
+
+ for (int i=0; i<targets.count(); ++i) {
+ QUrl target = targets.at(i);
+ QDeclarativePixmap *pixmap = new QDeclarativePixmap;
+
+ pixmap->load(&engine, target);
+
+ QVERIFY(pixmap->status() != QDeclarativePixmap::Error);
+ pixmaps.append(pixmap);
+ if (pixmap->isReady()) {
+ QVERIFY(pixmap->width() > 0);
+ getters.append(0);
+ pending.append(false);
+ } else {
+ QVERIFY(pixmap->width() <= 0);
+ getters.append(new Slotter);
+ pixmap->connectFinished(getters[i], SLOT(got()));
+ pending.append(true);
+ }
+ }
+
+ QCOMPARE(incache+slotters, targets.count());
+
+ if (cancel >= 0) {
+ pixmaps.at(cancel)->clear(getters[cancel]);
+ slotters--;
+ }
+
+ if (slotters) {
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ }
+
+ for (int i=0; i<targets.count(); ++i) {
+ QDeclarativePixmap *pixmap = pixmaps[i];
+
+ if (i == cancel) {
+ QVERIFY(!getters[i]->gotslot);
+ } else {
+ if (pending[i])
+ QVERIFY(getters[i]->gotslot);
+
+ QVERIFY(pixmap->isReady());
+ QVERIFY(pixmap->width() > 0);
+ delete getters[i];
+ }
+ }
+
+ qDeleteAll(pixmaps);
+}
+
+void tst_qdeclarativepixmapcache::massive()
+{
+ QDeclarativeEngine engine;
+ QUrl url = TEST_FILE("massive.png");
+
+ // Confirm that massive images remain in the cache while they are
+ // in use by the application.
+ {
+ qint64 cachekey = 0;
+ QDeclarativePixmap p(&engine, url);
+ QVERIFY(p.isReady());
+ QVERIFY(p.image().size() == QSize(10000, 1000));
+ cachekey = p.image().cacheKey();
+
+ QDeclarativePixmap p2(&engine, url);
+ QVERIFY(p2.isReady());
+ QVERIFY(p2.image().size() == QSize(10000, 1000));
+
+ QVERIFY(p2.image().cacheKey() == cachekey);
+ }
+
+ // Confirm that massive images are removed from the cache when
+ // they become unused
+ {
+ qint64 cachekey = 0;
+ {
+ QDeclarativePixmap p(&engine, url);
+ QVERIFY(p.isReady());
+ QVERIFY(p.image().size() == QSize(10000, 1000));
+ cachekey = p.image().cacheKey();
+ }
+
+ QDeclarativePixmap p2(&engine, url);
+ QVERIFY(p2.isReady());
+ QVERIFY(p2.image().size() == QSize(10000, 1000));
+
+ QVERIFY(p2.image().cacheKey() != cachekey);
+ }
+}
+
+// QTBUG-12729
+void tst_qdeclarativepixmapcache::cancelcrash()
+{
+ QUrl url("http://127.0.0.1:14452/cancelcrash_notexist.png");
+ for (int ii = 0; ii < 1000; ++ii) {
+ QDeclarativePixmap pix(&engine, url);
+ }
+}
+
+class MyPixmapProvider : public QDeclarativeImageProvider
+{
+public:
+ MyPixmapProvider()
+ : QDeclarativeImageProvider(Pixmap) {}
+
+ virtual QPixmap requestPixmap(const QString &d, QSize *, const QSize &) {
+ Q_UNUSED(d)
+ QPixmap pix(800, 600);
+ pix.fill(Qt::red);
+ return pix;
+ }
+};
+
+// QTBUG-13345
+void tst_qdeclarativepixmapcache::shrinkcache()
+{
+ QDeclarativeEngine engine;
+ engine.addImageProvider(QLatin1String("mypixmaps"), new MyPixmapProvider);
+
+ for (int ii = 0; ii < 4000; ++ii) {
+ QUrl url("image://mypixmaps/" + QString::number(ii));
+ QDeclarativePixmap p(&engine, url);
+ }
+}
+
+#ifndef QT_NO_CONCURRENT
+
+void createNetworkServer()
+{
+ QEventLoop eventLoop;
+ TestHTTPServer server(14453);
+ server.serveDirectory(TESTDATA("http"));
+ QTimer::singleShot(100, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+}
+
+#ifndef QT_NO_CONCURRENT
+// QT-3957
+void tst_qdeclarativepixmapcache::networkCrash()
+{
+ QFuture<void> future = QtConcurrent::run(createNetworkServer);
+ QDeclarativeEngine engine;
+ for (int ii = 0; ii < 100 ; ++ii) {
+ QDeclarativePixmap* pixmap = new QDeclarativePixmap;
+ pixmap->load(&engine, QUrl(QString("http://127.0.0.1:14453/exists.png")));
+ QTest::qSleep(1);
+ pixmap->clear();
+ delete pixmap;
+ }
+ future.cancel();
+}
+#endif
+
+#endif
+
+// QTBUG-22125
+void tst_qdeclarativepixmapcache::lockingCrash()
+{
+ TestHTTPServer server(14453);
+ server.serveDirectory(TESTDATA("http"), TestHTTPServer::Delay);
+
+ {
+ QDeclarativePixmap* p = new QDeclarativePixmap;
+ {
+ QDeclarativeEngine e;
+ p->load(&e, QUrl(QString("http://127.0.0.1:14453/exists6.png")));
+ }
+ p->clear();
+ QVERIFY(p->isNull());
+ delete p;
+ }
+}
+
+#include <QtQuick/QQuickView>
+class DataLeakView : public QQuickView
+{
+ Q_OBJECT
+
+public:
+ explicit DataLeakView() : QQuickView()
+ {
+ setSource(TEST_FILE("dataLeak.qml"));
+ }
+
+ void showFor2Seconds()
+ {
+ showFullScreen();
+ QTimer::singleShot(2000, this, SIGNAL(ready()));
+ }
+
+signals:
+ void ready();
+};
+
+// QTBUG-22742
+Q_GLOBAL_STATIC(QDeclarativePixmap, dataLeakPixmap)
+void tst_qdeclarativepixmapcache::dataLeak()
+{
+ // Should not leak cached QDeclarativePixmapData.
+ // Unfortunately, since the QDeclarativePixmapStore
+ // is a global static, and it releases the cache
+ // entries on dtor (application exit), we must use
+ // valgrind to determine whether it leaks or not.
+ QDeclarativePixmap *p1 = new QDeclarativePixmap;
+ QDeclarativePixmap *p2 = new QDeclarativePixmap;
+ {
+ QScopedPointer<DataLeakView> test(new DataLeakView);
+ test->showFor2Seconds();
+ dataLeakPixmap()->load(test->engine(), TEST_FILE("exists.png"));
+ p1->load(test->engine(), TEST_FILE("exists.png"));
+ p2->load(test->engine(), TEST_FILE("exists2.png"));
+ QTest::qWait(2005); // 2 seconds + a few more millis.
+ }
+
+ // When the (global static) dataLeakPixmap is deleted, it
+ // shouldn't attempt to dereference a QDeclarativePixmapData
+ // which has been deleted by the QDeclarativePixmapStore
+ // destructor.
+}
+
+QTEST_MAIN(tst_qdeclarativepixmapcache)
+
+#include "tst_qdeclarativepixmapcache.moc"
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation1.qml b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation1.qml
index 3631f971f0..3631f971f0 100644
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation1.qml
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation1.qml
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation2.qml b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation2.qml
index b07120234a..b07120234a 100644
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation2.qml
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation2.qml
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation3.qml b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation3.qml
index 8d5dc4a92b..8d5dc4a92b 100644
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimation3.qml
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimation3.qml
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml
index 81d36bf015..81d36bf015 100644
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationBehavior.qml
diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml
index e136df84f6..e136df84f6 100644
--- a/tests/auto/declarative/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/data/smoothedanimationValueSource.qml
diff --git a/tests/auto/qtquick2/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro b/tests/auto/qtquick2/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro
new file mode 100644
index 0000000000..1e8a7d5ba6
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativesmoothedanimation
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativesmoothedanimation.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp b/tests/auto/qtquick2/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp
new file mode 100644
index 0000000000..632bcda091
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativesmoothedanimation/tst_qdeclarativesmoothedanimation.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qdeclarativesmoothedanimation_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include "../../shared/util.h"
+
+class tst_qdeclarativesmoothedanimation : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativesmoothedanimation();
+
+private slots:
+ void defaultValues();
+ void values();
+ void disabled();
+ void simpleAnimation();
+ void valueSource();
+ void behavior();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qdeclarativesmoothedanimation::tst_qdeclarativesmoothedanimation()
+{
+}
+
+void tst_qdeclarativesmoothedanimation::defaultValues()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation1.qml")));
+ QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 0.);
+ QCOMPARE(obj->velocity(), 200.);
+ QCOMPARE(obj->duration(), -1);
+ QCOMPARE(obj->maximumEasingTime(), -1);
+ QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Eased);
+
+ delete obj;
+}
+
+void tst_qdeclarativesmoothedanimation::values()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation2.qml")));
+ QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 10.);
+ QCOMPARE(obj->velocity(), 200.);
+ QCOMPARE(obj->duration(), 300);
+ QCOMPARE(obj->maximumEasingTime(), -1);
+ QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Immediate);
+
+ delete obj;
+}
+
+void tst_qdeclarativesmoothedanimation::disabled()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimation3.qml")));
+ QDeclarativeSmoothedAnimation *obj = qobject_cast<QDeclarativeSmoothedAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 10.);
+ QCOMPARE(obj->velocity(), 250.);
+ QCOMPARE(obj->maximumEasingTime(), 150);
+ QCOMPARE(obj->reversingMode(), QDeclarativeSmoothedAnimation::Sync);
+
+ delete obj;
+}
+
+void tst_qdeclarativesmoothedanimation::simpleAnimation()
+{
+ QQuickRectangle rect;
+ QDeclarativeSmoothedAnimation animation;
+ animation.setTarget(&rect);
+ animation.setProperty("x");
+ animation.setTo(200);
+ animation.setDuration(250);
+ QVERIFY(animation.target() == &rect);
+ QVERIFY(animation.property() == "x");
+ QVERIFY(animation.to() == 200);
+ animation.start();
+ QVERIFY(animation.isRunning());
+ QTest::qWait(animation.duration());
+ QTRY_COMPARE(rect.x(), qreal(200));
+
+ rect.setX(0);
+ animation.start();
+ animation.pause();
+ QVERIFY(animation.isRunning());
+ QVERIFY(animation.isPaused());
+ animation.setCurrentTime(125);
+ QVERIFY(animation.currentTime() == 125);
+ QCOMPARE(rect.x(), qreal(100));
+}
+
+void tst_qdeclarativesmoothedanimation::valueSource()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimationValueSource.qml")));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
+ QVERIFY(theRect);
+
+ QDeclarativeSmoothedAnimation *easeX = rect->findChild<QDeclarativeSmoothedAnimation*>("easeX");
+ QVERIFY(easeX);
+ QVERIFY(easeX->isRunning());
+
+ QDeclarativeSmoothedAnimation *easeY = rect->findChild<QDeclarativeSmoothedAnimation*>("easeY");
+ QVERIFY(easeY);
+ QVERIFY(easeY->isRunning());
+
+ // XXX get the proper duration
+ QTest::qWait(100);
+
+ QTRY_VERIFY(!easeX->isRunning());
+ QTRY_VERIFY(!easeY->isRunning());
+
+ QTRY_COMPARE(theRect->x(), qreal(200));
+ QTRY_COMPARE(theRect->y(), qreal(200));
+
+ delete rect;
+}
+
+void tst_qdeclarativesmoothedanimation::behavior()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("smoothedanimationBehavior.qml")));
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
+ QVERIFY(theRect);
+
+ QDeclarativeSmoothedAnimation *easeX = rect->findChild<QDeclarativeSmoothedAnimation*>("easeX");
+ QVERIFY(easeX);
+
+ QDeclarativeSmoothedAnimation *easeY = rect->findChild<QDeclarativeSmoothedAnimation*>("easeY");
+ QVERIFY(easeY);
+
+ // XXX get the proper duration
+ QTest::qWait(400);
+
+ QTRY_VERIFY(!easeX->isRunning());
+ QTRY_VERIFY(!easeY->isRunning());
+
+ QTRY_COMPARE(theRect->x(), qreal(200));
+ QTRY_COMPARE(theRect->y(), qreal(200));
+
+ delete rect;
+}
+
+QTEST_MAIN(tst_qdeclarativesmoothedanimation)
+
+#include "tst_qdeclarativesmoothedanimation.moc"
diff --git a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation1.qml b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation1.qml
index 9f52aa56c1..9f52aa56c1 100644
--- a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation1.qml
+++ b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation1.qml
diff --git a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation2.qml b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation2.qml
index 172cc57ca8..172cc57ca8 100644
--- a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation2.qml
+++ b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation2.qml
diff --git a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation3.qml b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation3.qml
index f4dc121eb8..f4dc121eb8 100644
--- a/tests/auto/declarative/qdeclarativespringanimation/data/springanimation3.qml
+++ b/tests/auto/qtquick2/qdeclarativespringanimation/data/springanimation3.qml
diff --git a/tests/auto/qtquick2/qdeclarativespringanimation/qdeclarativespringanimation.pro b/tests/auto/qtquick2/qdeclarativespringanimation/qdeclarativespringanimation.pro
new file mode 100644
index 0000000000..3ac2551380
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativespringanimation/qdeclarativespringanimation.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativespringanimation
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativespringanimation.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp b/tests/auto/qtquick2/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp
new file mode 100644
index 0000000000..f7acc2a3e0
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativespringanimation/tst_qdeclarativespringanimation.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qdeclarativespringanimation_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include "../../shared/util.h"
+
+class tst_qdeclarativespringanimation : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativespringanimation();
+
+private slots:
+ void defaultValues();
+ void values();
+ void disabled();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qdeclarativespringanimation::tst_qdeclarativespringanimation()
+{
+}
+
+void tst_qdeclarativespringanimation::defaultValues()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation1.qml")));
+ QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 0.);
+ QCOMPARE(obj->velocity(), 0.);
+ QCOMPARE(obj->spring(), 0.);
+ QCOMPARE(obj->damping(), 0.);
+ QCOMPARE(obj->epsilon(), 0.01);
+ QCOMPARE(obj->modulus(), 0.);
+ QCOMPARE(obj->mass(), 1.);
+ QCOMPARE(obj->isRunning(), false);
+
+ delete obj;
+}
+
+void tst_qdeclarativespringanimation::values()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation2.qml")));
+ QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 1.44);
+ QCOMPARE(obj->velocity(), 0.9);
+ QCOMPARE(obj->spring(), 1.0);
+ QCOMPARE(obj->damping(), 0.5);
+ QCOMPARE(obj->epsilon(), 0.25);
+ QCOMPARE(obj->modulus(), 360.0);
+ QCOMPARE(obj->mass(), 2.0);
+ QCOMPARE(obj->isRunning(), true);
+
+ QTRY_COMPARE(obj->isRunning(), false);
+
+ delete obj;
+}
+
+void tst_qdeclarativespringanimation::disabled()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("springanimation3.qml")));
+ QDeclarativeSpringAnimation *obj = qobject_cast<QDeclarativeSpringAnimation*>(c.create());
+
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->to(), 1.44);
+ QCOMPARE(obj->velocity(), 0.9);
+ QCOMPARE(obj->spring(), 1.0);
+ QCOMPARE(obj->damping(), 0.5);
+ QCOMPARE(obj->epsilon(), 0.25);
+ QCOMPARE(obj->modulus(), 360.0);
+ QCOMPARE(obj->mass(), 2.0);
+ QCOMPARE(obj->isRunning(), false);
+
+ delete obj;
+}
+
+QTEST_MAIN(tst_qdeclarativespringanimation)
+
+#include "tst_qdeclarativespringanimation.moc"
diff --git a/tests/auto/declarative/qdeclarativestates/data/ExtendedRectangle.qml b/tests/auto/qtquick2/qdeclarativestates/data/ExtendedRectangle.qml
index 1ea346b841..1ea346b841 100644
--- a/tests/auto/declarative/qdeclarativestates/data/ExtendedRectangle.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/ExtendedRectangle.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/Implementation/MyType.qml b/tests/auto/qtquick2/qdeclarativestates/data/Implementation/MyType.qml
index 01eb32cd4d..01eb32cd4d 100644
--- a/tests/auto/declarative/qdeclarativestates/data/Implementation/MyType.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/Implementation/MyType.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/Implementation/images/qt-logo.png b/tests/auto/qtquick2/qdeclarativestates/data/Implementation/images/qt-logo.png
index 14ddf2a028..14ddf2a028 100644
--- a/tests/auto/declarative/qdeclarativestates/data/Implementation/images/qt-logo.png
+++ b/tests/auto/qtquick2/qdeclarativestates/data/Implementation/images/qt-logo.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativestates/data/QTBUG-14830.qml b/tests/auto/qtquick2/qdeclarativestates/data/QTBUG-14830.qml
index 5ba7c3ad6f..5ba7c3ad6f 100644
--- a/tests/auto/declarative/qdeclarativestates/data/QTBUG-14830.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/QTBUG-14830.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChanges1.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges1.qml
index 378f5390f9..378f5390f9 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChanges1.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges1.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChanges2.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges2.qml
index dc7f8ef0d1..dc7f8ef0d1 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChanges2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChanges3.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges3.qml
index af49575854..af49575854 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChanges3.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges3.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChanges4.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges4.qml
index 28b55818bd..28b55818bd 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChanges4.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges4.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChanges5.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges5.qml
index b1ca968fb9..b1ca968fb9 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChanges5.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChanges5.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorChangesCrash.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorChangesCrash.qml
index 9af0e4645a..9af0e4645a 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorChangesCrash.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorChangesCrash.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug.qml
index 60c537b1ed..60c537b1ed 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml b/tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug2.qml
index 574ef473ce..574ef473ce 100644
--- a/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/anchorRewindBug2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/attachedPropertyChanges.qml b/tests/auto/qtquick2/qdeclarativestates/data/attachedPropertyChanges.qml
index 413af2ee42..413af2ee42 100644
--- a/tests/auto/declarative/qdeclarativestates/data/attachedPropertyChanges.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/attachedPropertyChanges.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml b/tests/auto/qtquick2/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml
index 6cbf524ec2..6cbf524ec2 100644
--- a/tests/auto/declarative/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/autoStateAtStartupRestoreBug.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml b/tests/auto/qtquick2/qdeclarativestates/data/avoidFastForward.qml
index 519befc31e..519befc31e 100644
--- a/tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/avoidFastForward.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicBinding.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding.qml
index 59b67d0863..59b67d0863 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicBinding.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicBinding2.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding2.qml
index 55f88120aa..55f88120aa 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicBinding2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicBinding3.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding3.qml
index 361ab0b091..361ab0b091 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicBinding3.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding3.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicBinding4.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding4.qml
index b29f0fcf22..b29f0fcf22 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicBinding4.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicBinding4.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicChanges.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges.qml
index 3e2b73acde..3e2b73acde 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicChanges.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicChanges2.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges2.qml
index 5ff46cc60c..5ff46cc60c 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicChanges2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicChanges3.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges3.qml
index e46e98f75e..e46e98f75e 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicChanges3.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges3.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges4.qml
index 7da1e0fb2e..7da1e0fb2e 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicChanges4.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicExtension.qml b/tests/auto/qtquick2/qdeclarativestates/data/basicExtension.qml
index 00f5fee287..00f5fee287 100644
--- a/tests/auto/declarative/qdeclarativestates/data/basicExtension.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/basicExtension.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/deleting.qml b/tests/auto/qtquick2/qdeclarativestates/data/deleting.qml
index b8e8d33c17..b8e8d33c17 100644
--- a/tests/auto/declarative/qdeclarativestates/data/deleting.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/deleting.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/deletingState.qml b/tests/auto/qtquick2/qdeclarativestates/data/deletingState.qml
index 68a9c2a24d..68a9c2a24d 100644
--- a/tests/auto/declarative/qdeclarativestates/data/deletingState.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/deletingState.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/editProperties.qml b/tests/auto/qtquick2/qdeclarativestates/data/editProperties.qml
index 9bff3657ba..9bff3657ba 100644
--- a/tests/auto/declarative/qdeclarativestates/data/editProperties.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/editProperties.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/explicit.qml b/tests/auto/qtquick2/qdeclarativestates/data/explicit.qml
index d09893a1db..d09893a1db 100644
--- a/tests/auto/declarative/qdeclarativestates/data/explicit.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/explicit.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/extendsBug.qml b/tests/auto/qtquick2/qdeclarativestates/data/extendsBug.qml
index 573341520d..573341520d 100644
--- a/tests/auto/declarative/qdeclarativestates/data/extendsBug.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/extendsBug.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/fakeExtension.qml b/tests/auto/qtquick2/qdeclarativestates/data/fakeExtension.qml
index 6a5c7003f6..6a5c7003f6 100644
--- a/tests/auto/declarative/qdeclarativestates/data/fakeExtension.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/fakeExtension.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/illegalObj.qml b/tests/auto/qtquick2/qdeclarativestates/data/illegalObj.qml
index a2bbd5d32b..a2bbd5d32b 100644
--- a/tests/auto/declarative/qdeclarativestates/data/illegalObj.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/illegalObj.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/illegalTempState.qml b/tests/auto/qtquick2/qdeclarativestates/data/illegalTempState.qml
index 9cb39c0728..9cb39c0728 100644
--- a/tests/auto/declarative/qdeclarativestates/data/illegalTempState.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/illegalTempState.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/image.png b/tests/auto/qtquick2/qdeclarativestates/data/image.png
index ed1833c95b..ed1833c95b 100644
--- a/tests/auto/declarative/qdeclarativestates/data/image.png
+++ b/tests/auto/qtquick2/qdeclarativestates/data/image.png
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativestates/data/legalTempState.qml b/tests/auto/qtquick2/qdeclarativestates/data/legalTempState.qml
index a93860f5cc..a93860f5cc 100644
--- a/tests/auto/declarative/qdeclarativestates/data/legalTempState.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/legalTempState.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/nonExistantProp.qml b/tests/auto/qtquick2/qdeclarativestates/data/nonExistantProp.qml
index ce502699bb..ce502699bb 100644
--- a/tests/auto/declarative/qdeclarativestates/data/nonExistantProp.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/nonExistantProp.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange1.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange1.qml
index 663ad1a264..663ad1a264 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange1.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange1.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange2.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange2.qml
index ae290e961e..ae290e961e 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange3.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange3.qml
index 46665cb4c8..46665cb4c8 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange3.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange3.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange4.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange4.qml
index 22de72f8c9..22de72f8c9 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange4.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange4.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange5.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange5.qml
index c353d2637f..c353d2637f 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange5.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange5.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/parentChange6.qml b/tests/auto/qtquick2/qdeclarativestates/data/parentChange6.qml
index b373dbba20..b373dbba20 100644
--- a/tests/auto/declarative/qdeclarativestates/data/parentChange6.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/parentChange6.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/propertyErrors.qml b/tests/auto/qtquick2/qdeclarativestates/data/propertyErrors.qml
index ddd636493d..ddd636493d 100644
--- a/tests/auto/declarative/qdeclarativestates/data/propertyErrors.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/propertyErrors.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/reset.qml b/tests/auto/qtquick2/qdeclarativestates/data/reset.qml
index f0ecab0950..f0ecab0950 100644
--- a/tests/auto/declarative/qdeclarativestates/data/reset.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/reset.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/restoreEntryValues.qml b/tests/auto/qtquick2/qdeclarativestates/data/restoreEntryValues.qml
index 950a522841..950a522841 100644
--- a/tests/auto/declarative/qdeclarativestates/data/restoreEntryValues.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/restoreEntryValues.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/returnToBase.qml b/tests/auto/qtquick2/qdeclarativestates/data/returnToBase.qml
index 9a0ee82397..9a0ee82397 100644
--- a/tests/auto/declarative/qdeclarativestates/data/returnToBase.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/returnToBase.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/revertListBug.qml b/tests/auto/qtquick2/qdeclarativestates/data/revertListBug.qml
index fbc4bc5ecc..fbc4bc5ecc 100644
--- a/tests/auto/declarative/qdeclarativestates/data/revertListBug.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/revertListBug.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/script.qml b/tests/auto/qtquick2/qdeclarativestates/data/script.qml
index 218f0fae74..218f0fae74 100644
--- a/tests/auto/declarative/qdeclarativestates/data/script.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/script.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/signalOverride.qml b/tests/auto/qtquick2/qdeclarativestates/data/signalOverride.qml
index 9ab8037e51..9ab8037e51 100644
--- a/tests/auto/declarative/qdeclarativestates/data/signalOverride.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/signalOverride.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/signalOverride2.qml b/tests/auto/qtquick2/qdeclarativestates/data/signalOverride2.qml
index 4e5e335b8b..4e5e335b8b 100644
--- a/tests/auto/declarative/qdeclarativestates/data/signalOverride2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/signalOverride2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash.qml b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash.qml
index 3e2ae1e93d..3e2ae1e93d 100644
--- a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash2.qml b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash2.qml
index 3937874aa2..3937874aa2 100644
--- a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash2.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash2.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash3.qml b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash3.qml
index 98d4c57219..98d4c57219 100644
--- a/tests/auto/declarative/qdeclarativestates/data/signalOverrideCrash3.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/signalOverrideCrash3.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml b/tests/auto/qtquick2/qdeclarativestates/data/unnamedWhen.qml
index 35eacff07b..35eacff07b 100644
--- a/tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/unnamedWhen.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/urlResolution.qml b/tests/auto/qtquick2/qdeclarativestates/data/urlResolution.qml
index 516ac034d6..516ac034d6 100644
--- a/tests/auto/declarative/qdeclarativestates/data/urlResolution.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/urlResolution.qml
diff --git a/tests/auto/declarative/qdeclarativestates/data/whenOrdering.qml b/tests/auto/qtquick2/qdeclarativestates/data/whenOrdering.qml
index 92025a2054..92025a2054 100644
--- a/tests/auto/declarative/qdeclarativestates/data/whenOrdering.qml
+++ b/tests/auto/qtquick2/qdeclarativestates/data/whenOrdering.qml
diff --git a/tests/auto/qtquick2/qdeclarativestates/qdeclarativestates.pro b/tests/auto/qtquick2/qdeclarativestates/qdeclarativestates.pro
new file mode 100644
index 0000000000..f799f7066b
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativestates/qdeclarativestates.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativestates
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativestates.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/qtquick2/qdeclarativestates/tst_qdeclarativestates.cpp
new file mode 100644
index 0000000000..663d78d402
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativestates/tst_qdeclarativestates.cpp
@@ -0,0 +1,1596 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquickstateoperations_p.h>
+#include <private/qquickanchors_p_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qquickimage_p.h>
+#include <QtQuick/private/qdeclarativepropertychanges_p.h>
+#include <QtQuick/private/qdeclarativestategroup_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qdeclarativeproperty_p.h>
+#include "../../shared/util.h"
+
+class MyAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ foo WRITE setFoo)
+public:
+ MyAttached(QObject *parent) : QObject(parent), m_foo(13) {}
+
+ int foo() const { return m_foo; }
+ void setFoo(int f) { m_foo = f; }
+
+private:
+ int m_foo;
+};
+
+class MyRect : public QQuickRectangle
+{
+ Q_OBJECT
+ Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
+public:
+ MyRect() {}
+
+ void doSomething() { emit didSomething(); }
+
+ int propertyWithNotify() const { return m_prop; }
+ void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
+
+ static MyAttached *qmlAttachedProperties(QObject *o) {
+ return new MyAttached(o);
+ }
+Q_SIGNALS:
+ void didSomething();
+ void oddlyNamedNotifySignal();
+
+private:
+ int m_prop;
+};
+
+QML_DECLARE_TYPE(MyRect)
+QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
+
+class tst_qdeclarativestates : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativestates() {}
+
+private:
+ static QByteArray fullDataPath(const QString &path);
+
+private slots:
+ void initTestCase();
+
+ void basicChanges();
+ void attachedPropertyChanges();
+ void basicExtension();
+ void basicBinding();
+ void signalOverride();
+ void signalOverrideCrash();
+ void signalOverrideCrash2();
+ void signalOverrideCrash3();
+ void parentChange();
+ void parentChangeErrors();
+ void anchorChanges();
+ void anchorChanges2();
+ void anchorChanges3();
+ void anchorChanges4();
+ void anchorChanges5();
+ void anchorChangesRTL();
+ void anchorChangesRTL2();
+ void anchorChangesRTL3();
+ void anchorChangesCrash();
+ void anchorRewindBug();
+ void anchorRewindBug2();
+ void script();
+ void restoreEntryValues();
+ void explicitChanges();
+ void propertyErrors();
+ void incorrectRestoreBug();
+ void autoStateAtStartupRestoreBug();
+ void deletingChange();
+ void deletingState();
+ void tempState();
+ void illegalTempState();
+ void nonExistantProperty();
+ void reset();
+ void illegalObjectCreation();
+ void whenOrdering();
+ void urlResolution();
+ void unnamedWhen();
+ void returnToBase();
+ void extendsBug();
+ void editProperties();
+ void QTBUG_14830();
+ void avoidFastForward();
+ void revertListBug();
+};
+
+void tst_qdeclarativestates::initTestCase()
+{
+ qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
+}
+
+QByteArray tst_qdeclarativestates::fullDataPath(const QString &path)
+{
+ return QUrl::fromLocalFile(TESTDATA(path)).toString().toUtf8();
+}
+
+void tst_qdeclarativestates::basicChanges()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("bordered");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),2.0);
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1.0);
+ //### we should be checking that this is an implicit rather than explicit 1 (which currently fails)
+
+ rectPrivate->setState("bordered");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),2.0);
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ }
+
+ {
+ // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
+ // signal using 'onPropertyWithNotifyChanged' even though the signal name is
+ // actually 'oddlyNamedNotifySignal'
+
+ QDeclarativeComponent component(&engine, TESTDATA("basicChanges4.qml"));
+ QVERIFY(component.isReady());
+
+ MyRect *rect = qobject_cast<MyRect*>(component.create());
+ QVERIFY(rect != 0);
+
+ QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
+ QVERIFY(prop.hasNotifySignal());
+ QString notifySignal = QByteArray(prop.notifySignal().signature());
+ QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
+
+ QCOMPARE(rect->color(), QColor(Qt::red));
+
+ rect->setPropertyWithNotify(100);
+ QCOMPARE(rect->color(), QColor(Qt::blue));
+ }
+}
+
+void tst_qdeclarativestates::attachedPropertyChanges()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent component(&engine, TESTDATA("attachedPropertyChanges.qml"));
+ QVERIFY(component.isReady());
+
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item != 0);
+ QCOMPARE(item->width(), 50.0);
+
+ // Ensure attached property has been changed
+ QObject *attObj = qmlAttachedPropertiesObject<MyRect>(item, false);
+ QVERIFY(attObj);
+
+ MyAttached *att = qobject_cast<MyAttached*>(attObj);
+ QVERIFY(att);
+
+ QCOMPARE(att->foo(), 1);
+}
+
+void tst_qdeclarativestates::basicExtension()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicExtension.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("bordered");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),2.0);
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1.0);
+
+ rectPrivate->setState("bordered");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->border()->width(),2.0);
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->border()->width(),1.0);
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("fakeExtension.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+}
+
+void tst_qdeclarativestates::basicBinding()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("green"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("red"));
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor2", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor2", QColor("green"));
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicBinding4.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("yellow"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+ rect->setProperty("sourceColor", QColor("purple"));
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("purple"));
+
+ rectPrivate->setState("green");
+ QCOMPARE(rect->color(),QColor("green"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ }
+}
+
+void tst_qdeclarativestates::signalOverride()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverride.qml"));
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ QQuickItemPrivate::get(rect)->setState("green");
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("green"));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverride2.qml"));
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("white"));
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("extendedRect"));
+ QQuickItemPrivate::get(innerRect)->setState("green");
+ rect->doSomething();
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(innerRect->color(),QColor("green"));
+ QCOMPARE(innerRect->property("extendedColor").value<QColor>(),QColor("green"));
+ }
+}
+
+void tst_qdeclarativestates::signalOverrideCrash()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash.qml"));
+ MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate::get(rect)->setState("overridden");
+ rect->doSomething();
+}
+
+void tst_qdeclarativestates::signalOverrideCrash2()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QQuickItemPrivate::get(rect)->setState("state2");
+ QQuickItemPrivate::get(rect)->setState("state1");
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::signalOverrideCrash3()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("signalOverrideCrash3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+ QQuickItemPrivate::get(rect)->setState("");
+ QQuickItemPrivate::get(rect)->setState("state2");
+ QQuickItemPrivate::get(rect)->setState("");
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::parentChange()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange1.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickParentChange *pChange = qobject_cast<QQuickParentChange*>(state->operationAt(0));
+ QVERIFY(pChange != 0);
+ QQuickItem *nParent = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("NewParent"));
+ QVERIFY(nParent != 0);
+
+ QCOMPARE(pChange->parent(), nParent);
+
+ QQuickItemPrivate::get(rect)->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(-133));
+ QCOMPARE(innerRect->y(), qreal(-300));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rectPrivate->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(15));
+ QCOMPARE(innerRect->scale(), qreal(.5));
+ QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-19.9075));
+ QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-8.73433));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rectPrivate->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(-37));
+ QCOMPARE(innerRect->scale(), qreal(.25));
+ QCOMPARE(QString("%1").arg(innerRect->x()), QString("%1").arg(-217.305));
+ QCOMPARE(QString("%1").arg(innerRect->y()), QString("%1").arg(-164.413));
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ //do a non-qFuzzyCompare fuzzy compare
+ QVERIFY(innerRect->y() < qreal(0.00001) && innerRect->y() > qreal(-0.00001));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange6.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QQuickItemPrivate::get(rect)->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(180));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(-105));
+ QCOMPARE(innerRect->y(), qreal(-105));
+ }
+}
+
+void tst_qdeclarativestates::parentChangeErrors()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange4.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
+ QQuickItemPrivate::get(rect)->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ QCOMPARE(innerRect->y(), qreal(5));
+ }
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("parentChange5.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
+ QQuickItemPrivate::get(rect)->setState("reparented");
+ QCOMPARE(innerRect->rotation(), qreal(0));
+ QCOMPARE(innerRect->scale(), qreal(1));
+ QCOMPARE(innerRect->x(), qreal(5));
+ QCOMPARE(innerRect->y(), qreal(5));
+ }
+}
+
+void tst_qdeclarativestates::anchorChanges()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges1.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ rectPrivate->setState("right");
+ QCOMPARE(innerRect->x(), qreal(150));
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), qreal(5));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChanges2()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ rectPrivate->setState("right");
+ QCOMPARE(innerRect->x(), qreal(150));
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), qreal(5));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChanges3()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ rectPrivate->setState("reanchored");
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
+
+ QCOMPARE(innerRect->x(), qreal(10));
+ QCOMPARE(innerRect->y(), qreal(0));
+ QCOMPARE(innerRect->width(), qreal(190));
+ QCOMPARE(innerRect->height(), qreal(150));
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), qreal(0));
+ QCOMPARE(innerRect->y(), qreal(10));
+ QCOMPARE(innerRect->width(), qreal(150));
+ QCOMPARE(innerRect->height(), qreal(190));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChanges4()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges4.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ QQuickItemPrivate::get(rect)->setState("reanchored");
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().item, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->horizontalCenter().anchorLine, QQuickItemPrivate::get(bottomGuideline)->horizontalCenter().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().item, QQuickItemPrivate::get(leftGuideline)->verticalCenter().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->verticalCenter().anchorLine, QQuickItemPrivate::get(leftGuideline)->verticalCenter().anchorLine);
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChanges5()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges5.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+
+ QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ QQuickItemPrivate::get(rect)->setState("reanchored");
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ //QCOMPARE(aChanges->anchors()->horizontalCenter().item, bottomGuideline->horizontalCenter().item);
+ //QCOMPARE(aChanges->anchors()->horizontalCenter().anchorLine, bottomGuideline->horizontalCenter().anchorLine);
+ //QCOMPARE(aChanges->anchors()->baseline().item, leftGuideline->baseline().item);
+ //QCOMPARE(aChanges->anchors()->baseline().anchorLine, leftGuideline->baseline().anchorLine);
+
+ delete rect;
+}
+
+void mirrorAnchors(QQuickItem *item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->setLayoutMirror(true);
+}
+
+qreal offsetRTL(QQuickItem *anchorItem, QQuickItem *item) {
+ return anchorItem->width()+2*anchorItem->x()-item->width();
+}
+
+void tst_qdeclarativestates::anchorChangesRTL()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges1.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+ mirrorAnchors(innerRect);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ rectPrivate->setState("right");
+ QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) -qreal(5));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChangesRTL2()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+ mirrorAnchors(innerRect);
+
+ rectPrivate->setState("right");
+ QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(5));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::anchorChangesRTL3()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChanges3.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
+ QVERIFY(innerRect != 0);
+ mirrorAnchors(innerRect);
+
+ QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
+ QVERIFY(leftGuideline != 0);
+
+ QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
+ QVERIFY(bottomGuideline != 0);
+
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
+ QVERIFY(aChanges != 0);
+
+ rectPrivate->setState("reanchored");
+ QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().item, QQuickItemPrivate::get(leftGuideline)->left().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickItemPrivate::get(leftGuideline)->left().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().item, rectPrivate->top().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->top().anchorLine, rectPrivate->top().anchorLine);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().item, QQuickItemPrivate::get(bottomGuideline)->bottom().item);
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->bottom().anchorLine, QQuickItemPrivate::get(bottomGuideline)->bottom().anchorLine);
+
+ QCOMPARE(innerRect->x(), offsetRTL(leftGuideline, innerRect) - qreal(10));
+ QCOMPARE(innerRect->y(), qreal(0));
+ // between left side of parent and leftGuideline.x: 10, which has width 0
+ QCOMPARE(innerRect->width(), qreal(10));
+ QCOMPARE(innerRect->height(), qreal(150));
+
+ rectPrivate->setState("");
+ QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(0));
+ QCOMPARE(innerRect->y(), qreal(10));
+ // between right side of parent and left side of rightGuideline.x: 150, which has width 0
+ QCOMPARE(innerRect->width(), qreal(50));
+ QCOMPARE(innerRect->height(), qreal(190));
+
+ delete rect;
+}
+
+//QTBUG-9609
+void tst_qdeclarativestates::anchorChangesCrash()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorChangesCrash.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate::get(rect)->setState("reanchored");
+
+ delete rect;
+}
+
+// QTBUG-12273
+void tst_qdeclarativestates::anchorRewindBug()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("anchorRewindBug.qml")));
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
+ QVERIFY(rect != 0);
+
+ QQuickItem * column = rect->findChild<QQuickItem*>("column");
+
+ QVERIFY(column != 0);
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QCOMPARE(column->height(), 200.0);
+ QQuickItemPrivate::get(rect)->setState("reanchored");
+
+ // column height and width should stay implicit
+ // and column's implicit resizing should still work
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QTRY_COMPARE(column->height(), 100.0);
+
+ QQuickItemPrivate::get(rect)->setState("");
+
+ // column height and width should stay implicit
+ // and column's implicit resizing should still work
+ QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
+ QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
+ QTRY_COMPARE(column->height(), 200.0);
+
+ delete view;
+}
+
+// QTBUG-11834
+void tst_qdeclarativestates::anchorRewindBug2()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("anchorRewindBug2.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
+
+ QVERIFY(mover != 0);
+ QCOMPARE(mover->y(), qreal(0.0));
+ QCOMPARE(mover->width(), qreal(50.0));
+
+ QQuickItemPrivate::get(rect)->setState("anchored");
+ QCOMPARE(mover->y(), qreal(250.0));
+ QCOMPARE(mover->width(), qreal(200.0));
+
+ QQuickItemPrivate::get(rect)->setState("");
+ QCOMPARE(mover->y(), qreal(0.0));
+ QCOMPARE(mover->width(), qreal(50.0));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::script()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("script.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("blue")); // a script isn't reverted
+ }
+}
+
+void tst_qdeclarativestates::restoreEntryValues()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("restoreEntryValues.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("blue"));
+}
+
+void tst_qdeclarativestates::explicitChanges()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("explicit.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QDeclarativeListReference list(rect, "states");
+ QDeclarativeState *state = qobject_cast<QDeclarativeState*>(list.at(0));
+ QVERIFY(state != 0);
+
+ qmlExecuteDeferred(state);
+ QDeclarativePropertyChanges *changes = qobject_cast<QDeclarativePropertyChanges*>(rect->findChild<QDeclarativePropertyChanges*>("changes"));
+ QVERIFY(changes != 0);
+ QVERIFY(changes->isExplicit());
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rect->setProperty("sourceColor", QColor("green"));
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ rect->setProperty("sourceColor", QColor("yellow"));
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("yellow"));
+}
+
+void tst_qdeclarativestates::propertyErrors()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("propertyErrors.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QCOMPARE(rect->color(),QColor("red"));
+
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("propertyErrors.qml") + ":8:9: QML PropertyChanges: Cannot assign to read-only property \"activeFocus\"");
+ QQuickItemPrivate::get(rect)->setState("blue");
+}
+
+void tst_qdeclarativestates::incorrectRestoreBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("basicChanges.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QCOMPARE(rect->color(),QColor("red"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ // make sure if we change the base state value, we then restore to it correctly
+ rect->setColor(QColor("green"));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("green"));
+}
+
+void tst_qdeclarativestates::autoStateAtStartupRestoreBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent component(&engine, TESTDATA("autoStateAtStartupRestoreBug.qml"));
+ QObject *obj = component.create();
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 3);
+
+ obj->setProperty("input", 2);
+
+ QCOMPARE(obj->property("test").toInt(), 9);
+
+ delete obj;
+}
+
+void tst_qdeclarativestates::deletingChange()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("deleting.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+ QCOMPARE(rect->radius(),qreal(5));
+
+ rectPrivate->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->radius(),qreal(0));
+
+ QDeclarativePropertyChanges *pc = rect->findChild<QDeclarativePropertyChanges*>("pc1");
+ QVERIFY(pc != 0);
+ delete pc;
+
+ QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
+ QVERIFY(state != 0);
+ qmlExecuteDeferred(state);
+ QCOMPARE(state->operationCount(), 1);
+
+ rectPrivate->setState("blue");
+ QCOMPARE(rect->color(),QColor("red"));
+ QCOMPARE(rect->radius(),qreal(5));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::deletingState()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("deletingState.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+
+ QDeclarativeStateGroup *sg = rect->findChild<QDeclarativeStateGroup*>();
+ QVERIFY(sg != 0);
+ QVERIFY(sg->findState("blue") != 0);
+
+ sg->setState("blue");
+ QCOMPARE(rect->color(),QColor("blue"));
+
+ sg->setState("");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ QDeclarativeState *state = rect->findChild<QDeclarativeState*>();
+ QVERIFY(state != 0);
+ delete state;
+
+ QVERIFY(sg->findState("blue") == 0);
+
+ //### should we warn that state doesn't exist
+ sg->setState("blue");
+ QCOMPARE(rect->color(),QColor("red"));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::tempState()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("legalTempState.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QTest::ignoreMessage(QtDebugMsg, "entering placed");
+ QTest::ignoreMessage(QtDebugMsg, "entering idle");
+ rectPrivate->setState("placed");
+ QCOMPARE(rectPrivate->state(), QLatin1String("idle"));
+}
+
+void tst_qdeclarativestates::illegalTempState()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("illegalTempState.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
+ rectPrivate->setState("placed");
+ QCOMPARE(rectPrivate->state(), QLatin1String("placed"));
+}
+
+void tst_qdeclarativestates::nonExistantProperty()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent rectComponent(&engine, TESTDATA("nonExistantProp.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
+ rectPrivate->setState("blue");
+ QCOMPARE(rectPrivate->state(), QLatin1String("blue"));
+}
+
+void tst_qdeclarativestates::reset()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("reset.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickImage *image = rect->findChild<QQuickImage*>();
+ QVERIFY(image != 0);
+ QCOMPARE(image->width(), qreal(40.));
+ QCOMPARE(image->height(), qreal(20.));
+
+ QQuickItemPrivate::get(rect)->setState("state1");
+
+ QCOMPARE(image->width(), 20.0);
+ QCOMPARE(image->height(), qreal(20.));
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::illegalObjectCreation()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent component(&engine, TESTDATA("illegalObj.qml"));
+ QList<QDeclarativeError> errors = component.errors();
+ QVERIFY(errors.count() == 1);
+ const QDeclarativeError &error = errors.at(0);
+ QCOMPARE(error.line(), 9);
+ QCOMPARE(error.column(), 23);
+ QCOMPARE(error.description().toUtf8().constData(), "PropertyChanges does not support creating state-specific objects.");
+}
+
+void tst_qdeclarativestates::whenOrdering()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("whenOrdering.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+ rect->setProperty("condition2", true);
+ QCOMPARE(rectPrivate->state(), QLatin1String("state2"));
+ rect->setProperty("condition1", true);
+ QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
+ rect->setProperty("condition2", false);
+ QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
+ rect->setProperty("condition2", true);
+ QCOMPARE(rectPrivate->state(), QLatin1String("state1"));
+ rect->setProperty("condition1", false);
+ rect->setProperty("condition2", false);
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+}
+
+void tst_qdeclarativestates::urlResolution()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("urlResolution.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
+ QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
+ QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
+ QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
+ QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
+
+ QQuickItemPrivate::get(myType)->setState("SetImageState");
+ QUrl resolved = QUrl::fromLocalFile(TESTDATA("Implementation/images/qt-logo.png"));
+ QCOMPARE(image1->source(), resolved);
+ QCOMPARE(image2->source(), resolved);
+ QCOMPARE(image3->source(), resolved);
+
+ delete rect;
+}
+
+void tst_qdeclarativestates::unnamedWhen()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("unnamedWhen.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
+ rect->setProperty("triggerState", true);
+ QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
+ rect->setProperty("triggerState", false);
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
+}
+
+void tst_qdeclarativestates::returnToBase()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("returnToBase.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String(""));
+ rect->setProperty("triggerState", true);
+ QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1"));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState"));
+ rect->setProperty("triggerState", false);
+ QCOMPARE(rectPrivate->state(), QLatin1String(""));
+ QCOMPARE(rect->property("stateString").toString(), QLatin1String("originalState"));
+}
+
+//QTBUG-12559
+void tst_qdeclarativestates::extendsBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("extendsBug.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
+
+ rectPrivate->setState("b");
+ QCOMPARE(greenRect->x(), qreal(100));
+ QCOMPARE(greenRect->y(), qreal(100));
+}
+
+void tst_qdeclarativestates::editProperties()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("editProperties.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QDeclarativeStateGroup *stateGroup = rectPrivate->_states();
+ QVERIFY(stateGroup != 0);
+ qmlExecuteDeferred(stateGroup);
+
+ QDeclarativeState *blueState = stateGroup->findState("blue");
+ QVERIFY(blueState != 0);
+ qmlExecuteDeferred(blueState);
+
+ QDeclarativePropertyChanges *propertyChangesBlue = qobject_cast<QDeclarativePropertyChanges*>(blueState->operationAt(0));
+ QVERIFY(propertyChangesBlue != 0);
+
+ QDeclarativeState *greenState = stateGroup->findState("green");
+ QVERIFY(greenState != 0);
+ qmlExecuteDeferred(greenState);
+
+ QDeclarativePropertyChanges *propertyChangesGreen = qobject_cast<QDeclarativePropertyChanges*>(greenState->operationAt(0));
+ QVERIFY(propertyChangesGreen != 0);
+
+ QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
+ QVERIFY(childRect != 0);
+ QCOMPARE(childRect->width(), qreal(402));
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ QCOMPARE(childRect->height(), qreal(200));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(childRect->width(), qreal(50));
+ QCOMPARE(childRect->height(), qreal(40));
+ QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ QVERIFY(blueState->bindingInRevertList(childRect, "width"));
+
+
+ rectPrivate->setState("green");
+ QCOMPARE(childRect->width(), qreal(200));
+ QCOMPARE(childRect->height(), qreal(100));
+ QVERIFY(greenState->bindingInRevertList(childRect, "width"));
+
+
+ rectPrivate->setState("");
+
+
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QVERIFY(propertyChangesBlue->containsValue("width"));
+ QVERIFY(!propertyChangesBlue->containsProperty("x"));
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
+ QVERIFY(!propertyChangesBlue->value("x").isValid());
+
+ propertyChangesBlue->changeValue("width", 60);
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+
+
+ propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
+ QVERIFY(!propertyChangesBlue->containsValue("width"));
+ QVERIFY(propertyChangesBlue->containsExpression("width"));
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+
+ propertyChangesBlue->changeValue("width", 50);
+ QVERIFY(propertyChangesBlue->containsValue("width"));
+ QVERIFY(!propertyChangesBlue->containsExpression("width"));
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 50);
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ rectPrivate->setState("blue");
+ QCOMPARE(childRect->width(), qreal(50));
+ QCOMPARE(childRect->height(), qreal(40));
+
+ propertyChangesBlue->changeValue("width", 60);
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 60);
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QCOMPARE(childRect->width(), qreal(60));
+ QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+
+ propertyChangesBlue->changeExpression("width", "myRectangle.width / 2");
+ QVERIFY(!propertyChangesBlue->containsValue("width"));
+ QVERIFY(propertyChangesBlue->containsExpression("width"));
+ QCOMPARE(propertyChangesBlue->value("width").toInt(), 0);
+ QCOMPARE(propertyChangesBlue->actions().length(), 2);
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ QCOMPARE(childRect->width(), qreal(200));
+
+ propertyChangesBlue->changeValue("width", 50);
+ QCOMPARE(childRect->width(), qreal(50));
+
+ rectPrivate->setState("");
+ QCOMPARE(childRect->width(), qreal(402));
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+
+ QCOMPARE(propertyChangesGreen->actions().length(), 2);
+ rectPrivate->setState("green");
+ QCOMPARE(childRect->width(), qreal(200));
+ QCOMPARE(childRect->height(), qreal(100));
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ QVERIFY(greenState->bindingInRevertList(childRect, "width"));
+ QCOMPARE(propertyChangesGreen->actions().length(), 2);
+
+
+ propertyChangesGreen->removeProperty("height");
+ QVERIFY(!QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "height")));
+ QCOMPARE(childRect->height(), qreal(200));
+
+ QVERIFY(greenState->bindingInRevertList(childRect, "width"));
+ QVERIFY(greenState->containsPropertyInRevertList(childRect, "width"));
+ propertyChangesGreen->removeProperty("width");
+ QVERIFY(QDeclarativePropertyPrivate::binding(QDeclarativeProperty(childRect, "width")));
+ QCOMPARE(childRect->width(), qreal(402));
+ QVERIFY(!greenState->bindingInRevertList(childRect, "width"));
+ QVERIFY(!greenState->containsPropertyInRevertList(childRect, "width"));
+
+ propertyChangesBlue->removeProperty("width");
+ QCOMPARE(childRect->width(), qreal(402));
+
+ rectPrivate->setState("blue");
+ QCOMPARE(childRect->width(), qreal(402));
+ QCOMPARE(childRect->height(), qreal(40));
+}
+
+void tst_qdeclarativestates::QTBUG_14830()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("QTBUG-14830.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+ QQuickItem *item = rect->findChild<QQuickItem*>("area");
+
+ QCOMPARE(item->width(), qreal(171));
+}
+
+void tst_qdeclarativestates::avoidFastForward()
+{
+ QDeclarativeEngine engine;
+
+ //shouldn't fast forward if there isn't a transition
+ QDeclarativeComponent c(&engine, TESTDATA("avoidFastForward.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ rectPrivate->setState("a");
+ QCOMPARE(rect->property("updateCount").toInt(), 1);
+}
+
+//QTBUG-22583
+void tst_qdeclarativestates::revertListBug()
+{
+ QDeclarativeEngine engine;
+
+ QDeclarativeComponent c(&engine, TESTDATA("revertListBug.qml"));
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
+ QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
+ QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
+ QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
+ QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
+
+ QCOMPARE(rect1->parentItem(), origParent1);
+ QCOMPARE(rect2->parentItem(), origParent2);
+
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ rectPrivate->setState("reparented");
+
+ QCOMPARE(rect1->parentItem(), newParent);
+ QCOMPARE(rect2->parentItem(), origParent2);
+
+ rectPrivate->setState("");
+
+ QCOMPARE(rect1->parentItem(), origParent1);
+ QCOMPARE(rect2->parentItem(), origParent2);
+
+ QMetaObject::invokeMethod(rect, "switchTargetItem");
+
+ rectPrivate->setState("reparented");
+
+ QCOMPARE(rect1->parentItem(), origParent1);
+ QCOMPARE(rect2->parentItem(), newParent);
+
+ rectPrivate->setState("");
+
+ QCOMPARE(rect1->parentItem(), origParent1);
+ QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
+}
+
+QTEST_MAIN(tst_qdeclarativestates)
+
+#include "tst_qdeclarativestates.moc"
diff --git a/tests/auto/qtquick2/qdeclarativestyledtext/qdeclarativestyledtext.pro b/tests/auto/qtquick2/qdeclarativestyledtext/qdeclarativestyledtext.pro
new file mode 100644
index 0000000000..84532f611e
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativestyledtext/qdeclarativestyledtext.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativestyledtext
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativestyledtext.cpp
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/declarative/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp b/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
index b09c33302e..b09c33302e 100644
--- a/tests/auto/declarative/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
+++ b/tests/auto/qtquick2/qdeclarativestyledtext/tst_qdeclarativestyledtext.cpp
diff --git a/tests/auto/qtquick2/qdeclarativesystempalette/qdeclarativesystempalette.pro b/tests/auto/qtquick2/qdeclarativesystempalette/qdeclarativesystempalette.pro
new file mode 100644
index 0000000000..87c2af2190
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativesystempalette/qdeclarativesystempalette.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativesystempalette
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativesystempalette.cpp
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private widgets testlib
diff --git a/tests/auto/qtquick2/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp b/tests/auto/qtquick2/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp
new file mode 100644
index 0000000000..4cb09f90f5
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativesystempalette/tst_qdeclarativesystempalette.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QDebug>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/private/qdeclarativesystempalette_p.h>
+#include <qpalette.h>
+
+class tst_qdeclarativesystempalette : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativesystempalette();
+
+private slots:
+ void activePalette();
+ void inactivePalette();
+ void disabledPalette();
+ void paletteChanged();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qdeclarativesystempalette::tst_qdeclarativesystempalette()
+{
+}
+
+void tst_qdeclarativesystempalette::activePalette()
+{
+ QString componentStr = "import QtQuick 2.0\nSystemPalette { }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Active);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qdeclarativesystempalette::inactivePalette()
+{
+ QString componentStr = "import QtQuick 2.0\nSystemPalette { colorGroup: SystemPalette.Inactive }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+ QVERIFY(object->colorGroup() == QDeclarativeSystemPalette::Inactive);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Inactive);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qdeclarativesystempalette::disabledPalette()
+{
+ QString componentStr = "import QtQuick 2.0\nSystemPalette { colorGroup: SystemPalette.Disabled }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+ QVERIFY(object->colorGroup() == QDeclarativeSystemPalette::Disabled);
+
+ QPalette palette;
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ QCOMPARE(palette.window().color(), object->window());
+ QCOMPARE(palette.windowText().color(), object->windowText());
+ QCOMPARE(palette.base().color(), object->base());
+ QCOMPARE(palette.text().color(), object->text());
+ QCOMPARE(palette.alternateBase().color(), object->alternateBase());
+ QCOMPARE(palette.button().color(), object->button());
+ QCOMPARE(palette.buttonText().color(), object->buttonText());
+ QCOMPARE(palette.light().color(), object->light());
+ QCOMPARE(palette.midlight().color(), object->midlight());
+ QCOMPARE(palette.dark().color(), object->dark());
+ QCOMPARE(palette.mid().color(), object->mid());
+ QCOMPARE(palette.shadow().color(), object->shadow());
+ QCOMPARE(palette.highlight().color(), object->highlight());
+ QCOMPARE(palette.highlightedText().color(), object->highlightedText());
+
+ delete object;
+}
+
+void tst_qdeclarativesystempalette::paletteChanged()
+{
+ QString componentStr = "import QtQuick 2.0\nSystemPalette { }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QDeclarativeSystemPalette *object = qobject_cast<QDeclarativeSystemPalette*>(component.create());
+
+ QVERIFY(object != 0);
+
+ QPalette p;
+ p.setCurrentColorGroup(QPalette::Active);
+ p.setColor(QPalette::Active, QPalette::Text, QColor("red"));
+ p.setColor(QPalette::Active, QPalette::ButtonText, QColor("green"));
+ p.setColor(QPalette::Active, QPalette::WindowText, QColor("blue"));
+
+ qApp->setPalette(p);
+
+ object->setColorGroup(QDeclarativeSystemPalette::Active);
+ QTRY_COMPARE(QColor("red"), object->text());
+ QTRY_COMPARE(QColor("green"), object->buttonText());
+ QTRY_COMPARE(QColor("blue"), object->windowText());
+
+ delete object;
+}
+
+QTEST_MAIN(tst_qdeclarativesystempalette)
+
+#include "tst_qdeclarativesystempalette.moc"
diff --git a/tests/auto/qtquick2/qdeclarativetimer/qdeclarativetimer.pro b/tests/auto/qtquick2/qdeclarativetimer/qdeclarativetimer.pro
new file mode 100644
index 0000000000..d990dc449f
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativetimer/qdeclarativetimer.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativetimer
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativetimer.cpp
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private gui testlib
diff --git a/tests/auto/qtquick2/qdeclarativetimer/tst_qdeclarativetimer.cpp b/tests/auto/qtquick2/qdeclarativetimer/tst_qdeclarativetimer.cpp
new file mode 100644
index 0000000000..ac32585365
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativetimer/tst_qdeclarativetimer.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QSignalSpy>
+#include <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/private/qdeclarativetimer_p.h>
+#include <QtQuick/qquickitem.h>
+#include <QDebug>
+
+class tst_qdeclarativetimer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativetimer();
+
+private slots:
+ void notRepeating();
+ void notRepeatingStart();
+ void repeat();
+ void noTriggerIfNotRunning();
+ void triggeredOnStart();
+ void triggeredOnStartRepeat();
+ void changeDuration();
+ void restart();
+ void parentProperty();
+};
+
+class TimerHelper : public QObject
+{
+ Q_OBJECT
+public:
+ TimerHelper() : QObject(), count(0)
+ {
+ }
+
+ int count;
+
+public slots:
+ void timeout() {
+ ++count;
+ }
+};
+
+#define TIMEOUT_TIMEOUT 200
+
+tst_qdeclarativetimer::tst_qdeclarativetimer()
+{
+}
+
+void tst_qdeclarativetimer::notRepeating()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(timer->isRunning());
+ QVERIFY(!timer->isRepeating());
+ QCOMPARE(timer->interval(), 100);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QVERIFY(timer->isRunning() == false);
+}
+
+void tst_qdeclarativetimer::notRepeatingStart()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(!timer->isRunning());
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 0);
+
+ timer->start();
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 1);
+ QVERIFY(timer->isRunning() == false);
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::repeat()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > 0);
+ int oldCount = helper.count;
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > oldCount);
+ QVERIFY(timer->isRunning());
+
+ oldCount = helper.count;
+ timer->stop();
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count == oldCount);
+ QVERIFY(timer->isRunning() == false);
+
+ QSignalSpy spy(timer, SIGNAL(repeatChanged()));
+
+ timer->setRepeating(false);
+ QVERIFY(!timer->isRepeating());
+ QCOMPARE(spy.count(),1);
+
+ timer->setRepeating(false);
+ QCOMPARE(spy.count(),1);
+
+ timer->setRepeating(true);
+ QCOMPARE(spy.count(),2);
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::triggeredOnStart()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+ QVERIFY(timer->triggeredOnStart());
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QTest::qWait(1);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 2);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(helper.count, 2);
+ QVERIFY(timer->isRunning() == false);
+
+ QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged()));
+
+ timer->setTriggeredOnStart(false);
+ QVERIFY(!timer->triggeredOnStart());
+ QCOMPARE(spy.count(),1);
+
+ timer->setTriggeredOnStart(false);
+ QCOMPARE(spy.count(),1);
+
+ timer->setTriggeredOnStart(true);
+ QCOMPARE(spy.count(),2);
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::triggeredOnStartRepeat()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QTest::qWait(1);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > 1);
+ int oldCount = helper.count;
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QVERIFY(helper.count > oldCount);
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::noTriggerIfNotRunning()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray(
+ "import QtQuick 2.0\n"
+ "Item { property bool ok: true\n"
+ "Timer { id: t1; interval: 100; repeat: true; running: true; onTriggered: if (!running) ok=false }"
+ "Timer { interval: 10; running: true; onTriggered: t1.running=false }"
+ "}"
+ ), QUrl::fromLocalFile(""));
+ QObject *item = component.create();
+ QVERIFY(item != 0);
+ QTest::qWait(TIMEOUT_TIMEOUT);
+ QCOMPARE(item->property("ok").toBool(), true);
+
+ delete item;
+}
+
+void tst_qdeclarativetimer::changeDuration()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(500);
+ QCOMPARE(helper.count, 2);
+
+ timer->setInterval(500);
+
+ QTest::qWait(600);
+ QCOMPARE(helper.count, 3);
+ QVERIFY(timer->isRunning());
+
+ QSignalSpy spy(timer, SIGNAL(intervalChanged()));
+
+ timer->setInterval(200);
+ QCOMPARE(timer->interval(), 200);
+ QCOMPARE(spy.count(),1);
+
+ timer->setInterval(200);
+ QCOMPARE(spy.count(),1);
+
+ timer->setInterval(300);
+ QCOMPARE(spy.count(),2);
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::restart()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile(""));
+ QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(component.create());
+ QVERIFY(timer != 0);
+
+ TimerHelper helper;
+ connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ QCOMPARE(helper.count, 0);
+
+ QTest::qWait(600);
+ QCOMPARE(helper.count, 1);
+
+ QTest::qWait(300);
+
+ timer->restart();
+
+ QTest::qWait(700);
+
+ QCOMPARE(helper.count, 2);
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+void tst_qdeclarativetimer::parentProperty()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item != 0);
+ QDeclarativeTimer *timer = item->findChild<QDeclarativeTimer*>("timer");
+ QVERIFY(timer != 0);
+
+ QVERIFY(timer->isRunning());
+
+ delete timer;
+}
+
+QTEST_MAIN(tst_qdeclarativetimer)
+
+#include "tst_qdeclarativetimer.moc"
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/empty.xml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/empty.xml
index e69de29bb2..e69de29bb2 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/empty.xml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/empty.xml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/get.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/get.qml
index 509da7174b..509da7174b 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/get.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/get.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.qml
index 2df3927479..2df3927479 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.xml
index 40cd6d0432..40cd6d0432 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model.xml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.xml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model2.xml
index dab2ec6dc0..dab2ec6dc0 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.xml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/model2.xml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/propertychanges.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/propertychanges.qml
index f8a97bffc3..f8a97bffc3 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/propertychanges.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/propertychanges.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.qml
index dc609e95e3..dc609e95e3 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.xml
index d71de60710..d71de60710 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/recipes.xml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleCrash.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleCrash.qml
index 6a7059bb45..6a7059bb45 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleCrash.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleCrash.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleErrors.qml
index 91664b6d4a..91664b6d4a 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleErrors.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleKeys.qml
index 9f667d86e5..9f667d86e5 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/roleKeys.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/testtypes.qml
index 5ec1ffa35f..5ec1ffa35f 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/testtypes.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/unique.qml
index 322a2e4e5c..322a2e4e5c 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/data/unique.qml
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro b/tests/auto/qtquick2/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro
index 10944bcb41..10944bcb41 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro
diff --git a/tests/auto/qtquick2/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/qtquick2/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
new file mode 100644
index 0000000000..316ac50c5e
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
@@ -0,0 +1,961 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtGlobal>
+#include <math.h>
+#include <QMetaObject>
+#include <qtest.h>
+#include <QtTest/qsignalspy.h>
+#include <QtDeclarative/qdeclarativenetworkaccessmanagerfactory.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qnetworkrequest.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qtemporaryfile.h>
+#include "../../shared/util.h"
+#include <private/qdeclarativeengine_p.h>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qlistmodelinterface_p.h>
+#include "../../../../src/imports/xmllistmodel/qdeclarativexmllistmodel_p.h"
+
+typedef QPair<int, int> QDeclarativeXmlListRange;
+typedef QList<QVariantList> QDeclarativeXmlModelData;
+
+Q_DECLARE_METATYPE(QList<QDeclarativeXmlListRange>)
+Q_DECLARE_METATYPE(QDeclarativeXmlModelData)
+Q_DECLARE_METATYPE(QDeclarativeXmlListModel::Status)
+
+class tst_qdeclarativexmllistmodel : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativexmllistmodel() {}
+
+private slots:
+ void initTestCase() {
+ qRegisterMetaType<QDeclarativeXmlListModel::Status>();
+ }
+
+ void buildModel();
+ void testTypes();
+ void testTypes_data();
+ void cdata();
+ void attributes();
+ void roles();
+ void roleErrors();
+ void uniqueRoleNames();
+ void headers();
+ void xml();
+ void xml_data();
+ void source();
+ void source_data();
+ void data();
+ void get();
+ void reload();
+ void useKeys();
+ void useKeys_data();
+ void noKeysValueChanges();
+ void keysChanged();
+ void threading();
+ void threading_data();
+ void propertyChanges();
+
+ void roleCrash();
+
+private:
+ QString errorString(QListModelInterface* model) {
+ QString ret;
+ QMetaObject::invokeMethod(model, "errorString", Q_RETURN_ARG(QString, ret));
+ return ret;
+ }
+
+ QString makeItemXmlAndData(const QString &data, QDeclarativeXmlModelData *modelData = 0) const
+ {
+ if (modelData)
+ modelData->clear();
+ QString xml;
+
+ if (!data.isEmpty()) {
+ QStringList items = data.split(";");
+ foreach(const QString &item, items) {
+ if (item.isEmpty())
+ continue;
+ QVariantList variants;
+ xml += QLatin1String("<item>");
+ QStringList fields = item.split(",");
+ foreach(const QString &field, fields) {
+ QStringList values = field.split("=");
+ if (values.count() != 2) {
+ qWarning() << "makeItemXmlAndData: invalid field:" << field;
+ continue;
+ }
+ xml += QString("<%1>%2</%1>").arg(values[0], values[1]);
+ if (!modelData)
+ continue;
+ bool isNum = false;
+ int number = values[1].toInt(&isNum);
+ if (isNum)
+ variants << number;
+ else
+ variants << values[1];
+ }
+ xml += QLatin1String("</item>");
+ if (modelData)
+ modelData->append(variants);
+ }
+ }
+
+ QString decl = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>";
+ return decl + QLatin1String("<data>") + xml + QLatin1String("</data>");
+ }
+
+ QDeclarativeEngine engine;
+};
+
+class CustomNetworkAccessManagerFactory : public QObject, public QDeclarativeNetworkAccessManagerFactory
+{
+ Q_OBJECT
+public:
+ QVariantMap lastSentHeaders;
+
+protected:
+ QNetworkAccessManager *create(QObject *parent);
+};
+
+class CustomNetworkAccessManager : public QNetworkAccessManager
+{
+ Q_OBJECT
+public:
+ CustomNetworkAccessManager(CustomNetworkAccessManagerFactory *factory, QObject *parent)
+ : QNetworkAccessManager(parent), m_factory(factory) {}
+
+protected:
+ QNetworkReply *createRequest(Operation op, const QNetworkRequest &req, QIODevice * outgoingData = 0)
+ {
+ if (m_factory) {
+ QVariantMap map;
+ foreach (const QString &header, req.rawHeaderList())
+ map[header] = req.rawHeader(header.toUtf8());
+ m_factory->lastSentHeaders = map;
+ }
+ return QNetworkAccessManager::createRequest(op, req, outgoingData);
+ }
+
+ QPointer<CustomNetworkAccessManagerFactory> m_factory;
+};
+
+QNetworkAccessManager *CustomNetworkAccessManagerFactory::create(QObject *parent)
+{
+ return new CustomNetworkAccessManager(this, parent);
+}
+
+
+void tst_qdeclarativexmllistmodel::buildModel()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+ QCOMPARE(model->data(3, Qt::UserRole).toString(), QLatin1String("Spot"));
+ QCOMPARE(model->data(3, Qt::UserRole+1).toString(), QLatin1String("Dog"));
+ QCOMPARE(model->data(3, Qt::UserRole+2).toInt(), 9);
+ QCOMPARE(model->data(3, Qt::UserRole+3).toString(), QLatin1String("Medium"));
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::testTypes()
+{
+ QFETCH(QString, xml);
+ QFETCH(QString, roleName);
+ QFETCH(QVariant, expectedValue);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("testtypes.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ model->setProperty("xml",xml.toUtf8());
+ QMetaObject::invokeMethod(model, "reload");
+ QTRY_COMPARE(model->count(), 1);
+
+ int role = -1;
+ foreach (int i, model->roles()) {
+ if (model->toString(i) == roleName) {
+ role = i;
+ break;
+ }
+ }
+ QVERIFY(role >= 0);
+
+ if (expectedValue.toString() == "nan")
+ QVERIFY(qIsNaN(model->data(0, role).toDouble()));
+ else
+ QCOMPARE(model->data(0, role), expectedValue);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::testTypes_data()
+{
+ QTest::addColumn<QString>("xml");
+ QTest::addColumn<QString>("roleName");
+ QTest::addColumn<QVariant>("expectedValue");
+
+ QTest::newRow("missing string field") << "<data></data>"
+ << "stringValue" << QVariant("");
+ QTest::newRow("empty string") << "<data><a-string></a-string></data>"
+ << "stringValue" << QVariant("");
+ QTest::newRow("1-char string") << "<data><a-string>5</a-string></data>"
+ << "stringValue" << QVariant("5");
+ QTest::newRow("string ok") << "<data><a-string>abc def g</a-string></data>"
+ << "stringValue" << QVariant("abc def g");
+
+ QTest::newRow("missing number field") << "<data></data>"
+ << "numberValue" << QVariant("");
+ double nan = qQNaN();
+ QTest::newRow("empty number field") << "<data><a-number></a-number></data>"
+ << "numberValue" << QVariant(nan);
+ QTest::newRow("number field with string") << "<data><a-number>a string</a-number></data>"
+ << "numberValue" << QVariant(nan);
+ QTest::newRow("-1") << "<data><a-number>-1</a-number></data>"
+ << "numberValue" << QVariant("-1");
+ QTest::newRow("-1.5") << "<data><a-number>-1.5</a-number></data>"
+ << "numberValue" << QVariant("-1.5");
+ QTest::newRow("0") << "<data><a-number>0</a-number></data>"
+ << "numberValue" << QVariant("0");
+ QTest::newRow("+1") << "<data><a-number>1</a-number></data>"
+ << "numberValue" << QVariant("1");
+ QTest::newRow("+1.5") << "<data><a-number>1.5</a-number></data>"
+ << "numberValue" << QVariant("1.5");
+}
+
+void tst_qdeclarativexmllistmodel::cdata()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("recipes.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 5);
+
+ QVERIFY(model->data(2, Qt::UserRole+2).toString().startsWith(QLatin1String("<html>")));
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::attributes()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("recipes.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 5);
+ QCOMPARE(model->data(2, Qt::UserRole).toString(), QLatin1String("Vegetable Soup"));
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::roles()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+ QList<int> roles = model->roles();
+ QCOMPARE(roles.count(), 4);
+ QCOMPARE(model->toString(roles.at(0)), QLatin1String("name"));
+ QCOMPARE(model->toString(roles.at(1)), QLatin1String("type"));
+ QCOMPARE(model->toString(roles.at(2)), QLatin1String("age"));
+ QCOMPARE(model->toString(roles.at(3)), QLatin1String("size"));
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::roleErrors()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleErrors.qml")));
+ QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("roleErrors.qml")).toString() + ":7:5: QML XmlRole: An XmlRole query must not start with '/'").toUtf8().constData());
+ QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("roleErrors.qml")).toString() + ":10:5: QML XmlRole: invalid query: \"age/\"").toUtf8().constData());
+
+ //### make sure we receive all expected warning messages.
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+
+ //### should any of these return valid values?
+ QCOMPARE(model->data(3, Qt::UserRole), QVariant());
+ QCOMPARE(model->data(3, Qt::UserRole+1), QVariant());
+ QCOMPARE(model->data(3, Qt::UserRole+2), QVariant());
+
+ QEXPECT_FAIL("", "QTBUG-10797", Continue);
+ QCOMPARE(model->data(3, Qt::UserRole+3), QVariant());
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::uniqueRoleNames()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("unique.qml")));
+ QTest::ignoreMessage(QtWarningMsg, (QUrl::fromLocalFile(TESTDATA("unique.qml")).toString() + ":8:5: QML XmlRole: \"name\" duplicates a previous role name and will be disabled.").toUtf8().constData());
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+ QList<int> roles = model->roles();
+ QCOMPARE(roles.count(), 1);
+
+ delete model;
+}
+
+
+void tst_qdeclarativexmllistmodel::xml()
+{
+ QFETCH(QString, xml);
+ QFETCH(int, count);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+
+ QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)));
+ QVERIFY(errorString(model).isEmpty());
+ QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Loading);
+ QTRY_COMPARE(spy.count(), 1); spy.clear();
+ QTest::qWait(50);
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Ready);
+ QVERIFY(errorString(model).isEmpty());
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
+ QCOMPARE(model->count(), 9);
+
+ // if xml is empty (i.e. clearing) it won't have any effect if a source is set
+ if (xml.isEmpty())
+ model->setProperty("source",QUrl());
+ model->setProperty("xml",xml);
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0)); // immediately goes to 1.0 if using setXml()
+ QTRY_COMPARE(spy.count(), 1); spy.clear();
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Loading);
+ QTRY_COMPARE(spy.count(), 1); spy.clear();
+ if (xml.isEmpty())
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Null);
+ else
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Ready);
+ QVERIFY(errorString(model).isEmpty());
+ QCOMPARE(model->count(), count);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::xml_data()
+{
+ QTest::addColumn<QString>("xml");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("xml with no items") << "<Pets></Pets>" << 0;
+ QTest::newRow("empty xml") << "" << 0;
+ QTest::newRow("one item") << "<Pets><Pet><name>Hobbes</name><type>Tiger</type><age>7</age><size>Large</size></Pet></Pets>" << 1;
+}
+
+void tst_qdeclarativexmllistmodel::headers()
+{
+ // ensure the QNetworkAccessManagers created for this test are immediately deleted
+ QDeclarativeEngine qmlEng;
+
+ CustomNetworkAccessManagerFactory factory;
+ qmlEng.setNetworkAccessManagerFactory(&factory);
+
+ QDeclarativeComponent component(&qmlEng, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Ready);
+
+ QVariantMap expectedHeaders;
+ expectedHeaders["Accept"] = "application/xml,*/*";
+
+ QCOMPARE(factory.lastSentHeaders.count(), expectedHeaders.count());
+ foreach (const QString &header, expectedHeaders.keys()) {
+ QVERIFY(factory.lastSentHeaders.contains(header));
+ QCOMPARE(factory.lastSentHeaders[header].toString(), expectedHeaders[header].toString());
+ }
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::source()
+{
+ QFETCH(QUrl, source);
+ QFETCH(int, count);
+ QFETCH(QDeclarativeXmlListModel::Status, status);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)));
+
+ QVERIFY(errorString(model).isEmpty());
+ QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Loading);
+ QTRY_COMPARE(spy.count(), 1); spy.clear();
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Ready);
+ QVERIFY(errorString(model).isEmpty());
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
+ QCOMPARE(model->count(), 9);
+
+ model->setProperty("source",source);
+ if (model->property("source").toString().isEmpty())
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Null);
+ QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
+ QTRY_COMPARE(spy.count(), 1); spy.clear();
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")),
+ QDeclarativeXmlListModel::Loading);
+ QVERIFY(errorString(model).isEmpty());
+
+ QEventLoop loop;
+ QTimer timer;
+ timer.setSingleShot(true);
+ connect(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status)), &loop, SLOT(quit()));
+ connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+ timer.start(20000);
+ loop.exec();
+
+ if (spy.count() == 0 && status != QDeclarativeXmlListModel::Ready) {
+ qWarning("QDeclarativeXmlListModel invalid source test timed out");
+ } else {
+ QCOMPARE(spy.count(), 1); spy.clear();
+ }
+
+ QCOMPARE(qvariant_cast<QDeclarativeXmlListModel::Status>(model->property("status")), status);
+ QCOMPARE(model->count(), count);
+
+ if (status == QDeclarativeXmlListModel::Ready)
+ QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
+
+ QCOMPARE(errorString(model).isEmpty(), status == QDeclarativeXmlListModel::Ready);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::source_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QDeclarativeXmlListModel::Status>("status");
+
+ QTest::newRow("valid") << QUrl::fromLocalFile(TESTDATA("model2.xml")) << 2
+ << QDeclarativeXmlListModel::Ready;
+ QTest::newRow("invalid") << QUrl("http://blah.blah/blah.xml") << 0
+ << QDeclarativeXmlListModel::Error;
+
+ // empty file
+ QTemporaryFile *temp = new QTemporaryFile(this);
+ if (temp->open())
+ QTest::newRow("empty file") << QUrl::fromLocalFile(temp->fileName()) << 0
+ << QDeclarativeXmlListModel::Ready;
+ temp->close();
+}
+
+void tst_qdeclarativexmllistmodel::data()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+
+ for (int i=0; i<9; i++) {
+ for (int j=0; j<model->roles().count(); j++) {
+ QCOMPARE(model->data(i, j), QVariant());
+ }
+ }
+ QTRY_COMPARE(model->count(), 9);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::get()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("get.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+
+ QVERIFY(model != 0);
+
+ QVERIFY(QMetaObject::invokeMethod(model, "runPreTest"));
+ QCOMPARE(model->property("preTest").toBool(), true);
+
+ QTRY_COMPARE(model->count(), 9);
+
+ QVERIFY(QMetaObject::invokeMethod(model, "runPostTest"));
+ QCOMPARE(model->property("postTest").toBool(), true);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::reload()
+{
+ // If no keys are used, the model should be rebuilt from scratch when
+ // reload() is called.
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("model.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+ //reload multiple times to test the xml query aborting
+ QMetaObject::invokeMethod(model, "reload");
+ QMetaObject::invokeMethod(model, "reload");
+ QCoreApplication::processEvents();
+ QMetaObject::invokeMethod(model, "reload");
+ QMetaObject::invokeMethod(model, "reload");
+ QTRY_COMPARE(spyCount.count(), 1);
+ QTRY_COMPARE(spyInsert.count(), 1);
+ QTRY_COMPARE(spyRemove.count(), 1);
+
+ QCOMPARE(spyInsert[0][0].toInt(), 0);
+ QCOMPARE(spyInsert[0][1].toInt(), 9);
+
+ QCOMPARE(spyRemove[0][0].toInt(), 0);
+ QCOMPARE(spyRemove[0][1].toInt(), 9);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::useKeys()
+{
+ // If using incremental updates through keys, the model should only
+ // insert & remove some of the items, instead of throwing everything
+ // away and causing the view to repaint the whole view.
+
+ QFETCH(QString, oldXml);
+ QFETCH(int, oldCount);
+ QFETCH(QString, newXml);
+ QFETCH(QDeclarativeXmlModelData, newData);
+ QFETCH(QList<QDeclarativeXmlListRange>, insertRanges);
+ QFETCH(QList<QDeclarativeXmlListRange>, removeRanges);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+
+ model->setProperty("xml",oldXml);
+ QTRY_COMPARE(model->count(), oldCount);
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ model->setProperty("xml",newXml);
+
+ if (oldCount != newData.count()) {
+ QTRY_COMPARE(model->count(), newData.count());
+ QCOMPARE(spyCount.count(), 1);
+ } else {
+ QTRY_VERIFY(spyInsert.count() > 0 || spyRemove.count() > 0);
+ QCOMPARE(spyCount.count(), 0);
+ }
+
+ QList<int> roles = model->roles();
+ for (int i=0; i<model->count(); i++) {
+ for (int j=0; j<roles.count(); j++)
+ QCOMPARE(model->data(i, roles[j]), newData[i][j]);
+ }
+
+ QCOMPARE(spyInsert.count(), insertRanges.count());
+ for (int i=0; i<spyInsert.count(); i++) {
+ QCOMPARE(spyInsert[i][0].toInt(), insertRanges[i].first);
+ QCOMPARE(spyInsert[i][1].toInt(), insertRanges[i].second);
+ }
+
+ QCOMPARE(spyRemove.count(), removeRanges.count());
+ for (int i=0; i<spyRemove.count(); i++) {
+ QCOMPARE(spyRemove[i][0].toInt(), removeRanges[i].first);
+ QCOMPARE(spyRemove[i][1].toInt(), removeRanges[i].second);
+ }
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::useKeys_data()
+{
+ QTest::addColumn<QString>("oldXml");
+ QTest::addColumn<int>("oldCount");
+ QTest::addColumn<QString>("newXml");
+ QTest::addColumn<QDeclarativeXmlModelData>("newData");
+ QTest::addColumn<QList<QDeclarativeXmlListRange> >("insertRanges");
+ QTest::addColumn<QList<QDeclarativeXmlListRange> >("removeRanges");
+
+ QDeclarativeXmlModelData modelData;
+
+ QTest::newRow("append 1")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("append multiple")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("insert in different spots")
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("insert in middle")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=D,age=55,sport=Golf") << 2
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("remove first")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
+
+ QTest::newRow("remove last")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
+ << makeItemXmlAndData("name=A,age=25,sport=Football", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1));
+
+ QTest::newRow("remove from multiple spots")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 5
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=C,age=45,sport=Curling", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1) << qMakePair(3,2));
+
+ QTest::newRow("remove all")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
+ << makeItemXmlAndData("", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 3));
+
+ QTest::newRow("replace item")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=ZZZ,age=25,sport=Football", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
+
+ QTest::newRow("add and remove simultaneously, in different spots")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf") << 4
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics;name=E,age=65,sport=Fencing", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2));
+
+ QTest::newRow("insert at start, remove at end i.e. rss feed")
+ << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 3
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2));
+
+ QTest::newRow("remove at start, insert at end")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
+ << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2));
+
+ QTest::newRow("all data has changed")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35") << 2
+ << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 2));
+}
+
+void tst_qdeclarativexmllistmodel::noKeysValueChanges()
+{
+ // The 'key' roles are 'name' and 'age', as defined in roleKeys.qml.
+ // If a 'sport' value is changed, the model should not be reloaded,
+ // since 'sport' is not marked as a key.
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+
+ QString xml;
+
+ xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
+ model->setProperty("xml",xml);
+ QTRY_COMPARE(model->count(), 2);
+
+ model->setProperty("xml","");
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ xml = makeItemXmlAndData("name=A,age=25,sport=AussieRules;name=B,age=35,sport=Athletics");
+ model->setProperty("xml",xml);
+
+ // wait for the new xml data to be set, and verify no signals were emitted
+ QTRY_VERIFY(model->data(0, model->roles()[2]).toString() != QLatin1String("Football"));
+ QCOMPARE(model->data(0, model->roles()[2]).toString(), QLatin1String("AussieRules"));
+
+ QVERIFY(spyInsert.count() == 0);
+ QVERIFY(spyRemove.count() == 0);
+ QVERIFY(spyCount.count() == 0);
+
+ QCOMPARE(model->count(), 2);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::keysChanged()
+{
+ // If the key roles change, the next time the data is reloaded, it should
+ // delete all its data and build a clean model (i.e. same behaviour as
+ // if no keys are set).
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+
+ QString xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
+ model->setProperty("xml",xml);
+ QTRY_COMPARE(model->count(), 2);
+
+ model->setProperty("xml","");
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ QVERIFY(QMetaObject::invokeMethod(model, "disableNameKey"));
+ model->setProperty("xml",xml);
+
+ QTRY_VERIFY(spyInsert.count() > 0 && spyRemove.count() > 0);
+
+ QCOMPARE(spyInsert.count(), 1);
+ QCOMPARE(spyInsert[0][0].toInt(), 0);
+ QCOMPARE(spyInsert[0][1].toInt(), 2);
+
+ QCOMPARE(spyRemove.count(), 1);
+ QCOMPARE(spyRemove[0][0].toInt(), 0);
+ QCOMPARE(spyRemove[0][1].toInt(), 2);
+
+ QCOMPARE(spyCount.count(), 0);
+
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::threading()
+{
+ QFETCH(int, xmlDataCount);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleKeys.qml")));
+
+ QListModelInterface *m1 = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(m1 != 0);
+ QListModelInterface *m2 = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(m2 != 0);
+ QListModelInterface *m3 = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(m3 != 0);
+
+ for (int dataCount=0; dataCount<xmlDataCount; dataCount++) {
+
+ QString data1, data2, data3;
+ for (int i=0; i<dataCount; i++) {
+ data1 += "name=A" + QString::number(i) + ",age=1" + QString::number(i) + ",sport=Football;";
+ data2 += "name=B" + QString::number(i) + ",age=2" + QString::number(i) + ",sport=Athletics;";
+ data3 += "name=C" + QString::number(i) + ",age=3" + QString::number(i) + ",sport=Curling;";
+ }
+
+ //Set the xml data multiple times with randomized order and mixed with multiple event loops
+ //to test the xml query reloading/aborting, the result should be stable.
+ m1->setProperty("xml",makeItemXmlAndData(data1));
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ m3->setProperty("xml",makeItemXmlAndData(data3));
+ QCoreApplication::processEvents();
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ m1->setProperty("xml",makeItemXmlAndData(data1));
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ QCoreApplication::processEvents();
+ m3->setProperty("xml",makeItemXmlAndData(data3));
+ QCoreApplication::processEvents();
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ m1->setProperty("xml",makeItemXmlAndData(data1));
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ m3->setProperty("xml",makeItemXmlAndData(data3));
+ QCoreApplication::processEvents();
+ m2->setProperty("xml",makeItemXmlAndData(data2));
+ m3->setProperty("xml",makeItemXmlAndData(data3));
+ m3->setProperty("xml",makeItemXmlAndData(data3));
+ QCoreApplication::processEvents();
+
+ QTRY_VERIFY(m1->count() == dataCount && m2->count() == dataCount && m3->count() == dataCount);
+
+ for (int i=0; i<dataCount; i++) {
+ QCOMPARE(m1->data(i, m1->roles()[0]).toString(), QString("A" + QString::number(i)));
+ QCOMPARE(m1->data(i, m1->roles()[1]).toString(), QString("1" + QString::number(i)));
+ QCOMPARE(m1->data(i, m1->roles()[2]).toString(), QString("Football"));
+
+ QCOMPARE(m2->data(i, m2->roles()[0]).toString(), QString("B" + QString::number(i)));
+ QCOMPARE(m2->data(i, m2->roles()[1]).toString(), QString("2" + QString::number(i)));
+ QCOMPARE(m2->data(i, m2->roles()[2]).toString(), QString("Athletics"));
+
+ QCOMPARE(m3->data(i, m3->roles()[0]).toString(), QString("C" + QString::number(i)));
+ QCOMPARE(m3->data(i, m3->roles()[1]).toString(), QString("3" + QString::number(i)));
+ QCOMPARE(m3->data(i, m3->roles()[2]).toString(), QString("Curling"));
+ }
+ }
+
+ delete m1;
+ delete m2;
+ delete m3;
+}
+
+void tst_qdeclarativexmllistmodel::threading_data()
+{
+ QTest::addColumn<int>("xmlDataCount");
+
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("10") << 10;
+}
+
+void tst_qdeclarativexmllistmodel::propertyChanges()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ QTRY_COMPARE(model->count(), 9);
+
+ QObject *role = model->findChild<QObject*>("role");
+ QVERIFY(role);
+
+ QSignalSpy nameSpy(role, SIGNAL(nameChanged()));
+ QSignalSpy querySpy(role, SIGNAL(queryChanged()));
+ QSignalSpy isKeySpy(role, SIGNAL(isKeyChanged()));
+
+ role->setProperty("name","size");
+ role->setProperty("query","size/string()");
+ role->setProperty("isKey",true);
+
+ QCOMPARE(role->property("name").toString(), QString("size"));
+ QCOMPARE(role->property("query").toString(), QString("size/string()"));
+ QVERIFY(role->property("isKey").toBool());
+
+ QCOMPARE(nameSpy.count(),1);
+ QCOMPARE(querySpy.count(),1);
+ QCOMPARE(isKeySpy.count(),1);
+
+ role->setProperty("name","size");
+ role->setProperty("query","size/string()");
+ role->setProperty("isKey",true);
+
+ QCOMPARE(nameSpy.count(),1);
+ QCOMPARE(querySpy.count(),1);
+ QCOMPARE(isKeySpy.count(),1);
+
+ QSignalSpy sourceSpy(model, SIGNAL(sourceChanged()));
+ QSignalSpy xmlSpy(model, SIGNAL(xmlChanged()));
+ QSignalSpy modelQuerySpy(model, SIGNAL(queryChanged()));
+ QSignalSpy namespaceDeclarationsSpy(model, SIGNAL(namespaceDeclarationsChanged()));
+
+ model->setProperty("source",QUrl(""));
+ model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
+ model->setProperty("query","/Pets");
+ model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
+
+ QCOMPARE(model->property("source").toUrl(), QUrl(""));
+ QCOMPARE(model->property("xml").toString(), QString("<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>"));
+ QCOMPARE(model->property("query").toString(), QString("/Pets"));
+ QCOMPARE(model->property("namespaceDeclarations").toString(), QString("declare namespace media=\"http://search.yahoo.com/mrss/\";"));
+
+ QTRY_VERIFY(model->count() == 1);
+
+ QCOMPARE(sourceSpy.count(),1);
+ QCOMPARE(xmlSpy.count(),1);
+ QCOMPARE(modelQuerySpy.count(),1);
+ QCOMPARE(namespaceDeclarationsSpy.count(),1);
+
+ model->setProperty("source",QUrl(""));
+ model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
+ model->setProperty("query","/Pets");
+ model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
+
+ QCOMPARE(sourceSpy.count(),1);
+ QCOMPARE(xmlSpy.count(),1);
+ QCOMPARE(modelQuerySpy.count(),1);
+ QCOMPARE(namespaceDeclarationsSpy.count(),1);
+
+ QTRY_VERIFY(model->count() == 1);
+ delete model;
+}
+
+void tst_qdeclarativexmllistmodel::roleCrash()
+{
+ // don't crash
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("roleCrash.qml")));
+ QListModelInterface *model = qobject_cast<QListModelInterface*>(component.create());
+ QVERIFY(model != 0);
+ delete model;
+}
+
+QTEST_MAIN(tst_qdeclarativexmllistmodel)
+
+#include "tst_qdeclarativexmllistmodel.moc"
diff --git a/tests/auto/declarative/qquickanchors/data/anchors.qml b/tests/auto/qtquick2/qquickanchors/data/anchors.qml
index 4be49a3468..4be49a3468 100644
--- a/tests/auto/declarative/qquickanchors/data/anchors.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/anchors.qml
diff --git a/tests/auto/declarative/qquickanchors/data/centerin.qml b/tests/auto/qtquick2/qquickanchors/data/centerin.qml
index e5f64f1e47..e5f64f1e47 100644
--- a/tests/auto/declarative/qquickanchors/data/centerin.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/centerin.qml
diff --git a/tests/auto/declarative/qquickanchors/data/centerinRotation.qml b/tests/auto/qtquick2/qquickanchors/data/centerinRotation.qml
index 933a25c100..933a25c100 100644
--- a/tests/auto/declarative/qquickanchors/data/centerinRotation.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/centerinRotation.qml
diff --git a/tests/auto/declarative/qquickanchors/data/crash1.qml b/tests/auto/qtquick2/qquickanchors/data/crash1.qml
index 98dd6cfa41..98dd6cfa41 100644
--- a/tests/auto/declarative/qquickanchors/data/crash1.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/crash1.qml
diff --git a/tests/auto/declarative/qquickanchors/data/fill.qml b/tests/auto/qtquick2/qquickanchors/data/fill.qml
index 08db199d7b..08db199d7b 100644
--- a/tests/auto/declarative/qquickanchors/data/fill.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/fill.qml
diff --git a/tests/auto/declarative/qquickanchors/data/hvCenter.qml b/tests/auto/qtquick2/qquickanchors/data/hvCenter.qml
index 6763f8eb75..6763f8eb75 100644
--- a/tests/auto/declarative/qquickanchors/data/hvCenter.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/hvCenter.qml
diff --git a/tests/auto/declarative/qquickanchors/data/loop1.qml b/tests/auto/qtquick2/qquickanchors/data/loop1.qml
index 342b2af052..342b2af052 100644
--- a/tests/auto/declarative/qquickanchors/data/loop1.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/loop1.qml
diff --git a/tests/auto/declarative/qquickanchors/data/loop2.qml b/tests/auto/qtquick2/qquickanchors/data/loop2.qml
index e1875be025..e1875be025 100644
--- a/tests/auto/declarative/qquickanchors/data/loop2.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/loop2.qml
diff --git a/tests/auto/declarative/qquickanchors/data/margins.qml b/tests/auto/qtquick2/qquickanchors/data/margins.qml
index 9403f65a61..9403f65a61 100644
--- a/tests/auto/declarative/qquickanchors/data/margins.qml
+++ b/tests/auto/qtquick2/qquickanchors/data/margins.qml
diff --git a/tests/auto/qtquick2/qquickanchors/qquickanchors.pro b/tests/auto/qtquick2/qquickanchors/qquickanchors.pro
new file mode 100644
index 0000000000..92f24cff07
--- /dev/null
+++ b/tests/auto/qtquick2/qquickanchors/qquickanchors.pro
@@ -0,0 +1,12 @@
+TARGET = tst_qquickanchors
+CONFIG += testcase
+SOURCES += tst_qquickanchors.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private v8-private testlib
diff --git a/tests/auto/qtquick2/qquickanchors/tst_qquickanchors.cpp b/tests/auto/qtquick2/qquickanchors/tst_qquickanchors.cpp
new file mode 100644
index 0000000000..cae1421573
--- /dev/null
+++ b/tests/auto/qtquick2/qquickanchors/tst_qquickanchors.cpp
@@ -0,0 +1,692 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QSignalSpy>
+#include <private/qquickitem_p.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickanchors_p_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include "../../shared/util.h"
+
+Q_DECLARE_METATYPE(QQuickAnchors::Anchor)
+Q_DECLARE_METATYPE(QQuickAnchorLine::AnchorLine)
+
+class tst_qquickanchors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickanchors() {}
+
+private slots:
+ void basicAnchors();
+ void basicAnchorsRTL();
+ void loops();
+ void illegalSets();
+ void illegalSets_data();
+ void reset();
+ void reset_data();
+ void resetConvenience();
+ void nullItem();
+ void nullItem_data();
+ void crash1();
+ void centerIn();
+ void centerInRTL();
+ void centerInRotation();
+ void hvCenter();
+ void hvCenterRTL();
+ void fill();
+ void fillRTL();
+ void margins();
+ void marginsRTL();
+};
+
+/*
+ Find an item with the specified objectName.
+*/
+template<typename T>
+T *findItem(QQuickItem *parent, const QString &objectName)
+{
+ if (!parent)
+ return 0;
+
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QQuickItem::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ return static_cast<T*>(item);
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+void tst_qquickanchors::basicAnchors()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("anchors.qml")));
+
+ qApp->processEvents();
+
+ //sibling horizontal
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
+
+ //parent horizontal
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
+
+ //vertical
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
+
+ //stretch
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->width(), 96.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->width(), 192.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->width(), 192.0);
+
+ //vertical stretch
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->height(), 40.0);
+
+ //more parent horizontal
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
+
+ //centerIn
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
+
+ //margins
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->width(), 86.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->height(), 10.0);
+
+ // offsets
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
+ QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
+
+ //baseline
+ QQuickText *text1 = findItem<QQuickText>(view->rootObject(), QLatin1String("text1"));
+ QQuickText *text2 = findItem<QQuickText>(view->rootObject(), QLatin1String("text2"));
+ QCOMPARE(text1->y(), text2->y());
+
+ delete view;
+}
+
+QQuickItem* childItem(QQuickItem *parentItem, const char * itemString) {
+ return findItem<QQuickItem>(parentItem, QLatin1String(itemString));
+}
+
+qreal offsetMasterRTL(QQuickItem *rootItem, const char * itemString) {
+ QQuickItem* masterItem = findItem<QQuickItem>(rootItem, QLatin1String("masterRect"));
+ return masterItem->width()+2*masterItem->x()-findItem<QQuickItem>(rootItem, QLatin1String(itemString))->width();
+}
+
+qreal offsetParentRTL(QQuickItem *rootItem, const char * itemString) {
+ return rootItem->width()+2*rootItem->x()-findItem<QQuickItem>(rootItem, QLatin1String(itemString))->width();
+}
+
+void mirrorAnchors(QQuickItem *item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->setLayoutMirror(true);
+}
+
+void tst_qquickanchors::basicAnchorsRTL()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("anchors.qml")));
+
+ qApp->processEvents();
+
+ QQuickItem* rootItem = qobject_cast<QQuickItem*>(view->rootObject());
+ foreach (QObject *child, rootItem->children()) {
+ bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
+ QCOMPARE(mirrored, false);
+ }
+
+ foreach (QObject *child, rootItem->children())
+ mirrorAnchors(qobject_cast<QQuickItem*>(child));
+
+ foreach (QObject *child, rootItem->children()) {
+ bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
+ QCOMPARE(mirrored, true);
+ }
+
+ //sibling horizontal
+ QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
+ QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
+ QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0);
+ QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0);
+ QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0);
+ QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0);
+
+ //parent horizontal
+ QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0);
+ QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0);
+ QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0);
+ QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0);
+ QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0);
+ QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0);
+
+ //vertical
+ QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0);
+ QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0);
+
+ //stretch
+ QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0);
+ QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0);
+ QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0);
+ QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0);
+ QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0);
+ QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0);
+
+ //vertical stretch
+ QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0);
+ QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0);
+
+ //more parent horizontal
+ QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0);
+ QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0);
+ QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0);
+
+ //centerIn
+ QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0);
+ QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0);
+
+ //margins
+ QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0);
+ QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0);
+ QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0);
+ QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0);
+
+ // offsets
+ QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0);
+ QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0);
+ QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0);
+
+ //baseline
+ QQuickText *text1 = findItem<QQuickText>(rootItem, QLatin1String("text1"));
+ QQuickText *text2 = findItem<QQuickText>(rootItem, QLatin1String("text2"));
+ QCOMPARE(text1->y(), text2->y());
+
+ delete view;
+}
+
+// mostly testing that we don't crash
+void tst_qquickanchors::loops()
+{
+ {
+ QUrl source(QUrl::fromLocalFile(TESTDATA("loop1.qml")));
+
+ QString expect = source.toString() + ":6:5: QML Text: Possible anchor loop detected on horizontal anchor.";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+
+ QQuickView *view = new QQuickView;
+ view->setSource(source);
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QUrl source(QUrl::fromLocalFile(TESTDATA("loop2.qml")));
+
+ QString expect = source.toString() + ":8:3: QML Image: Possible anchor loop detected on horizontal anchor.";
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+
+ QQuickView *view = new QQuickView;
+ view->setSource(source);
+ qApp->processEvents();
+
+ delete view;
+ }
+}
+
+void tst_qquickanchors::illegalSets()
+{
+ QFETCH(QString, qml);
+ QFETCH(QString, warning);
+
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 1.0\n" + qml.toUtf8()), QUrl::fromLocalFile(""));
+ if (!component.isReady())
+ qWarning() << "Test errors:" << component.errors();
+ QVERIFY(component.isReady());
+ QObject *o = component.create();
+ delete o;
+}
+
+void tst_qquickanchors::illegalSets_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<QString>("warning");
+
+ QTest::newRow("H - too many anchors")
+ << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
+ << "file::2:23: QML Rectangle: Cannot specify left, right, and hcenter anchors.";
+
+ foreach (const QString &side, QStringList() << "left" << "right") {
+ QTest::newRow("H - anchor to V")
+ << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
+ << "file::2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
+
+ QTest::newRow("H - anchor to non parent/sibling")
+ << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
+ << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+
+ QTest::newRow("H - anchor to self")
+ << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
+ << "file::2:1: QML Rectangle: Cannot anchor item to self.";
+ }
+
+
+ QTest::newRow("V - too many anchors")
+ << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
+ << "file::2:23: QML Rectangle: Cannot specify top, bottom, and vcenter anchors.";
+
+ QTest::newRow("V - too many anchors with baseline")
+ << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
+ << "file::2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.";
+
+ foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
+
+ QTest::newRow("V - anchor to H")
+ << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
+ << "file::2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
+
+ QTest::newRow("V - anchor to non parent/sibling")
+ << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
+ << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+
+ QTest::newRow("V - anchor to self")
+ << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
+ << "file::2:1: QML Rectangle: Cannot anchor item to self.";
+ }
+
+
+ QTest::newRow("centerIn - anchor to non parent/sibling")
+ << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
+ << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+
+
+ QTest::newRow("fill - anchor to non parent/sibling")
+ << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
+ << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+}
+
+void tst_qquickanchors::reset()
+{
+ QFETCH(QString, side);
+ QFETCH(QQuickAnchorLine::AnchorLine, anchorLine);
+ QFETCH(QQuickAnchors::Anchor, usedAnchor);
+
+ QQuickItem *baseItem = new QQuickItem;
+
+ QQuickAnchorLine anchor;
+ anchor.item = baseItem;
+ anchor.anchorLine = anchorLine;
+
+ QQuickItem *item = new QQuickItem;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ const QMetaObject *meta = itemPrivate->anchors()->metaObject();
+ QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
+
+ QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
+ QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true);
+
+ QVERIFY(p.reset(itemPrivate->anchors()));
+ QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false);
+
+ delete item;
+ delete baseItem;
+}
+
+void tst_qquickanchors::reset_data()
+{
+ QTest::addColumn<QString>("side");
+ QTest::addColumn<QQuickAnchorLine::AnchorLine>("anchorLine");
+ QTest::addColumn<QQuickAnchors::Anchor>("usedAnchor");
+
+ QTest::newRow("left") << "left" << QQuickAnchorLine::Left << QQuickAnchors::LeftAnchor;
+ QTest::newRow("top") << "top" << QQuickAnchorLine::Top << QQuickAnchors::TopAnchor;
+ QTest::newRow("right") << "right" << QQuickAnchorLine::Right << QQuickAnchors::RightAnchor;
+ QTest::newRow("bottom") << "bottom" << QQuickAnchorLine::Bottom << QQuickAnchors::BottomAnchor;
+
+ QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchorLine::HCenter << QQuickAnchors::HCenterAnchor;
+ QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchorLine::VCenter << QQuickAnchors::VCenterAnchor;
+ QTest::newRow("baseline") << "baseline" << QQuickAnchorLine::Baseline << QQuickAnchors::BaselineAnchor;
+}
+
+void tst_qquickanchors::resetConvenience()
+{
+ QQuickItem *baseItem = new QQuickItem;
+ QQuickItem *item = new QQuickItem;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ //fill
+ itemPrivate->anchors()->setFill(baseItem);
+ QVERIFY(itemPrivate->anchors()->fill() == baseItem);
+ itemPrivate->anchors()->resetFill();
+ QVERIFY(itemPrivate->anchors()->fill() == 0);
+
+ //centerIn
+ itemPrivate->anchors()->setCenterIn(baseItem);
+ QVERIFY(itemPrivate->anchors()->centerIn() == baseItem);
+ itemPrivate->anchors()->resetCenterIn();
+ QVERIFY(itemPrivate->anchors()->centerIn() == 0);
+
+ delete item;
+ delete baseItem;
+}
+
+void tst_qquickanchors::nullItem()
+{
+ QFETCH(QString, side);
+
+ QQuickAnchorLine anchor;
+ QQuickItem *item = new QQuickItem;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+
+ const QMetaObject *meta = itemPrivate->anchors()->metaObject();
+ QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
+
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML Item: Cannot anchor to a null item.");
+ QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
+
+ delete item;
+}
+
+void tst_qquickanchors::nullItem_data()
+{
+ QTest::addColumn<QString>("side");
+
+ QTest::newRow("left") << "left";
+ QTest::newRow("top") << "top";
+ QTest::newRow("right") << "right";
+ QTest::newRow("bottom") << "bottom";
+
+ QTest::newRow("hcenter") << "horizontalCenter";
+ QTest::newRow("vcenter") << "verticalCenter";
+ QTest::newRow("baseline") << "baseline";
+}
+
+//QTBUG-5428
+void tst_qquickanchors::crash1()
+{
+ QUrl source(QUrl::fromLocalFile(TESTDATA("crash1.qml")));
+
+ QString expect = source.toString() + ":3:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
+
+ QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
+
+ QQuickView *view = new QQuickView(source);
+ qApp->processEvents();
+
+ delete view;
+}
+
+void tst_qquickanchors::fill()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("fill.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QCOMPARE(rect->x(), 0.0 + 10.0);
+ QCOMPARE(rect->y(), 0.0 + 30.0);
+ QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
+ //Alter Offsets (tests QTBUG-6631)
+ rectPrivate->anchors()->setLeftMargin(20.0);
+ rectPrivate->anchors()->setRightMargin(0.0);
+ rectPrivate->anchors()->setBottomMargin(0.0);
+ rectPrivate->anchors()->setTopMargin(10.0);
+ QCOMPARE(rect->x(), 0.0 + 20.0);
+ QCOMPARE(rect->y(), 0.0 + 10.0);
+ QCOMPARE(rect->width(), 200.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 10.0);
+
+ delete view;
+}
+
+void tst_qquickanchors::fillRTL()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("fill.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ mirrorAnchors(rect);
+
+ QCOMPARE(rect->x(), 0.0 + 20.0);
+ QCOMPARE(rect->y(), 0.0 + 30.0);
+ QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
+ //Alter Offsets (tests QTBUG-6631)
+ rectPrivate->anchors()->setLeftMargin(20.0);
+ rectPrivate->anchors()->setRightMargin(0.0);
+ rectPrivate->anchors()->setBottomMargin(0.0);
+ rectPrivate->anchors()->setTopMargin(10.0);
+ QCOMPARE(rect->x(), 0.0 + 0.0);
+ QCOMPARE(rect->y(), 0.0 + 10.0);
+ QCOMPARE(rect->width(), 200.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 10.0);
+
+ delete view;
+}
+
+void tst_qquickanchors::centerIn()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerin.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ QCOMPARE(rect->x(), 75.0 + 10);
+ QCOMPARE(rect->y(), 75.0 + 30);
+ //Alter Offsets (tests QTBUG-6631)
+ rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
+ rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
+ QCOMPARE(rect->x(), 75.0 - 20.0);
+ QCOMPARE(rect->y(), 75.0 - 10.0);
+
+ delete view;
+}
+
+void tst_qquickanchors::centerInRTL()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerin.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ mirrorAnchors(rect);
+
+ QCOMPARE(rect->x(), 75.0 - 10);
+ QCOMPARE(rect->y(), 75.0 + 30);
+ //Alter Offsets (tests QTBUG-6631)
+ rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
+ rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
+ QCOMPARE(rect->x(), 75.0 + 20.0);
+ QCOMPARE(rect->y(), 75.0 - 10.0);
+
+ delete view;
+}
+
+//QTBUG-12441
+void tst_qquickanchors::centerInRotation()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("centerinRotation.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* outer = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("outer"));
+ QQuickRectangle* inner = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("inner"));
+
+ QEXPECT_FAIL("", "QTBUG-12441", Abort);
+ QCOMPARE(outer->x(), qreal(49.5));
+ QCOMPARE(outer->y(), qreal(49.5));
+ QCOMPARE(inner->x(), qreal(25.5));
+ QCOMPARE(inner->y(), qreal(25.5));
+
+ delete view;
+}
+
+void tst_qquickanchors::hvCenter()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("hvCenter.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+
+ // test QTBUG-10999
+ QCOMPARE(rect->x(), 10.0);
+ QCOMPARE(rect->y(), 19.0);
+
+ rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
+ rectPrivate->anchors()->setVerticalCenterOffset(5.0);
+ QCOMPARE(rect->x(), 10.0 - 5.0);
+ QCOMPARE(rect->y(), 19.0 + 5.0);
+
+ delete view;
+}
+
+void tst_qquickanchors::hvCenterRTL()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("hvCenter.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ mirrorAnchors(rect);
+
+ // test QTBUG-10999
+ QCOMPARE(rect->x(), 10.0);
+ QCOMPARE(rect->y(), 19.0);
+
+ rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
+ rectPrivate->anchors()->setVerticalCenterOffset(5.0);
+ QCOMPARE(rect->x(), 10.0 + 5.0);
+ QCOMPARE(rect->y(), 19.0 + 5.0);
+
+ delete view;
+}
+void tst_qquickanchors::margins()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("margins.qml")));
+
+ qApp->processEvents();
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ QCOMPARE(rect->x(), 5.0);
+ QCOMPARE(rect->y(), 6.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
+ QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
+
+ rectPrivate->anchors()->setTopMargin(0.0);
+ rectPrivate->anchors()->setMargins(20.0);
+
+ QCOMPARE(rect->x(), 5.0);
+ QCOMPARE(rect->y(), 20.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
+
+ delete view;
+}
+
+void tst_qquickanchors::marginsRTL()
+{
+ QQuickView *view = new QQuickView(QUrl::fromLocalFile(TESTDATA("margins.qml")));
+
+ QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ mirrorAnchors(rect);
+
+ QCOMPARE(rect->x(), 10.0);
+ QCOMPARE(rect->y(), 6.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
+ QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
+
+ rectPrivate->anchors()->setTopMargin(0.0);
+ rectPrivate->anchors()->setMargins(20.0);
+
+ QCOMPARE(rect->x(), 20.0);
+ QCOMPARE(rect->y(), 20.0);
+ QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
+ QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
+
+ delete view;
+}
+
+
+QTEST_MAIN(tst_qquickanchors)
+
+#include "tst_qquickanchors.moc"
diff --git a/tests/auto/declarative/qquickanimatedimage/data/colors.gif b/tests/auto/qtquick2/qquickanimatedimage/data/colors.gif
index 1270bfaa79..1270bfaa79 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/colors.gif
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/colors.gif
Binary files differ
diff --git a/tests/auto/declarative/qquickanimatedimage/data/colors.qml b/tests/auto/qtquick2/qquickanimatedimage/data/colors.qml
index 5ccc0148dd..5ccc0148dd 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/colors.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/colors.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/hearts.gif b/tests/auto/qtquick2/qquickanimatedimage/data/hearts.gif
index cfb55f27f5..cfb55f27f5 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/hearts.gif
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/hearts.gif
Binary files differ
diff --git a/tests/auto/declarative/qquickanimatedimage/data/hearts.qml b/tests/auto/qtquick2/qquickanimatedimage/data/hearts.qml
index 717bab430b..717bab430b 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/hearts.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/hearts.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/qmldir b/tests/auto/qtquick2/qquickanimatedimage/data/qmldir
index ef7c1f44f3..ef7c1f44f3 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/qmldir
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/qmldir
diff --git a/tests/auto/declarative/qquickanimatedimage/data/qtbug-16520.qml b/tests/auto/qtquick2/qquickanimatedimage/data/qtbug-16520.qml
index da77a4063b..da77a4063b 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/qtbug-16520.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/qtbug-16520.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickman.gif b/tests/auto/qtquick2/qquickanimatedimage/data/stickman.gif
index 7c4cd18687..7c4cd18687 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickman.gif
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickman.gif
Binary files differ
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickman.qml b/tests/auto/qtquick2/qquickanimatedimage/data/stickman.qml
index a47924de21..a47924de21 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickman.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickman.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickmanerror1.qml b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanerror1.qml
index 4f823b3d70..4f823b3d70 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickmanerror1.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanerror1.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickmanpause.qml b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanpause.qml
index ef771ed56f..ef771ed56f 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickmanpause.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanpause.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickmanscaled.qml b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanscaled.qml
index 1ef1f95165..1ef1f95165 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickmanscaled.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanscaled.qml
diff --git a/tests/auto/declarative/qquickanimatedimage/data/stickmanstopped.qml b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanstopped.qml
index 0bf80b8972..0bf80b8972 100644
--- a/tests/auto/declarative/qquickanimatedimage/data/stickmanstopped.qml
+++ b/tests/auto/qtquick2/qquickanimatedimage/data/stickmanstopped.qml
diff --git a/tests/auto/qtquick2/qquickanimatedimage/qquickanimatedimage.pro b/tests/auto/qtquick2/qquickanimatedimage/qquickanimatedimage.pro
new file mode 100644
index 0000000000..56394592b8
--- /dev/null
+++ b/tests/auto/qtquick2/qquickanimatedimage/qquickanimatedimage.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickanimatedimage
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qquickanimatedimage.cpp ../../shared/testhttpserver.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/qtquick2/qquickanimatedimage/tst_qquickanimatedimage.cpp
new file mode 100644
index 0000000000..bf1017fe21
--- /dev/null
+++ b/tests/auto/qtquick2/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qquickimage_p.h>
+#include <private/qquickanimatedimage_p.h>
+#include <QSignalSpy>
+#include <QtDeclarative/qdeclarativecontext.h>
+
+#include "../../shared/testhttpserver.h"
+#include "../../shared/util.h"
+
+Q_DECLARE_METATYPE(QQuickImageBase::Status)
+
+class tst_qquickanimatedimage : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickanimatedimage() {}
+
+private slots:
+ void play();
+ void pause();
+ void stopped();
+ void setFrame();
+ void frameCount();
+ void mirror_running();
+ void mirror_notRunning();
+ void mirror_notRunning_data();
+ void remote();
+ void remote_data();
+ void sourceSize();
+ void sourceSizeReadOnly();
+ void invalidSource();
+ void qtbug_16520();
+ void progressAndStatusChanges();
+
+};
+
+void tst_qquickanimatedimage::play()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickman.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::pause()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QVERIFY(anim->isPaused());
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::stopped()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(!anim->isPlaying());
+ QCOMPARE(anim->currentFrame(), 0);
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::setFrame()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QCOMPARE(anim->currentFrame(), 2);
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::frameCount()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("colors.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QCOMPARE(anim->frameCount(), 3);
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::mirror_running()
+{
+ // test where mirror is set to true after animation has started
+
+ QQuickView *canvas = new QQuickView;
+ canvas->show();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("hearts.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
+ QVERIFY(anim);
+
+ int width = anim->property("width").toInt();
+
+ QCOMPARE(anim->currentFrame(), 0);
+ QPixmap frame0 = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ anim->setCurrentFrame(1);
+ QPixmap frame1 = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ anim->setCurrentFrame(0);
+
+ QSignalSpy spy(anim, SIGNAL(frameChanged()));
+ anim->setPlaying(true);
+
+ QTRY_VERIFY(spy.count() == 1); spy.clear();
+ anim->setProperty("mirror", true);
+
+ QCOMPARE(anim->currentFrame(), 1);
+ QPixmap frame1_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ QTRY_VERIFY(spy.count() == 1); spy.clear();
+ QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
+ QPixmap frame0_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
+
+ QTransform transform;
+ transform.translate(width, 0).scale(-1, 1.0);
+ QPixmap frame0_expected = frame0.transformed(transform);
+ QPixmap frame1_expected = frame1.transformed(transform);
+
+ QCOMPARE(frame0_flipped, frame0_expected);
+ QCOMPARE(frame1_flipped, frame1_expected);
+
+ delete canvas;
+}
+
+void tst_qquickanimatedimage::mirror_notRunning()
+{
+ QFETCH(QUrl, fileUrl);
+
+ QQuickView *canvas = new QQuickView;
+ canvas->show();
+
+ canvas->setSource(fileUrl);
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
+ QVERIFY(anim);
+
+ int width = anim->property("width").toInt();
+ QPixmap screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ QTransform transform;
+ transform.translate(width, 0).scale(-1, 1.0);
+ QPixmap expected = screenshot.transformed(transform);
+
+ int frame = anim->currentFrame();
+ bool playing = anim->isPlaying();
+ bool paused = anim->isPlaying();
+
+ anim->setProperty("mirror", true);
+ screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
+
+ QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
+ QCOMPARE(screenshot, expected);
+
+ // mirroring should not change the current frame or playing status
+ QCOMPARE(anim->currentFrame(), frame);
+ QCOMPARE(anim->isPlaying(), playing);
+ QCOMPARE(anim->isPaused(), paused);
+
+ delete canvas;
+}
+
+void tst_qquickanimatedimage::mirror_notRunning_data()
+{
+ QTest::addColumn<QUrl>("fileUrl");
+
+ QTest::newRow("paused") << QUrl::fromLocalFile(TESTDATA("stickmanpause.qml"));
+ QTest::newRow("stopped") << QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml"));
+}
+
+void tst_qquickanimatedimage::remote()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, paused);
+
+ TestHTTPServer server(14449);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
+ QTRY_VERIFY(component.isReady());
+
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+
+ QTRY_VERIFY(anim->isPlaying());
+ if (paused) {
+ QTRY_VERIFY(anim->isPaused());
+ QCOMPARE(anim->currentFrame(), 2);
+ }
+ QVERIFY(anim->status() != QQuickAnimatedImage::Error);
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::sourceSize()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanscaled.qml")));
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+ QCOMPARE(anim->width(),240.0);
+ QCOMPARE(anim->height(),180.0);
+ QCOMPARE(anim->sourceSize(),QSize(160,120));
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::sourceSizeReadOnly()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanerror1.qml")));
+ QVERIFY(component.isError());
+ QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
+}
+
+void tst_qquickanimatedimage::remote_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("paused");
+
+ QTest::newRow("playing") << "stickman.qml" << false;
+ QTest::newRow("paused") << "stickmanpause.qml" << true;
+}
+
+void tst_qquickanimatedimage::invalidSource()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
+ QVERIFY(component.isReady());
+
+ QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
+
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+ QVERIFY(anim);
+
+ QVERIFY(!anim->isPlaying());
+ QVERIFY(!anim->isPaused());
+ QCOMPARE(anim->currentFrame(), 0);
+ QCOMPARE(anim->frameCount(), 0);
+ QTRY_VERIFY(anim->status() == 3);
+}
+
+void tst_qquickanimatedimage::qtbug_16520()
+{
+ TestHTTPServer server(14449);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("qtbug-16520.qml")));
+ QTRY_VERIFY(component.isReady());
+
+ QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
+ QVERIFY(root);
+ QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
+
+ anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
+
+ QTRY_VERIFY(anim->opacity() == 0);
+ QTRY_VERIFY(anim->opacity() == 1);
+
+ delete anim;
+}
+
+void tst_qquickanimatedimage::progressAndStatusChanges()
+{
+ TestHTTPServer server(14449);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ QDeclarativeEngine engine;
+ QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("stickman.gif")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+
+ qRegisterMetaType<QQuickImageBase::Status>();
+ QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
+ QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
+ QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
+
+ // Loading local file
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.gif")));
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 1);
+ QTRY_COMPARE(progressSpy.count(), 0);
+ QTRY_COMPARE(statusSpy.count(), 0);
+
+ // Loading remote file
+ ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
+ QTRY_VERIFY(obj->status() == QQuickImage::Loading);
+ QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 2);
+ QTRY_VERIFY(progressSpy.count() > 1);
+ QTRY_COMPARE(statusSpy.count(), 2);
+
+ ctxt->setContextProperty("srcImage", "");
+ QTRY_VERIFY(obj->status() == QQuickImage::Null);
+ QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_COMPARE(sourceSpy.count(), 3);
+ QTRY_VERIFY(progressSpy.count() > 2);
+ QTRY_COMPARE(statusSpy.count(), 3);
+}
+
+QTEST_MAIN(tst_qquickanimatedimage)
+
+#include "tst_qquickanimatedimage.moc"
diff --git a/tests/auto/declarative/qquickborderimage/data/colors-mirror.png b/tests/auto/qtquick2/qquickborderimage/data/colors-mirror.png
index e30870dd1e..e30870dd1e 100644
--- a/tests/auto/declarative/qquickborderimage/data/colors-mirror.png
+++ b/tests/auto/qtquick2/qquickborderimage/data/colors-mirror.png
Binary files differ
diff --git a/tests/auto/declarative/qquickborderimage/data/colors-round-quotes.sci b/tests/auto/qtquick2/qquickborderimage/data/colors-round-quotes.sci
index 294f3cfe48..294f3cfe48 100644
--- a/tests/auto/declarative/qquickborderimage/data/colors-round-quotes.sci
+++ b/tests/auto/qtquick2/qquickborderimage/data/colors-round-quotes.sci
diff --git a/tests/auto/declarative/qquickborderimage/data/colors-round-remote.sci b/tests/auto/qtquick2/qquickborderimage/data/colors-round-remote.sci
index c673bed598..c673bed598 100644
--- a/tests/auto/declarative/qquickborderimage/data/colors-round-remote.sci
+++ b/tests/auto/qtquick2/qquickborderimage/data/colors-round-remote.sci
diff --git a/tests/auto/declarative/qquickborderimage/data/colors-round.sci b/tests/auto/qtquick2/qquickborderimage/data/colors-round.sci
index 5d2f49f0e1..5d2f49f0e1 100644
--- a/tests/auto/declarative/qquickborderimage/data/colors-round.sci
+++ b/tests/auto/qtquick2/qquickborderimage/data/colors-round.sci
diff --git a/tests/auto/declarative/qquickborderimage/data/colors.png b/tests/auto/qtquick2/qquickborderimage/data/colors.png
index dfb62f3d64..dfb62f3d64 100644
--- a/tests/auto/declarative/qquickborderimage/data/colors.png
+++ b/tests/auto/qtquick2/qquickborderimage/data/colors.png
Binary files differ
diff --git a/tests/auto/declarative/qquickborderimage/data/heart200.png b/tests/auto/qtquick2/qquickborderimage/data/heart200.png
index 5a31ae8f4d..5a31ae8f4d 100644
--- a/tests/auto/declarative/qquickborderimage/data/heart200.png
+++ b/tests/auto/qtquick2/qquickborderimage/data/heart200.png
Binary files differ
diff --git a/tests/auto/declarative/qquickborderimage/data/invalid.sci b/tests/auto/qtquick2/qquickborderimage/data/invalid.sci
index 98c72c9bf1..98c72c9bf1 100644
--- a/tests/auto/declarative/qquickborderimage/data/invalid.sci
+++ b/tests/auto/qtquick2/qquickborderimage/data/invalid.sci
diff --git a/tests/auto/declarative/qquickborderimage/data/mirror.qml b/tests/auto/qtquick2/qquickborderimage/data/mirror.qml
index abab076e08..abab076e08 100644
--- a/tests/auto/declarative/qquickborderimage/data/mirror.qml
+++ b/tests/auto/qtquick2/qquickborderimage/data/mirror.qml
diff --git a/tests/auto/qtquick2/qquickborderimage/qquickborderimage.pro b/tests/auto/qtquick2/qquickborderimage/qquickborderimage.pro
new file mode 100644
index 0000000000..34d08aa37f
--- /dev/null
+++ b/tests/auto/qtquick2/qquickborderimage/qquickborderimage.pro
@@ -0,0 +1,14 @@
+CONFIG += testcase
+TARGET = tst_qquickborderimage
+macx:CONFIG -= app_bundle
+
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qquickborderimage.cpp ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network widgets testlib
diff --git a/tests/auto/qtquick2/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/qtquick2/qquickborderimage/tst_qquickborderimage.cpp
new file mode 100644
index 0000000000..b9fd91d7fb
--- /dev/null
+++ b/tests/auto/qtquick2/qquickborderimage/tst_qquickborderimage.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QTextDocument>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QDir>
+#include <QGraphicsScene>
+#include <QPainter>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qquickborderimage_p.h>
+#include <private/qquickimagebase_p.h>
+#include <private/qquickscalegrid_p_p.h>
+#include <private/qquickloader_p.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+
+#include "../../shared/testhttpserver.h"
+#include "../../shared/util.h"
+
+#define SERVER_PORT 14446
+#define SERVER_ADDR "http://127.0.0.1:14446"
+
+class tst_qquickborderimage : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qquickborderimage();
+
+private slots:
+ void noSource();
+ void imageSource();
+ void imageSource_data();
+ void clearSource();
+ void resized();
+ void smooth();
+ void mirror();
+ void tileModes();
+ void sciSource();
+ void sciSource_data();
+ void invalidSciFile();
+ void pendingRemoteRequest();
+ void pendingRemoteRequest_data();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qquickborderimage::tst_qquickborderimage()
+{
+}
+
+void tst_qquickborderimage::noSource()
+{
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->source(), QUrl());
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qquickborderimage::imageSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("remote");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << false << "";
+ QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << false
+ << "file::2:1: QML BorderImage: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString();
+ QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << "";
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true
+ << "file::2:1: QML BorderImage: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
+}
+
+void tst_qquickborderimage::imageSource()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, remote);
+ QFETCH(QString, error);
+
+ TestHTTPServer *server = 0;
+ if (remote) {
+ server = new TestHTTPServer(SERVER_PORT);
+ QVERIFY(server->isValid());
+ server->serveDirectory(TESTDATA(""));
+ }
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
+
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (remote)
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+
+ if (error.isEmpty()) {
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QCOMPARE(obj->sourceSize().width(), 120);
+ QCOMPARE(obj->sourceSize().height(), 120);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
+ } else {
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
+ }
+
+ delete obj;
+ delete server;
+}
+
+void tst_qquickborderimage::clearSource()
+{
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: srcImage }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QQuickBorderImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+
+ ctxt->setContextProperty("srcImage", "");
+ QVERIFY(obj->source().isEmpty());
+ QVERIFY(obj->status() == QQuickBorderImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+}
+
+void tst_qquickborderimage::resized()
+{
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + QUrl::fromLocalFile(TESTDATA("colors.png")).toString() + "\"; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->sourceSize().width(), 120);
+ QCOMPARE(obj->sourceSize().height(), 120);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qquickborderimage::smooth()
+{
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->smooth(), true);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qquickborderimage::mirror()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->show();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml")));
+ QQuickBorderImage *image = qobject_cast<QQuickBorderImage*>(canvas->rootObject());
+ QVERIFY(image != 0);
+ canvas->show();
+
+ QImage screenshot = canvas->grabFrameBuffer();
+
+ QImage srcPixmap(screenshot);
+ QTransform transform;
+ transform.translate(image->width(), 0).scale(-1, 1.0);
+ srcPixmap = srcPixmap.transformed(transform);
+
+ image->setProperty("mirror", true);
+ screenshot = canvas->grabFrameBuffer();
+ QCOMPARE(screenshot, srcPixmap);
+
+ delete canvas;
+}
+
+void tst_qquickborderimage::tileModes()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; width: 100; height: 300; horizontalTileMode: BorderImage.Repeat; verticalTileMode: BorderImage.Repeat }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 100.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Repeat);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Repeat);
+
+ delete obj;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 150; horizontalTileMode: BorderImage.Round; verticalTileMode: BorderImage.Round }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 150.);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Round);
+
+ delete obj;
+ }
+}
+
+void tst_qquickborderimage::sciSource()
+{
+ QFETCH(QString, source);
+ QFETCH(bool, valid);
+
+ bool remote = source.startsWith("http");
+ TestHTTPServer *server = 0;
+ if (remote) {
+ server = new TestHTTPServer(SERVER_PORT);
+ QVERIFY(server->isValid());
+ server->serveDirectory(TESTDATA(""));
+ }
+
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\"; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (remote)
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+
+ if (valid) {
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Ready);
+ QCOMPARE(obj->border()->left(), 10);
+ QCOMPARE(obj->border()->top(), 20);
+ QCOMPARE(obj->border()->right(), 30);
+ QCOMPARE(obj->border()->bottom(), 40);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Repeat);
+ } else {
+ QTRY_VERIFY(obj->status() == QQuickBorderImage::Error);
+ }
+
+ delete obj;
+ delete server;
+}
+
+void tst_qquickborderimage::sciSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<bool>("valid");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors-round.sci")).toString() << true;
+ QTest::newRow("local quoted filename") << QUrl::fromLocalFile(TESTDATA("colors-round-quotes.sci")).toString() << true;
+ QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.sci")).toString() << false;
+ QTest::newRow("remote") << SERVER_ADDR "/colors-round.sci" << true;
+ QTest::newRow("remote filename quoted") << SERVER_ADDR "/colors-round-quotes.sci" << true;
+ QTest::newRow("remote image") << SERVER_ADDR "/colors-round-remote.sci" << true;
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.sci" << false;
+}
+
+void tst_qquickborderimage::invalidSciFile()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QQuickGridScaledImage: Invalid tile rule specified. Using Stretch."); // for "Roun"
+ QTest::ignoreMessage(QtWarningMsg, "QQuickGridScaledImage: Invalid tile rule specified. Using Stretch."); // for "Repea"
+
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + QUrl::fromLocalFile(TESTDATA("invalid.sci")).toString() +"\"; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->status(), QQuickImageBase::Error);
+ QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Stretch);
+ QCOMPARE(obj->verticalTileMode(), QQuickBorderImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qquickborderimage::pendingRemoteRequest()
+{
+ QFETCH(QString, source);
+
+ QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->status(), QQuickBorderImage::Loading);
+
+ // verify no crash
+ // This will cause a delayed "QThread: Destroyed while thread is still running" warning
+ delete obj;
+ QTest::qWait(50);
+}
+
+void tst_qquickborderimage::pendingRemoteRequest_data()
+{
+ QTest::addColumn<QString>("source");
+
+ QTest::newRow("png file") << "http://localhost/none.png";
+ QTest::newRow("sci file") << "http://localhost/none.sci";
+}
+
+QTEST_MAIN(tst_qquickborderimage)
+
+#include "tst_qquickborderimage.moc"
diff --git a/tests/auto/declarative/qquickcanvas/data/window.qml b/tests/auto/qtquick2/qquickcanvas/data/window.qml
index d79d5161b5..d79d5161b5 100644
--- a/tests/auto/declarative/qquickcanvas/data/window.qml
+++ b/tests/auto/qtquick2/qquickcanvas/data/window.qml
diff --git a/tests/auto/qtquick2/qquickcanvas/qquickcanvas.pro b/tests/auto/qtquick2/qquickcanvas/qquickcanvas.pro
new file mode 100644
index 0000000000..c95d474a21
--- /dev/null
+++ b/tests/auto/qtquick2/qquickcanvas/qquickcanvas.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qquickcanvas
+SOURCES += tst_qquickcanvas.cpp
+
+macx:CONFIG -= app_bundle
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickcanvas/tst_qquickcanvas.cpp b/tests/auto/qtquick2/qquickcanvas/tst_qquickcanvas.cpp
new file mode 100644
index 0000000000..f894ff3d39
--- /dev/null
+++ b/tests/auto/qtquick2/qquickcanvas/tst_qquickcanvas.cpp
@@ -0,0 +1,557 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QDebug>
+#include <QTouchEvent>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickCanvas>
+#include <QtDeclarative/QDeclarativeEngine>
+#include <QtDeclarative/QDeclarativeComponent>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtGui/QWindowSystemInterface>
+#include "../../shared/util.h"
+
+struct TouchEventData {
+ QEvent::Type type;
+ QWidget *widget;
+ QWindow *window;
+ Qt::TouchPointStates states;
+ QList<QTouchEvent::TouchPoint> touchPoints;
+};
+
+static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p, const QPointF &lastPoint = QPointF())
+{
+ QPointF last = lastPoint.isNull() ? p : lastPoint;
+
+ QTouchEvent::TouchPoint tp;
+
+ tp.setPos(p);
+ tp.setLastPos(last);
+ tp.setScenePos(item->mapToScene(p));
+ tp.setLastScenePos(item->mapToScene(last));
+ tp.setScreenPos(item->canvas()->mapToGlobal(tp.scenePos().toPoint()));
+ tp.setLastScreenPos(item->canvas()->mapToGlobal(tp.lastScenePos().toPoint()));
+ return tp;
+}
+
+static TouchEventData makeTouchData(QEvent::Type type, QWidget *w, Qt::TouchPointStates states, const QList<QTouchEvent::TouchPoint> &touchPoints)
+{
+ TouchEventData d = { type, w, 0, states, touchPoints };
+ return d;
+}
+
+static TouchEventData makeTouchData(QEvent::Type type, QWidget *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
+{
+ QList<QTouchEvent::TouchPoint> points;
+ points << touchPoint;
+ return makeTouchData(type, w, states, points);
+}
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QList<QTouchEvent::TouchPoint>& touchPoints)
+{
+ TouchEventData d = { type, 0, w, states, touchPoints };
+ return d;
+}
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
+{
+ QList<QTouchEvent::TouchPoint> points;
+ points << touchPoint;
+ return makeTouchData(type, w, states, points);
+}
+
+#define COMPARE_TOUCH_POINTS(tp1, tp2) \
+{ \
+ QCOMPARE(tp1.pos(), tp2.pos()); \
+ QCOMPARE(tp1.lastPos(), tp2.lastPos()); \
+ QCOMPARE(tp1.scenePos(), tp2.scenePos()); \
+ QCOMPARE(tp1.lastScenePos(), tp2.lastScenePos()); \
+ QCOMPARE(tp1.screenPos(), tp2.screenPos()); \
+ QCOMPARE(tp1.lastScreenPos(), tp2.lastScreenPos()); \
+}
+
+#define COMPARE_TOUCH_DATA(d1, d2) \
+{ \
+ QCOMPARE((int)d1.type, (int)d2.type); \
+ QCOMPARE(d1.widget, d2.widget); \
+ QCOMPARE((int)d1.states, (int)d2.states); \
+ QCOMPARE(d1.touchPoints.count(), d2.touchPoints.count()); \
+ for (int i=0; i<d1.touchPoints.count(); i++) { \
+ COMPARE_TOUCH_POINTS(d1.touchPoints[i], d2.touchPoints[i]); \
+ } \
+}
+
+class TestTouchItem : public QQuickRectangle
+{
+ Q_OBJECT
+public:
+ TestTouchItem(QQuickItem *parent = 0)
+ : QQuickRectangle(parent), acceptEvents(true), mousePressId(0)
+ {
+ border()->setWidth(1);
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFiltersChildMouseEvents(true);
+ }
+
+ void reset() {
+ acceptEvents = true;
+ setEnabled(true);
+ setOpacity(1.0);
+
+ lastEvent = makeTouchData(QEvent::None, canvas(), 0, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
+ }
+
+ bool acceptEvents;
+ TouchEventData lastEvent;
+ int mousePressId;
+
+protected:
+ virtual void touchEvent(QTouchEvent *event) {
+ if (!acceptEvents) {
+ event->ignore();
+ return;
+ }
+ lastEvent = makeTouchData(event->type(), event->widget(), event->touchPointStates(), event->touchPoints());
+ event->accept();
+ }
+
+ virtual void mousePressEvent(QMouseEvent *) {
+ mousePressId = ++mousePressNum;
+ }
+
+ bool childMouseEventFilter(QQuickItem *, QEvent *event) {
+ if (event->type() == QEvent::MouseButtonPress)
+ mousePressId = ++mousePressNum;
+ return false;
+ }
+
+ static int mousePressNum;
+};
+
+int TestTouchItem::mousePressNum = 0;
+
+class ConstantUpdateItem : public QQuickItem
+{
+Q_OBJECT
+public:
+ ConstantUpdateItem(QQuickItem *parent = 0) : QQuickItem(parent), iterations(0) {setFlag(ItemHasContents);}
+
+ int iterations;
+protected:
+ QSGNode* updatePaintNode(QSGNode *, UpdatePaintNodeData *){
+ iterations++;
+ update();
+ return 0;
+ }
+};
+
+class tst_qquickcanvas : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickcanvas();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void constantUpdates();
+
+ void touchEvent_basic();
+ void touchEvent_propagation();
+ void touchEvent_propagation_data();
+
+ void clearCanvas();
+ void mouseFiltering();
+
+ void qmlCreation();
+ void clearColor();
+};
+
+tst_qquickcanvas::tst_qquickcanvas()
+{
+}
+
+void tst_qquickcanvas::initTestCase()
+{
+}
+
+void tst_qquickcanvas::cleanupTestCase()
+{
+}
+
+//If the item calls update inside updatePaintNode, it should schedule another update
+void tst_qquickcanvas::constantUpdates()
+{
+ QQuickCanvas canvas;
+ ConstantUpdateItem item(canvas.rootItem());
+ canvas.show();
+ QTRY_VERIFY(item.iterations > 60);
+}
+
+void tst_qquickcanvas::touchEvent_basic()
+{
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(250, 250);
+ canvas->move(100, 100);
+ canvas->show();
+
+ TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPointF pos(10, 10);
+
+ // press single point
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas);
+ QTest::qWait(50);
+
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ TouchEventData d = makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem,pos));
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ topItem->reset();
+
+ // press multiple points
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+
+ // touch point on top item moves to bottom item, but top item should still receive the event
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).move(0, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, canvas, Qt::TouchPointMoved,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
+ topItem->reset();
+
+ // touch point on bottom item moves to top item, but bottom item should still receive the event
+ QTest::touchEvent(canvas).press(0, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).move(0, topItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, canvas, Qt::TouchPointMoved,
+ makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
+ bottomItem->reset();
+
+ // a single stationary press on an item shouldn't cause an event
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).stationary(0)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+
+ // move touch point from top item to bottom, and release
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).release(0, bottomItem->mapToScene(pos).toPoint(),canvas);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, canvas, Qt::TouchPointReleased,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
+ topItem->reset();
+
+ // release while another point is pressed
+ QTest::touchEvent(canvas).press(0, topItem->mapToScene(pos).toPoint(),canvas)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).move(0, bottomItem->mapToScene(pos).toPoint(), canvas);
+ QTest::qWait(50);
+ QTest::touchEvent(canvas).release(0, bottomItem->mapToScene(pos).toPoint(), canvas)
+ .stationary(1);
+ QTest::qWait(50);
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, canvas, Qt::TouchPointReleased,
+ makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos))));
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
+ topItem->reset();
+ bottomItem->reset();
+
+ delete topItem;
+ delete middleItem;
+ delete bottomItem;
+ delete canvas;
+}
+
+void tst_qquickcanvas::touchEvent_propagation()
+{
+ QFETCH(bool, acceptEvents);
+ QFETCH(bool, enableItem);
+ QFETCH(qreal, itemOpacity);
+
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(250, 250);
+ canvas->move(100, 100);
+ canvas->show();
+
+ TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPointF pos(10, 10);
+ QPoint pointInBottomItem = bottomItem->mapToScene(pos).toPoint(); // (10, 10)
+ QPoint pointInMiddleItem = middleItem->mapToScene(pos).toPoint(); // (60, 60) overlaps with bottomItem
+ QPoint pointInTopItem = topItem->mapToScene(pos).toPoint(); // (110, 110) overlaps with bottom & top items
+
+ // disable topItem
+ topItem->acceptEvents = acceptEvents;
+ topItem->setEnabled(enableItem);
+ topItem->setOpacity(itemOpacity);
+
+ // single touch to top item, should be received by middle item
+ QTest::touchEvent(canvas).press(0, pointInTopItem, canvas);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(middleItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
+ makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))));
+
+ // touch top and middle items, middle item should get both events
+ QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
+ .press(1, pointInMiddleItem, canvas);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(middleItem->lastEvent.touchPoints.count(), 2);
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))
+ << makeTouchPoint(middleItem, pos) )));
+ middleItem->reset();
+
+ // disable middleItem as well
+ middleItem->acceptEvents = acceptEvents;
+ middleItem->setEnabled(enableItem);
+ middleItem->setOpacity(itemOpacity);
+
+ // touch top and middle items, bottom item should get all events
+ QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
+ .press(1, pointInMiddleItem, canvas);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 2);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))
+ << makeTouchPoint(bottomItem, bottomItem->mapFromItem(middleItem, pos)) )));
+ bottomItem->reset();
+
+ // disable bottom item as well
+ bottomItem->acceptEvents = acceptEvents;
+ bottomItem->setEnabled(enableItem);
+ bottomItem->setOpacity(itemOpacity);
+
+ // no events should be received
+ QTest::touchEvent(canvas).press(0, pointInTopItem, canvas)
+ .press(1, pointInMiddleItem, canvas)
+ .press(2, pointInBottomItem, canvas);
+ QTest::qWait(50);
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+
+ topItem->reset();
+ middleItem->reset();
+ bottomItem->reset();
+
+ // disable middle item, touch on top item
+ middleItem->acceptEvents = acceptEvents;
+ middleItem->setEnabled(enableItem);
+ middleItem->setOpacity(itemOpacity);
+ QTest::touchEvent(canvas).press(0, pointInTopItem, canvas);
+ QTest::qWait(50);
+ if (!enableItem || itemOpacity == 0) {
+ // middle item is disabled or has 0 opacity, bottom item receives the event
+ QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
+ COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
+ makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))));
+ } else {
+ // middle item ignores event, sends it to the top item (top-most child)
+ QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
+ QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
+ COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed,
+ makeTouchPoint(topItem, pos)));
+ }
+
+ delete topItem;
+ delete middleItem;
+ delete bottomItem;
+ delete canvas;
+}
+
+void tst_qquickcanvas::touchEvent_propagation_data()
+{
+ QTest::addColumn<bool>("acceptEvents");
+ QTest::addColumn<bool>("enableItem");
+ QTest::addColumn<qreal>("itemOpacity");
+
+ QTest::newRow("disable events") << false << true << 1.0;
+ QTest::newRow("disable item") << true << false << 1.0;
+ QTest::newRow("opacity of 0") << true << true << 0.0;
+}
+
+void tst_qquickcanvas::clearCanvas()
+{
+ QQuickCanvas *canvas = new QQuickCanvas;
+ QQuickItem *item = new QQuickItem;
+ item->setParentItem(canvas->rootItem());
+
+ QVERIFY(item->canvas() == canvas);
+
+ delete canvas;
+
+ QVERIFY(item->canvas() == 0);
+
+ delete item;
+}
+
+void tst_qquickcanvas::mouseFiltering()
+{
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(250, 250);
+ canvas->move(100, 100);
+ canvas->show();
+
+ TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
+ bottomItem->setObjectName("Bottom Item");
+ bottomItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+ middleItem->setObjectName("Middle Item");
+ middleItem->setPos(QPointF(50, 50));
+ middleItem->setSize(QSizeF(150, 150));
+
+ TestTouchItem *topItem = new TestTouchItem(middleItem);
+ topItem->setObjectName("Top Item");
+ topItem->setPos(QPointF(50, 50));
+ topItem->setSize(QSizeF(150, 150));
+
+ QPoint pos(100, 100);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, pos);
+ QTest::qWait(50);
+
+ // Mouse filtering propagates down the stack, so the
+ // correct order is
+ // 1. middleItem filters event
+ // 2. bottomItem filters event
+ // 3. topItem receives event
+ QCOMPARE(middleItem->mousePressId, 1);
+ QCOMPARE(bottomItem->mousePressId, 2);
+ QCOMPARE(topItem->mousePressId, 3);
+}
+
+void tst_qquickcanvas::qmlCreation()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+ component.loadUrl(TESTDATA("window.qml"));
+ QObject* created = component.create();
+ QVERIFY(created);
+
+ QQuickCanvas* canvas = qobject_cast<QQuickCanvas*>(created);
+ QVERIFY(canvas);
+ QCOMPARE(canvas->clearColor(), QColor(Qt::green));
+
+ QQuickItem* item = canvas->findChild<QQuickItem*>("item");
+ QVERIFY(item);
+ QCOMPARE(item->canvas(), canvas);
+}
+
+void tst_qquickcanvas::clearColor()
+{
+ //### Can we examine rendering to make sure it is really blue?
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(250, 250);
+ canvas->move(100, 100);
+ canvas->setClearColor(Qt::blue);
+ canvas->show();
+ QTest::qWaitForWindowShown(canvas);
+ QCOMPARE(canvas->clearColor(), QColor(Qt::blue));
+ delete canvas;
+}
+
+QTEST_MAIN(tst_qquickcanvas)
+
+#include "tst_qquickcanvas.moc"
diff --git a/tests/auto/declarative/qquickcanvasitem/data/anim-gr.gif b/tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.gif
index 45263e0afb..45263e0afb 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/anim-gr.gif
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.gif
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/anim-gr.png b/tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.png
index 925e2efc9a..925e2efc9a 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/anim-gr.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/anim-gr.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/anim-poster-gr.png b/tests/auto/qtquick2/qquickcanvasitem/data/anim-poster-gr.png
index 6941207373..6941207373 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/anim-poster-gr.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/anim-poster-gr.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/background.png b/tests/auto/qtquick2/qquickcanvasitem/data/background.png
index 6db6c6b1b9..6db6c6b1b9 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/background.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/background.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/broken.png b/tests/auto/qtquick2/qquickcanvasitem/data/broken.png
index f2581017b4..f2581017b4 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/broken.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/broken.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/ggrr-256x256.png b/tests/auto/qtquick2/qquickcanvasitem/data/ggrr-256x256.png
index 0342e4a384..0342e4a384 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/ggrr-256x256.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/ggrr-256x256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/green-16x16.png b/tests/auto/qtquick2/qquickcanvasitem/data/green-16x16.png
index e19a3ffddd..e19a3ffddd 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/green-16x16.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/green-16x16.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/green-1x1.png b/tests/auto/qtquick2/qquickcanvasitem/data/green-1x1.png
index 862d1dd10c..862d1dd10c 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/green-1x1.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/green-1x1.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/green-256x256.png b/tests/auto/qtquick2/qquickcanvasitem/data/green-256x256.png
index b06945c310..b06945c310 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/green-256x256.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/green-256x256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/green-2x2.png b/tests/auto/qtquick2/qquickcanvasitem/data/green-2x2.png
index adc059449c..adc059449c 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/green-2x2.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/green-2x2.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/green.png b/tests/auto/qtquick2/qquickcanvasitem/data/green.png
index 28a1faab37..28a1faab37 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/green.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/green.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/grgr-256x256.png b/tests/auto/qtquick2/qquickcanvasitem/data/grgr-256x256.png
index b8c7189d62..b8c7189d62 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/grgr-256x256.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/grgr-256x256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/red-16x16.png b/tests/auto/qtquick2/qquickcanvasitem/data/red-16x16.png
index 9038fef784..9038fef784 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/red-16x16.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/red-16x16.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/red.png b/tests/auto/qtquick2/qquickcanvasitem/data/red.png
index a6e195d59c..a6e195d59c 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/red.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/red.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/redtransparent.png b/tests/auto/qtquick2/qquickcanvasitem/data/redtransparent.png
index 75da08c3d6..75da08c3d6 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/redtransparent.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/redtransparent.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/rgrg-256x256.png b/tests/auto/qtquick2/qquickcanvasitem/data/rgrg-256x256.png
index e6fba3daa5..e6fba3daa5 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/rgrg-256x256.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/rgrg-256x256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/rrgg-256x256.png b/tests/auto/qtquick2/qquickcanvasitem/data/rrgg-256x256.png
index 7f63515654..7f63515654 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/rrgg-256x256.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/rrgg-256x256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/testhelper.js b/tests/auto/qtquick2/qquickcanvasitem/data/testhelper.js
index bac0210e16..bac0210e16 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/testhelper.js
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/testhelper.js
diff --git a/tests/auto/declarative/qquickcanvasitem/data/transparent.png b/tests/auto/qtquick2/qquickcanvasitem/data/transparent.png
index 2b498699a8..2b498699a8 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/transparent.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/transparent.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/transparent50.png b/tests/auto/qtquick2/qquickcanvasitem/data/transparent50.png
index 55f8e69325..55f8e69325 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/transparent50.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/transparent50.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_arc.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_arc.qml
index 6006a5a4c0..6006a5a4c0 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_arc.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_arc.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_arcto.qml
index cc1d88672b..cc1d88672b 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_arcto.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_arcto.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_canvas.qml
index 70bedb2131..70bedb2131 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_canvas.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_composite.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_composite.qml
index 11e1dce902..11e1dce902 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_composite.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_composite.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_drawimage.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_drawimage.qml
index 3752f528be..3752f528be 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_drawimage.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_drawimage.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_fillStyle.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_fillStyle.qml
index 8f5a78cec0..8f5a78cec0 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_fillStyle.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_fillStyle.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_fillrect.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_fillrect.qml
index 2061647268..2061647268 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_fillrect.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_fillrect.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_gradient.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_gradient.qml
index d454c2efe1..d454c2efe1 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_gradient.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_gradient.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_line.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_line.qml
index baf9987ce3..baf9987ce3 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_line.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_line.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_path.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_path.qml
index b04ccf5458..b04ccf5458 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_path.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_path.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_pattern.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_pattern.qml
index dd5b6628e8..dd5b6628e8 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_pattern.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_pattern.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_pixel.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_pixel.qml
index 1a3793d7a3..1a3793d7a3 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_pixel.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_pixel.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_shadow.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_shadow.qml
index 4405ca6c0e..4405ca6c0e 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_shadow.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_shadow.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_state.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_state.qml
index 8042cf6a1d..8042cf6a1d 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_state.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_state.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_strokeStyle.qml
index 6b42f8a770..6b42f8a770 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_strokeStyle.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_strokeStyle.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_text.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_text.qml
index baeb17c9fb..baeb17c9fb 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_text.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_text.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/tst_transform.qml b/tests/auto/qtquick2/qquickcanvasitem/data/tst_transform.qml
index 834a22f549..834a22f549 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/tst_transform.qml
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/tst_transform.qml
diff --git a/tests/auto/declarative/qquickcanvasitem/data/yellow.png b/tests/auto/qtquick2/qquickcanvasitem/data/yellow.png
index 51e8aaf38c..51e8aaf38c 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/yellow.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/yellow.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/data/yellow75.png b/tests/auto/qtquick2/qquickcanvasitem/data/yellow75.png
index 2bb82c9834..2bb82c9834 100644
--- a/tests/auto/declarative/qquickcanvasitem/data/yellow75.png
+++ b/tests/auto/qtquick2/qquickcanvasitem/data/yellow75.png
Binary files differ
diff --git a/tests/auto/declarative/qquickcanvasitem/qquickcanvasitem.pro b/tests/auto/qtquick2/qquickcanvasitem/qquickcanvasitem.pro
index 141e477416..141e477416 100644
--- a/tests/auto/declarative/qquickcanvasitem/qquickcanvasitem.pro
+++ b/tests/auto/qtquick2/qquickcanvasitem/qquickcanvasitem.pro
diff --git a/tests/auto/declarative/qquickcanvasitem/tst_qquickcanvasitem.cpp b/tests/auto/qtquick2/qquickcanvasitem/tst_qquickcanvasitem.cpp
index 57195babb7..57195babb7 100644
--- a/tests/auto/declarative/qquickcanvasitem/tst_qquickcanvasitem.cpp
+++ b/tests/auto/qtquick2/qquickcanvasitem/tst_qquickcanvasitem.cpp
diff --git a/tests/auto/qtquick2/qquickdrag/qquickdrag.pro b/tests/auto/qtquick2/qquickdrag/qquickdrag.pro
new file mode 100644
index 0000000000..4fdfa7b355
--- /dev/null
+++ b/tests/auto/qtquick2/qquickdrag/qquickdrag.pro
@@ -0,0 +1,9 @@
+TARGET = tst_qquickdrag
+CONFIG += testcase
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickdrag.cpp
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickdrag/tst_qquickdrag.cpp b/tests/auto/qtquick2/qquickdrag/tst_qquickdrag.cpp
new file mode 100644
index 0000000000..9163df6c62
--- /dev/null
+++ b/tests/auto/qtquick2/qquickdrag/tst_qquickdrag.cpp
@@ -0,0 +1,827 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ QVariant result = expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result.value<T>();
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
+Q_DECLARE_METATYPE(Qt::DropActions)
+
+class TestDropTarget : public QQuickItem
+{
+ Q_OBJECT
+public:
+ TestDropTarget(QQuickItem *parent = 0)
+ : QQuickItem(parent)
+ , enterEvents(0)
+ , moveEvents(0)
+ , leaveEvents(0)
+ , dropEvents(0)
+ , acceptAction(Qt::MoveAction)
+ , defaultAction(Qt::IgnoreAction)
+ , proposedAction(Qt::IgnoreAction)
+ , accept(true)
+ {
+ setFlags(ItemAcceptsDrops);
+ }
+
+ void reset()
+ {
+ enterEvents = 0;
+ moveEvents = 0;
+ leaveEvents = 0;
+ dropEvents = 0;
+ defaultAction = Qt::IgnoreAction;
+ proposedAction = Qt::IgnoreAction;
+ supportedActions = Qt::IgnoreAction;
+ }
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ ++enterEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setAccepted(accept);
+ }
+
+ void dragMoveEvent(QDragMoveEvent *event)
+ {
+ ++moveEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setAccepted(accept);
+ }
+
+ void dragLeaveEvent(QDragLeaveEvent *event)
+ {
+ ++leaveEvents;
+ event->setAccepted(accept);
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ ++dropEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setDropAction(acceptAction);
+ event->setAccepted(accept);
+ }
+
+ int enterEvents;
+ int moveEvents;
+ int leaveEvents;
+ int dropEvents;
+ Qt::DropAction acceptAction;
+ Qt::DropAction defaultAction;
+ Qt::DropAction proposedAction;
+ Qt::DropActions supportedActions;
+ QPointF position;
+ bool accept;
+};
+
+class tst_QQuickDrag: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void active();
+ void drop();
+ void move();
+ void hotSpot();
+ void supportedActions();
+ void proposedAction();
+ void keys();
+ void source();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+void tst_QQuickDrag::initTestCase()
+{
+
+}
+
+void tst_QQuickDrag::cleanupTestCase()
+{
+
+}
+
+void tst_QQuickDrag::active()
+{
+ QQuickCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.cancel()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ // Start while a drag is active, cancels the previous drag and starts a new one.
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.cancel()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ // Enter events aren't sent to items without the QQuickItem::ItemAcceptsDrops flag.
+ dropTarget.setFlags(QQuickItem::Flags());
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.setFlags(QQuickItem::Flags());
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ // Follow up events aren't sent to items if the enter event isn't accepted.
+ dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
+ dropTarget.accept = false;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.accept = true;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.accept = false;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ // Events are sent to hidden or disabled items.
+ dropTarget.accept = true;
+ dropTarget.setVisible(false);
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ evaluate<void>(item, "Drag.active = false");
+ dropTarget.setVisible(true);
+
+ dropTarget.setOpacity(0.0);
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ evaluate<void>(item, "Drag.active = false");
+ dropTarget.setOpacity(1.0);
+
+ dropTarget.setEnabled(false);
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+}
+
+void tst_QQuickDrag::drop()
+{
+ QQuickCanvas canvas;
+ TestDropTarget outerTarget(canvas.rootItem());
+ outerTarget.setSize(QSizeF(100, 100));
+ outerTarget.acceptAction = Qt::CopyAction;
+ TestDropTarget innerTarget(&outerTarget);
+ innerTarget.setSize(QSizeF(100, 100));
+ innerTarget.acceptAction = Qt::MoveAction;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&outerTarget);
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ // Inner target declines the drop so it is propagated to the outer target.
+ innerTarget.accept = false;
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
+
+
+ // Inner target doesn't accept enter so drop goes directly to outer.
+ innerTarget.accept = true;
+ innerTarget.setFlags(QQuickItem::Flags());
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ // Neither target accepts drop so Qt::IgnoreAction is returned.
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ outerTarget.accept = false;
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ // drop doesn't send an event and returns Qt.IgnoreAction if not active.
+ innerTarget.accept = true;
+ outerTarget.accept = true;
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+}
+
+void tst_QQuickDrag::move()
+{
+ QQuickCanvas canvas;
+ TestDropTarget outerTarget(canvas.rootItem());
+ outerTarget.setSize(QSizeF(100, 100));
+ TestDropTarget leftTarget(&outerTarget);
+ leftTarget.setPos(QPointF(0, 35));
+ leftTarget.setSize(QSizeF(30, 30));
+ TestDropTarget rightTarget(&outerTarget);
+ rightTarget.setPos(QPointF(70, 35));
+ rightTarget.setSize(QSizeF(30, 30));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&outerTarget);
+
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(50)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Move within the outer target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(60, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Move into the right target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(75, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(75)); QCOMPARE(outerTarget.position.y(), qreal(50));
+ QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
+
+ // Move into the left target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 1); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 1); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
+ QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(15));
+
+ // Move within the left target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 40));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 1);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(40));
+ QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(5));
+
+ // Move out of all targets.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(110, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+
+ // Stop the right target accepting drag events and move into it.
+ rightTarget.accept = false;
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(80, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(80)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Stop the outer target accepting drag events after it has accepted an enter event.
+ outerTarget.accept = false;
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(60, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Clear the QQuickItem::ItemAcceptsDrops flag from the outer target after it accepted an enter event.
+ outerTarget.setFlags(QQuickItem::Flags());
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(40, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(40)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Clear the QQuickItem::ItemAcceptsDrops flag from the left target before it accepts an enter event.
+ leftTarget.setFlags(QQuickItem::Flags());
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
+}
+
+
+void tst_QQuickDrag::hotSpot()
+{
+ QQuickCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property real hotSpotX: Drag.hotSpot.x\n"
+ "property real hotSpotY: Drag.hotSpot.y\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(0));
+
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.position.x(), qreal(50));
+ QCOMPARE(dropTarget.position.y(), qreal(50));
+
+ evaluate<void>(item, "{ Drag.hotSpot.x = 5, Drag.hotSpot.y = 5 }");
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(5));
+
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.position.x(), qreal(55));
+ QCOMPARE(dropTarget.position.y(), qreal(55));
+
+ item->setPos(QPointF(30, 20));
+ QCOMPARE(dropTarget.position.x(), qreal(35));
+ QCOMPARE(dropTarget.position.y(), qreal(25));
+
+ evaluate<void>(item, "{ Drag.hotSpot.x = 10; Drag.hotSpot.y = 10 }");
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(10));
+ // Changing the hotSpot won't generate a move event so the position is unchanged. Should it?
+ QCOMPARE(dropTarget.position.x(), qreal(35));
+ QCOMPARE(dropTarget.position.y(), qreal(25));
+
+ item->setPos(QPointF(10, 20));
+ QCOMPARE(dropTarget.position.x(), qreal(20));
+ QCOMPARE(dropTarget.position.y(), qreal(30));
+}
+
+void tst_QQuickDrag::supportedActions()
+{
+ QQuickCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property int supportedActions: Drag.supportedActions\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);
+
+ evaluate<void>(item, "Drag.supportedActions = Qt.CopyAction | Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
+
+ // Once a drag is started the proposed actions are locked in for future events.
+ evaluate<void>(item, "Drag.supportedActions = Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ item->setPos(QPointF(60, 60));
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
+
+ // Calling start with proposed actions will override the current actions for the next sequence.
+ evaluate<void>(item, "Drag.start(Qt.CopyAction)");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction);
+
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(dropTarget.supportedActions, Qt::MoveAction);
+}
+
+void tst_QQuickDrag::proposedAction()
+{
+ QQuickCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property int proposedAction: Drag.proposedAction\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
+
+ evaluate<void>(item, "Drag.proposedAction = Qt.CopyAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.CopyAction"), true);
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.defaultAction, Qt::CopyAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::CopyAction);
+
+ // The proposed action can change during a drag.
+ evaluate<void>(item, "Drag.proposedAction = Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
+ item->setPos(QPointF(60, 60));
+ QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
+
+ evaluate<void>(item, "Drag.proposedAction = Qt.LinkAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.LinkAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.LinkAction"), true);
+ evaluate<void>(item, "Drag.drop()");
+ QCOMPARE(dropTarget.defaultAction, Qt::LinkAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::LinkAction);
+}
+
+void tst_QQuickDrag::keys()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property variant keys: Drag.keys\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+
+// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList());
+// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList());
+ QCOMPARE(item->property("keys").toStringList(), QStringList());
+
+ evaluate<void>(item, "Drag.keys = [\"red\", \"blue\"]");
+// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList() << "red" << "blue");
+// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList() << "red" << "blue");
+ QCOMPARE(item->property("keys").toStringList(), QStringList() << "red" << "blue");
+}
+
+void tst_QQuickDrag::source()
+{
+
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property Item source: Drag.source\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Item { id: proxySource; objectName: \"proxySource\" }\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+
+ QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
+ QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
+
+ QQuickItem *proxySource = item->findChild<QQuickItem *>("proxySource");
+ QVERIFY(proxySource);
+
+ evaluate<void>(item, "Drag.source = proxySource");
+ QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(proxySource));
+ QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(proxySource));
+
+ evaluate<void>(item, "Drag.source = undefined");
+ QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
+ QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
+}
+
+QTEST_MAIN(tst_QQuickDrag)
+
+#include "tst_qquickdrag.moc"
diff --git a/tests/auto/qtquick2/qquickdroparea/qquickdroparea.pro b/tests/auto/qtquick2/qquickdroparea/qquickdroparea.pro
new file mode 100644
index 0000000000..46fe08c145
--- /dev/null
+++ b/tests/auto/qtquick2/qquickdroparea/qquickdroparea.pro
@@ -0,0 +1,9 @@
+TARGET = tst_qquickdroparea
+CONFIG += testcase
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickdroparea.cpp
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/qtquick2/qquickdroparea/tst_qquickdroparea.cpp
new file mode 100644
index 0000000000..f8a081ff21
--- /dev/null
+++ b/tests/auto/qtquick2/qquickdroparea/tst_qquickdroparea.cpp
@@ -0,0 +1,1117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+
+#include <QtGui/qwindowsysteminterface_qpa.h>
+
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ QVariant result = expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result.value<T>();
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
+class tst_QQuickDropArea: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void containsDrag_internal();
+ void containsDrag_external();
+ void keys_internal();
+ void keys_external();
+ void source_internal();
+// void source_external();
+ void position_internal();
+ void position_external();
+ void drop_internal();
+// void drop_external();
+ void simultaneousDrags();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+void tst_QQuickDropArea::initTestCase()
+{
+
+}
+
+void tst_QQuickDropArea::cleanupTestCase()
+{
+
+}
+
+void tst_QQuickDropArea::containsDrag_internal()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool hasDrag: containsDrag\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ dragItem->setPos(QPointF(150, 50));
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ dragItem->setPos(QPointF(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ dragItem->setPos(QPointF(150, 50));
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dragItem, "Drag.active = false");
+}
+
+void tst_QQuickDropArea::containsDrag_external()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool hasDrag: containsDrag\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+ QQuickCanvas alternateCanvas;
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(150, 50));
+}
+
+void tst_QQuickDropArea::keys_internal()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property variant dragKeys\n"
+ "property variant dropKeys: keys\n"
+ "property int enterEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]\n"
+ "}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"blue\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "blue");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"red\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"green\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = [\"red\", \"green\"]");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red" << "green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red" << "green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dragItem, "Drag.keys = []");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = []");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = []");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dragItem, "Drag.keys = [\"red\", \"blue\"]");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+}
+
+void tst_QQuickDropArea::keys_external()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property variant dragKeys\n"
+ "property variant dropKeys: keys\n"
+ "property int enterEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+ QQuickCanvas alternateCanvas;
+
+ data.setData("text/x-red", "red");
+ data.setData("text/x-blue", "blue");
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-blue\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-blue");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-red\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-green\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = [\"text/x-red\", \"text/x-green\"]");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ data.removeFormat("text/x-red");
+ data.removeFormat("text/x-blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = []");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ data.setData("text/x-red", "red");
+ data.setData("text/x-blue", "blue");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(50, 50));
+}
+
+void tst_QQuickDropArea::source_internal()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property Item source: drag.source\n"
+ "property Item eventSource\n"
+ "width: 100; height: 100\n"
+ "onEntered: {eventSource = drag.source}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "Item { id: dragSource; objectName: \"dragSource\" }\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QQuickItem *dragSource = dropArea->findChild<QQuickItem *>("dragSource");
+ QVERIFY(dragSource);
+
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragItem));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragItem));
+ QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragItem));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+
+
+ evaluate<void>(dropArea, "{ eventSource = null }");
+ evaluate<void>(dragItem, "Drag.source = dragSource");
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragSource));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragSource));
+ QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragSource));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+}
+
+// Setting a source can't be emulated using the QWindowSystemInterface API.
+
+//void tst_QQuickDropArea::source_external()
+//{
+//}
+
+void tst_QQuickDropArea::position_internal()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property real dragX: drag.x\n"
+ "property real dragY: drag.y\n"
+ "property real eventX\n"
+ "property real eventY\n"
+ "property int enterEvents: 0\n"
+ "property int moveEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
+ "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 0);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ dragItem->setPos(QPointF(40, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ dragItem->setPos(QPointF(75, 25));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+}
+
+void tst_QQuickDropArea::position_external()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property real dragX: drag.x\n"
+ "property real dragY: drag.y\n"
+ "property real eventX\n"
+ "property real eventY\n"
+ "property int enterEvents: 0\n"
+ "property int moveEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
+ "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(40, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(75, 25));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(75, 25));
+}
+
+void tst_QQuickDropArea::drop_internal()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool accept: false\n"
+ "property bool setAccepted: false\n"
+ "property bool acceptDropAction: false\n"
+ "property bool setDropAction: false\n"
+ "property int dropAction: Qt.IgnoreAction\n"
+ "property int proposedAction: Qt.IgnoreAction\n"
+ "property int supportedActions: Qt.IgnoreAction\n"
+ "property int dropEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onDropped: {\n"
+ "++dropEvents\n"
+ "supportedActions = drop.supportedActions\n"
+ "proposedAction = drop.action\n"
+ "if (setDropAction)\n"
+ "drop.action = dropAction\n"
+ "if (acceptDropAction)\n"
+ "drop.accept(dropAction)\n"
+ "else if (setAccepted)\n"
+ "drop.accepted = accept\n"
+ "else if (accept)\n"
+ "drop.accept()\n"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ accept = true; setDropAction = true; dropAction = Qt.LinkAction }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ accept = false; setAccepted = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false; setDropAction = false; acceptDropAction = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ acceptDropAction = false; dropAction = Qt.IgnoreAction; accept = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false }");
+ evaluate<void>(dragItem, "Drag.supportedActions = Qt.LinkAction");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false }");
+ evaluate<void>(dragItem, "Drag.proposedAction = Qt.LinkAction");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
+}
+
+// Setting the supportedActions can't be emulated using the QWindowSystemInterface API.
+
+//void tst_QQuickDropArea::drop_external()
+//{
+//}
+
+void tst_QQuickDropArea::simultaneousDrags()
+{
+ QQuickCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "keys: [\"red\", \"text/x-red\"]\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "DropArea {\n"
+ "objectName: \"dropArea2\"\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "keys: [\"blue\", \"text/x-blue\"]\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem1\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem2\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]"
+ "}\n"
+ "}", QUrl());
+
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea1 = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea1);
+ dropArea1->setParentItem(canvas.rootItem());
+
+ QQuickItem *dropArea2 = dropArea1->findChild<QQuickItem *>("dropArea2");
+ QVERIFY(dropArea2);
+
+ QQuickItem *dragItem1 = dropArea1->findChild<QQuickItem *>("dragItem1");
+ QVERIFY(dragItem1);
+
+ QQuickItem *dragItem2 = dropArea1->findChild<QQuickItem *>("dragItem2");
+ QVERIFY(dragItem2);
+
+ QMimeData data;
+ data.setData("text/x-red", "red");
+ data.setData("text/x-blue", "blue");
+
+ QQuickCanvas alternateCanvas;
+
+ // Mixed internal drags.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // internal then external.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // external then internal.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // Different acceptance
+ evaluate<void>(dragItem1, "Drag.keys = \"red\"");
+ evaluate<void>(dragItem2, "Drag.keys = \"blue\"");
+ data.removeFormat("text/x-red");
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ // internal then external
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ QWindowSystemInterface::handleDrop(&alternateCanvas, &data, QPoint(50, 50));
+}
+
+QTEST_MAIN(tst_QQuickDropArea)
+
+#include "tst_qquickdroparea.moc"
diff --git a/tests/auto/declarative/qquickflickable/data/disabled.qml b/tests/auto/qtquick2/qquickflickable/data/disabled.qml
index 9b679827c7..9b679827c7 100644
--- a/tests/auto/declarative/qquickflickable/data/disabled.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/disabled.qml
diff --git a/tests/auto/declarative/qquickflickable/data/flickable01.qml b/tests/auto/qtquick2/qquickflickable/data/flickable01.qml
index cbec44bb4f..cbec44bb4f 100644
--- a/tests/auto/declarative/qquickflickable/data/flickable01.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/flickable01.qml
diff --git a/tests/auto/declarative/qquickflickable/data/flickable02.qml b/tests/auto/qtquick2/qquickflickable/data/flickable02.qml
index 80caa32da5..80caa32da5 100644
--- a/tests/auto/declarative/qquickflickable/data/flickable02.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/flickable02.qml
diff --git a/tests/auto/declarative/qquickflickable/data/flickable03.qml b/tests/auto/qtquick2/qquickflickable/data/flickable03.qml
index ebc49ba90a..ebc49ba90a 100644
--- a/tests/auto/declarative/qquickflickable/data/flickable03.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/flickable03.qml
diff --git a/tests/auto/declarative/qquickflickable/data/flickable04.qml b/tests/auto/qtquick2/qquickflickable/data/flickable04.qml
index b2f30b84ec..b2f30b84ec 100644
--- a/tests/auto/declarative/qquickflickable/data/flickable04.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/flickable04.qml
diff --git a/tests/auto/declarative/qquickflickable/data/flickableqgraphicswidget.qml b/tests/auto/qtquick2/qquickflickable/data/flickableqgraphicswidget.qml
index bb8f1eefc6..bb8f1eefc6 100644
--- a/tests/auto/declarative/qquickflickable/data/flickableqgraphicswidget.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/flickableqgraphicswidget.qml
diff --git a/tests/auto/declarative/qquickflickable/data/margins.qml b/tests/auto/qtquick2/qquickflickable/data/margins.qml
index 4866bd8301..4866bd8301 100644
--- a/tests/auto/declarative/qquickflickable/data/margins.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/margins.qml
diff --git a/tests/auto/declarative/qquickflickable/data/nestedPressDelay.qml b/tests/auto/qtquick2/qquickflickable/data/nestedPressDelay.qml
index 60dadcc73c..60dadcc73c 100644
--- a/tests/auto/declarative/qquickflickable/data/nestedPressDelay.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/nestedPressDelay.qml
diff --git a/tests/auto/declarative/qquickflickable/data/resize.qml b/tests/auto/qtquick2/qquickflickable/data/resize.qml
index 1a9ef54107..1a9ef54107 100644
--- a/tests/auto/declarative/qquickflickable/data/resize.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/resize.qml
diff --git a/tests/auto/declarative/qquickflickable/data/wheel.qml b/tests/auto/qtquick2/qquickflickable/data/wheel.qml
index 2928bbcd72..2928bbcd72 100644
--- a/tests/auto/declarative/qquickflickable/data/wheel.qml
+++ b/tests/auto/qtquick2/qquickflickable/data/wheel.qml
diff --git a/tests/auto/qtquick2/qquickflickable/qquickflickable.pro b/tests/auto/qtquick2/qquickflickable/qquickflickable.pro
new file mode 100644
index 0000000000..7376f593fd
--- /dev/null
+++ b/tests/auto/qtquick2/qquickflickable/qquickflickable.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickflickable
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickflickable.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickflickable/tst_qquickflickable.cpp b/tests/auto/qtquick2/qquickflickable/tst_qquickflickable.cpp
new file mode 100644
index 0000000000..1827e0af1c
--- /dev/null
+++ b/tests/auto/qtquick2/qquickflickable/tst_qquickflickable.cpp
@@ -0,0 +1,662 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquickflickable_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include <math.h>
+#include "../../shared/util.h"
+#include <QtOpenGL/QGLShaderProgram>
+
+class tst_qquickflickable : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickflickable();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void create();
+ void horizontalViewportSize();
+ void verticalViewportSize();
+ void properties();
+ void boundsBehavior();
+ void maximumFlickVelocity();
+ void flickDeceleration();
+ void pressDelay();
+ void nestedPressDelay();
+ void flickableDirection();
+ void resizeContent();
+ void returnToBounds();
+ void wheel();
+ void movingAndDragging();
+ void disabled();
+ void flickVelocity();
+ void margins();
+
+private:
+ QDeclarativeEngine engine;
+
+ void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &objectName);
+};
+
+tst_qquickflickable::tst_qquickflickable()
+{
+}
+
+void tst_qquickflickable::initTestCase()
+{
+
+}
+
+void tst_qquickflickable::cleanupTestCase()
+{
+
+}
+
+void tst_qquickflickable::create()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable01.qml")));
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+ QCOMPARE(obj->contentX(), 0.);
+ QCOMPARE(obj->contentY(), 0.);
+
+ QCOMPARE(obj->horizontalVelocity(), 0.);
+ QCOMPARE(obj->verticalVelocity(), 0.);
+
+ QCOMPARE(obj->isInteractive(), true);
+ QCOMPARE(obj->boundsBehavior(), QQuickFlickable::DragAndOvershootBounds);
+ QCOMPARE(obj->pressDelay(), 0);
+ QCOMPARE(obj->maximumFlickVelocity(), 2500.);
+
+ delete obj;
+}
+
+void tst_qquickflickable::horizontalViewportSize()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable02.qml")));
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->contentWidth(), 800.);
+ QCOMPARE(obj->contentHeight(), 300.);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+
+ delete obj;
+}
+
+void tst_qquickflickable::verticalViewportSize()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->contentWidth(), 200.);
+ QCOMPARE(obj->contentHeight(), 1200.);
+ QCOMPARE(obj->isAtXBeginning(), true);
+ QCOMPARE(obj->isAtXEnd(), false);
+ QCOMPARE(obj->isAtYBeginning(), true);
+ QCOMPARE(obj->isAtYEnd(), false);
+
+ delete obj;
+}
+
+void tst_qquickflickable::properties()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("flickable04.qml")));
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->isInteractive(), false);
+ QCOMPARE(obj->boundsBehavior(), QQuickFlickable::StopAtBounds);
+ QCOMPARE(obj->pressDelay(), 200);
+ QCOMPARE(obj->maximumFlickVelocity(), 2000.);
+
+ QVERIFY(obj->property("ok").toBool() == false);
+ QMetaObject::invokeMethod(obj, "check");
+ QVERIFY(obj->property("ok").toBool() == true);
+
+ delete obj;
+}
+
+void tst_qquickflickable::boundsBehavior()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Flickable { boundsBehavior: Flickable.StopAtBounds }", QUrl::fromLocalFile(""));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
+ QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
+
+ QVERIFY(flickable);
+ QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
+
+ flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
+ QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragAndOvershootBounds);
+ QCOMPARE(spy.count(),1);
+ flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
+ QCOMPARE(spy.count(),1);
+
+ flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
+ QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragOverBounds);
+ QCOMPARE(spy.count(),2);
+ flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
+ QCOMPARE(spy.count(),2);
+
+ flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
+ QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
+ QCOMPARE(spy.count(),3);
+ flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
+ QCOMPARE(spy.count(),3);
+}
+
+void tst_qquickflickable::maximumFlickVelocity()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Flickable { maximumFlickVelocity: 1.0; }", QUrl::fromLocalFile(""));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
+ QSignalSpy spy(flickable, SIGNAL(maximumFlickVelocityChanged()));
+
+ QVERIFY(flickable);
+ QCOMPARE(flickable->maximumFlickVelocity(), 1.0);
+
+ flickable->setMaximumFlickVelocity(2.0);
+ QCOMPARE(flickable->maximumFlickVelocity(), 2.0);
+ QCOMPARE(spy.count(),1);
+ flickable->setMaximumFlickVelocity(2.0);
+ QCOMPARE(spy.count(),1);
+}
+
+void tst_qquickflickable::flickDeceleration()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Flickable { flickDeceleration: 1.0; }", QUrl::fromLocalFile(""));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
+ QSignalSpy spy(flickable, SIGNAL(flickDecelerationChanged()));
+
+ QVERIFY(flickable);
+ QCOMPARE(flickable->flickDeceleration(), 1.0);
+
+ flickable->setFlickDeceleration(2.0);
+ QCOMPARE(flickable->flickDeceleration(), 2.0);
+ QCOMPARE(spy.count(),1);
+ flickable->setFlickDeceleration(2.0);
+ QCOMPARE(spy.count(),1);
+}
+
+void tst_qquickflickable::pressDelay()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Flickable { pressDelay: 100; }", QUrl::fromLocalFile(""));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
+ QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
+
+ QVERIFY(flickable);
+ QCOMPARE(flickable->pressDelay(), 100);
+
+ flickable->setPressDelay(200);
+ QCOMPARE(flickable->pressDelay(), 200);
+ QCOMPARE(spy.count(),1);
+ flickable->setPressDelay(200);
+ QCOMPARE(spy.count(),1);
+}
+
+// QTBUG-17361
+void tst_qquickflickable::nestedPressDelay()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("nestedPressDelay.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(canvas->rootObject());
+ QVERIFY(outer != 0);
+
+ QQuickFlickable *inner = canvas->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
+ QVERIFY(inner != 0);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(150, 150));
+ // the MouseArea is not pressed immediately
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ // The outer pressDelay will prevail (50ms, vs. 10sec)
+ // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
+ QTRY_VERIFY(outer->property("pressed").toBool() == true);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(150, 150));
+
+ delete canvas;
+}
+
+void tst_qquickflickable::flickableDirection()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Flickable { flickableDirection: Flickable.VerticalFlick; }", QUrl::fromLocalFile(""));
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
+ QSignalSpy spy(flickable, SIGNAL(flickableDirectionChanged()));
+
+ QVERIFY(flickable);
+ QCOMPARE(flickable->flickableDirection(), QQuickFlickable::VerticalFlick);
+
+ flickable->setFlickableDirection(QQuickFlickable::HorizontalAndVerticalFlick);
+ QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalAndVerticalFlick);
+ QCOMPARE(spy.count(),1);
+
+ flickable->setFlickableDirection(QQuickFlickable::AutoFlickDirection);
+ QCOMPARE(flickable->flickableDirection(), QQuickFlickable::AutoFlickDirection);
+ QCOMPARE(spy.count(),2);
+
+ flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
+ QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
+ QCOMPARE(spy.count(),3);
+
+ flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
+ QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
+ QCOMPARE(spy.count(),3);
+}
+
+// QtQuick 1.1
+void tst_qquickflickable::resizeContent()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("resize.qml")));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->contentX(), 0.);
+ QCOMPARE(obj->contentY(), 0.);
+ QCOMPARE(obj->contentWidth(), 300.);
+ QCOMPARE(obj->contentHeight(), 300.);
+
+ QMetaObject::invokeMethod(root, "resizeContent");
+
+ QCOMPARE(obj->contentX(), 100.);
+ QCOMPARE(obj->contentY(), 100.);
+ QCOMPARE(obj->contentWidth(), 600.);
+ QCOMPARE(obj->contentHeight(), 600.);
+
+ delete root;
+}
+
+// QtQuick 1.1
+void tst_qquickflickable::returnToBounds()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("resize.qml")));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->contentX(), 0.);
+ QCOMPARE(obj->contentY(), 0.);
+ QCOMPARE(obj->contentWidth(), 300.);
+ QCOMPARE(obj->contentHeight(), 300.);
+
+ obj->setContentX(100);
+ obj->setContentY(400);
+ QTRY_COMPARE(obj->contentX(), 100.);
+ QTRY_COMPARE(obj->contentY(), 400.);
+
+ QMetaObject::invokeMethod(root, "returnToBounds");
+
+ QTRY_COMPARE(obj->contentX(), 0.);
+ QTRY_COMPARE(obj->contentY(), 0.);
+
+ delete root;
+}
+
+void tst_qquickflickable::wheel()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("wheel.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flick");
+ QVERIFY(flick != 0);
+
+ {
+ QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
+ event.setAccepted(false);
+ QApplication::sendEvent(canvas, &event);
+ }
+
+ QTRY_VERIFY(flick->contentY() > 0);
+ QVERIFY(flick->contentX() == 0);
+
+ flick->setContentY(0);
+ QVERIFY(flick->contentY() == 0);
+
+ {
+ QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Horizontal);
+ event.setAccepted(false);
+ QApplication::sendEvent(canvas, &event);
+ }
+
+ QTRY_VERIFY(flick->contentX() > 0);
+ QVERIFY(flick->contentY() == 0);
+
+ delete canvas;
+}
+
+void tst_qquickflickable::movingAndDragging()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ QSignalSpy vDragSpy(flickable, SIGNAL(draggingVerticallyChanged()));
+ QSignalSpy hDragSpy(flickable, SIGNAL(draggingHorizontallyChanged()));
+ QSignalSpy dragSpy(flickable, SIGNAL(draggingChanged()));
+ QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
+ QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
+ QSignalSpy moveSpy(flickable, SIGNAL(movingChanged()));
+ QSignalSpy dragStartSpy(flickable, SIGNAL(dragStarted()));
+ QSignalSpy dragEndSpy(flickable, SIGNAL(dragEnded()));
+
+ //Vertical
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
+
+ QTest::mouseMove(canvas, QPoint(50, 80));
+ QTest::mouseMove(canvas, QPoint(50, 70));
+ QTest::mouseMove(canvas, QPoint(50, 60));
+
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(50, 80), Qt::LeftButton, Qt::LeftButton, 0);
+
+ QVERIFY(!flickable->isDraggingHorizontally());
+ QVERIFY(flickable->isDraggingVertically());
+ QVERIFY(flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 1);
+ QCOMPARE(dragSpy.count(), 1);
+ QCOMPARE(hDragSpy.count(), 0);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 0);
+
+ QVERIFY(!flickable->isMovingHorizontally());
+ QVERIFY(flickable->isMovingVertically());
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(vMoveSpy.count(), 1);
+ QCOMPARE(moveSpy.count(), 1);
+ QCOMPARE(hMoveSpy.count(), 0);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
+
+ QTRY_VERIFY(!flickable->isDraggingVertically());
+ QVERIFY(!flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 2);
+ QCOMPARE(dragSpy.count(), 2);
+ QCOMPARE(hDragSpy.count(), 0);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 1);
+
+ // wait for any motion to end
+ QTRY_VERIFY(flickable->isMoving() == false);
+
+ //Horizontal
+ vDragSpy.clear();
+ hDragSpy.clear();
+ dragSpy.clear();
+ vMoveSpy.clear();
+ hMoveSpy.clear();
+ moveSpy.clear();
+ dragStartSpy.clear();
+ dragEndSpy.clear();
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(90, 50));
+
+ QTest::mouseMove(canvas, QPoint(80, 50));
+ QTest::mouseMove(canvas, QPoint(70, 50));
+ QTest::mouseMove(canvas, QPoint(60, 50));
+
+ QVERIFY(flickable->isDraggingHorizontally());
+ QVERIFY(flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 0);
+ QCOMPARE(dragSpy.count(), 1);
+ QCOMPARE(hDragSpy.count(), 1);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 0);
+
+ QVERIFY(!flickable->isMovingVertically());
+ QVERIFY(flickable->isMovingHorizontally());
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(vMoveSpy.count(), 0);
+ QCOMPARE(moveSpy.count(), 1);
+ QCOMPARE(hMoveSpy.count(), 1);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(60, 50));
+
+ QTRY_VERIFY(!flickable->isDraggingHorizontally());
+ QVERIFY(!flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 0);
+ QCOMPARE(dragSpy.count(), 2);
+ QCOMPARE(hDragSpy.count(), 2);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 1);
+
+ // Don't test moving because a flick could occur
+
+ delete canvas;
+}
+
+void tst_qquickflickable::disabled()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("disabled.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flickable");
+ QVERIFY(flick != 0);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
+
+ QTest::mouseMove(canvas, QPoint(50, 80));
+ QTest::mouseMove(canvas, QPoint(50, 70));
+ QTest::mouseMove(canvas, QPoint(50, 60));
+
+ QVERIFY(flick->isMoving() == false);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
+
+ // verify that mouse clicks on other elements still work (QTBUG-20584)
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 10));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10));
+
+ QTRY_VERIFY(canvas->rootObject()->property("clicked").toBool() == true);
+}
+
+void tst_qquickflickable::flickVelocity()
+{
+#ifdef Q_OS_MAC
+ QSKIP("Producing flicks on Mac CI impossible due to timing problems");
+#endif
+
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("flickable03.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ // flick up
+ flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
+ QVERIFY(flickable->verticalVelocity() > 0.0);
+ QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+ // flick down
+ flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
+ QVERIFY(flickable->verticalVelocity() < 0.0);
+ QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
+
+ delete canvas;
+}
+
+void tst_qquickflickable::margins()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("margins.qml")));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
+ QVERIFY(obj != 0);
+
+ // starting state
+ QCOMPARE(obj->contentX(), -40.);
+ QCOMPARE(obj->contentY(), -20.);
+ QCOMPARE(obj->contentWidth(), 1600.);
+ QCOMPARE(obj->contentHeight(), 600.);
+ QCOMPARE(obj->xOrigin(), 0.);
+ QCOMPARE(obj->yOrigin(), 0.);
+
+ // Reduce left margin
+ obj->setLeftMargin(30);
+ QTRY_COMPARE(obj->contentX(), -30.);
+
+ // Reduce top margin
+ obj->setTopMargin(20);
+ QTRY_COMPARE(obj->contentY(), -20.);
+
+ // position to the far right, including margin
+ obj->setContentX(1600 + 50 - obj->width());
+ obj->returnToBounds();
+ QTest::qWait(200);
+ QCOMPARE(obj->contentX(), 1600. + 50. - obj->width());
+
+ // position beyond the far right, including margin
+ obj->setContentX(1600 + 50 - obj->width() + 1.);
+ obj->returnToBounds();
+ QTRY_COMPARE(obj->contentX(), 1600. + 50. - obj->width());
+
+ // Reduce right margin
+ obj->setRightMargin(40);
+ QTRY_COMPARE(obj->contentX(), 1600. + 40. - obj->width());
+ QCOMPARE(obj->contentWidth(), 1600.);
+
+ // position to the far bottom, including margin
+ obj->setContentY(600 + 30 - obj->height());
+ obj->returnToBounds();
+ QTest::qWait(200);
+ QCOMPARE(obj->contentY(), 600. + 30. - obj->height());
+
+ // position beyond the far bottom, including margin
+ obj->setContentY(600 + 30 - obj->height() + 1.);
+ obj->returnToBounds();
+ QTRY_COMPARE(obj->contentY(), 600. + 30. - obj->height());
+
+ // Reduce bottom margin
+ obj->setBottomMargin(20);
+ QTRY_COMPARE(obj->contentY(), 600. + 20. - obj->height());
+ QCOMPARE(obj->contentHeight(), 600.);
+
+ delete root;
+}
+
+void tst_qquickflickable::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+ const int pointCount = 5;
+ QPoint diff = to - from;
+
+ // send press, five equally spaced moves, and release.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+ for (int i = 0; i < pointCount; ++i) {
+ QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ QTest::qWait(duration/pointCount);
+ QCoreApplication::processEvents();
+ }
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
+template<typename T>
+T *tst_qquickflickable::findItem(QQuickItem *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ return static_cast<T*>(item);
+ }
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_qquickflickable)
+
+#include "tst_qquickflickable.moc"
diff --git a/tests/auto/declarative/qquickflipable/data/crash.qml b/tests/auto/qtquick2/qquickflipable/data/crash.qml
index a0327918cb..a0327918cb 100644
--- a/tests/auto/declarative/qquickflipable/data/crash.qml
+++ b/tests/auto/qtquick2/qquickflipable/data/crash.qml
diff --git a/tests/auto/declarative/qquickflipable/data/flipable-abort.qml b/tests/auto/qtquick2/qquickflipable/data/flipable-abort.qml
index 90fc03a5f9..90fc03a5f9 100644
--- a/tests/auto/declarative/qquickflipable/data/flipable-abort.qml
+++ b/tests/auto/qtquick2/qquickflipable/data/flipable-abort.qml
diff --git a/tests/auto/declarative/qquickflipable/data/test-flipable.qml b/tests/auto/qtquick2/qquickflipable/data/test-flipable.qml
index dff6d3fe39..dff6d3fe39 100644
--- a/tests/auto/declarative/qquickflipable/data/test-flipable.qml
+++ b/tests/auto/qtquick2/qquickflipable/data/test-flipable.qml
diff --git a/tests/auto/qtquick2/qquickflipable/qquickflipable.pro b/tests/auto/qtquick2/qquickflipable/qquickflipable.pro
new file mode 100644
index 0000000000..532c42f79b
--- /dev/null
+++ b/tests/auto/qtquick2/qquickflipable/qquickflipable.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickflipable
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickflipable.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickflipable/tst_qquickflipable.cpp b/tests/auto/qtquick2/qquickflipable/tst_qquickflipable.cpp
new file mode 100644
index 0000000000..a217e26714
--- /dev/null
+++ b/tests/auto/qtquick2/qquickflipable/tst_qquickflipable.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquickflipable_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include <QFontMetrics>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <math.h>
+#include <QtOpenGL/QGLShaderProgram>
+#include "../../shared/util.h"
+
+class tst_qquickflipable : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickflipable();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void create();
+ void checkFrontAndBack();
+ void setFrontAndBack();
+
+ // below here task issues
+ void QTBUG_9161_crash();
+ void QTBUG_8474_qgv_abort();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+tst_qquickflipable::tst_qquickflipable()
+{
+}
+void tst_qquickflipable::initTestCase()
+{
+}
+
+void tst_qquickflipable::cleanupTestCase()
+{
+
+}
+
+void tst_qquickflipable::create()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
+ QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ delete obj;
+}
+
+void tst_qquickflipable::checkFrontAndBack()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
+ QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->front() != 0);
+ QVERIFY(obj->back() != 0);
+ delete obj;
+}
+
+void tst_qquickflipable::setFrontAndBack()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("test-flipable.qml")));
+ QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->front() != 0);
+ QVERIFY(obj->back() != 0);
+
+ QString message = c.url().toString() + ":3:1: QML Flipable: front is a write-once property";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ obj->setFront(new QQuickRectangle());
+
+ message = c.url().toString() + ":3:1: QML Flipable: back is a write-once property";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ obj->setBack(new QQuickRectangle());
+ delete obj;
+}
+
+void tst_qquickflipable::QTBUG_9161_crash()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("crash.qml")));
+ QQuickItem *root = canvas->rootObject();
+ QVERIFY(root != 0);
+ canvas->show();
+ delete canvas;
+}
+
+void tst_qquickflipable::QTBUG_8474_qgv_abort()
+{
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("flipable-abort.qml")));
+ QQuickItem *root = canvas->rootObject();
+ QVERIFY(root != 0);
+ canvas->show();
+ delete canvas;
+}
+
+QTEST_MAIN(tst_qquickflipable)
+
+#include "tst_qquickflipable.moc"
diff --git a/tests/auto/declarative/qquickfocusscope/data/canvasFocus.qml b/tests/auto/qtquick2/qquickfocusscope/data/canvasFocus.qml
index 7d8dac5a22..7d8dac5a22 100644
--- a/tests/auto/declarative/qquickfocusscope/data/canvasFocus.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/canvasFocus.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/chain.qml b/tests/auto/qtquick2/qquickfocusscope/data/chain.qml
index 4b96662318..4b96662318 100644
--- a/tests/auto/declarative/qquickfocusscope/data/chain.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/chain.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/forceActiveFocus.qml b/tests/auto/qtquick2/qquickfocusscope/data/forceActiveFocus.qml
index 74d2106888..74d2106888 100644
--- a/tests/auto/declarative/qquickfocusscope/data/forceActiveFocus.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/forceActiveFocus.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/forcefocus.qml b/tests/auto/qtquick2/qquickfocusscope/data/forcefocus.qml
index f41582a951..f41582a951 100644
--- a/tests/auto/declarative/qquickfocusscope/data/forcefocus.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/forcefocus.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/qtBug13380.qml b/tests/auto/qtquick2/qquickfocusscope/data/qtBug13380.qml
index 29de046b38..29de046b38 100644
--- a/tests/auto/declarative/qquickfocusscope/data/qtBug13380.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/qtBug13380.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/signalEmission.qml b/tests/auto/qtquick2/qquickfocusscope/data/signalEmission.qml
index 999a40c5ad..999a40c5ad 100644
--- a/tests/auto/declarative/qquickfocusscope/data/signalEmission.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/signalEmission.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/test.qml b/tests/auto/qtquick2/qquickfocusscope/data/test.qml
index 67be29c3fb..67be29c3fb 100644
--- a/tests/auto/declarative/qquickfocusscope/data/test.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/test.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/test2.qml b/tests/auto/qtquick2/qquickfocusscope/data/test2.qml
index ad74f3e9f4..ad74f3e9f4 100644
--- a/tests/auto/declarative/qquickfocusscope/data/test2.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/test2.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/test3.qml b/tests/auto/qtquick2/qquickfocusscope/data/test3.qml
index 537c30816e..537c30816e 100644
--- a/tests/auto/declarative/qquickfocusscope/data/test3.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/test3.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/test4.qml b/tests/auto/qtquick2/qquickfocusscope/data/test4.qml
index 0eea649f5d..0eea649f5d 100644
--- a/tests/auto/declarative/qquickfocusscope/data/test4.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/test4.qml
diff --git a/tests/auto/declarative/qquickfocusscope/data/test5.qml b/tests/auto/qtquick2/qquickfocusscope/data/test5.qml
index 9c37cd1303..9c37cd1303 100644
--- a/tests/auto/declarative/qquickfocusscope/data/test5.qml
+++ b/tests/auto/qtquick2/qquickfocusscope/data/test5.qml
diff --git a/tests/auto/qtquick2/qquickfocusscope/qquickfocusscope.pro b/tests/auto/qtquick2/qquickfocusscope/qquickfocusscope.pro
new file mode 100644
index 0000000000..138750db3c
--- /dev/null
+++ b/tests/auto/qtquick2/qquickfocusscope/qquickfocusscope.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_qquickfocusscope
+SOURCES += tst_qquickfocusscope.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickfocusscope/tst_qquickfocusscope.cpp b/tests/auto/qtquick2/qquickfocusscope/tst_qquickfocusscope.cpp
new file mode 100644
index 0000000000..11cc7a15e0
--- /dev/null
+++ b/tests/auto/qtquick2/qquickfocusscope/tst_qquickfocusscope.cpp
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QSignalSpy>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qquicktextedit_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickfocusscope_p.h>
+#include "../../shared/util.h"
+
+class tst_qquickfocusscope : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickfocusscope() {}
+
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &id);
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void basic();
+ void nested();
+ void noFocus();
+ void textEdit();
+ void forceFocus();
+ void noParentFocus();
+ void signalEmission();
+ void qtBug13380();
+ void forceActiveFocus();
+ void canvasFocus();
+};
+void tst_qquickfocusscope::initTestCase()
+{
+}
+
+void tst_qquickfocusscope::cleanupTestCase()
+{
+
+}
+
+/*
+ Find an item with the specified id.
+*/
+template<typename T>
+T *tst_qquickfocusscope::findItem(QQuickItem *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ QList<QQuickItem *> children = parent->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QQuickItem *item = children.at(i);
+ if (item) {
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ return static_cast<T*>(item);
+ }
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+ }
+ return 0;
+}
+
+void tst_qquickfocusscope::basic()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("test.qml")));
+
+ QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
+ QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
+ QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
+ QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
+ QVERIFY(item0 != 0);
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVERIFY(view->isTopLevel());
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Right);
+ QTest::qWait(50);
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == true);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Down);
+ QTest::qWait(50);
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == true);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::nested()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("test2.qml")));
+
+ QQuickFocusScope *item1 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item1"));
+ QQuickFocusScope *item2 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item2"));
+ QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
+ QQuickFocusScope *item4 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item4"));
+ QQuickFocusScope *item5 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item5"));
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+ QVERIFY(item4 != 0);
+ QVERIFY(item5 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == true);
+ QVERIFY(item3->hasActiveFocus() == true);
+ QVERIFY(item4->hasActiveFocus() == true);
+ QVERIFY(item5->hasActiveFocus() == true);
+ delete view;
+}
+
+void tst_qquickfocusscope::noFocus()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("test4.qml")));
+
+ QQuickRectangle *item0 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item0"));
+ QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
+ QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
+ QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
+ QVERIFY(item0 != 0);
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Right);
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Down);
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::textEdit()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("test5.qml")));
+
+ QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
+ QQuickTextEdit *item1 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item1"));
+ QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
+ QQuickTextEdit *item3 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item3"));
+ QVERIFY(item0 != 0);
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Right);
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Right);
+ QTest::keyClick(view, Qt::Key_Right);
+ QTest::keyClick(view, Qt::Key_Right);
+ QTest::keyClick(view, Qt::Key_Right);
+ QTest::keyClick(view, Qt::Key_Right);
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == true);
+ QVERIFY(item3->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_Down);
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == true);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::forceFocus()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("forcefocus.qml")));
+
+ QQuickFocusScope *item0 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item0"));
+ QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
+ QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
+ QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
+ QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
+ QQuickRectangle *item5 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item5"));
+ QVERIFY(item0 != 0);
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+ QVERIFY(item4 != 0);
+ QVERIFY(item5 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item4->hasActiveFocus() == false);
+ QVERIFY(item5->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_4);
+ QVERIFY(item0->hasActiveFocus() == true);
+ QVERIFY(item1->hasActiveFocus() == true);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == false);
+ QVERIFY(item4->hasActiveFocus() == false);
+ QVERIFY(item5->hasActiveFocus() == false);
+
+ QTest::keyClick(view, Qt::Key_5);
+ QVERIFY(item0->hasActiveFocus() == false);
+ QVERIFY(item1->hasActiveFocus() == false);
+ QVERIFY(item2->hasActiveFocus() == false);
+ QVERIFY(item3->hasActiveFocus() == true);
+ QVERIFY(item4->hasActiveFocus() == false);
+ QVERIFY(item5->hasActiveFocus() == true);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::noParentFocus()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("chain.qml")));
+ QVERIFY(view->rootObject());
+
+ view->show();
+ view->requestActivateWindow();
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVERIFY(view->rootObject()->property("focus1") == false);
+ QVERIFY(view->rootObject()->property("focus2") == false);
+ QVERIFY(view->rootObject()->property("focus3") == true);
+ QVERIFY(view->rootObject()->property("focus4") == true);
+ QVERIFY(view->rootObject()->property("focus5") == true);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::signalEmission()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("signalEmission.qml")));
+
+ QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
+ QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
+ QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
+ QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
+ QVERIFY(item1 != 0);
+ QVERIFY(item2 != 0);
+ QVERIFY(item3 != 0);
+ QVERIFY(item4 != 0);
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QVariant blue(QColor("blue"));
+ QVariant red(QColor("red"));
+
+ item1->setFocus(true);
+ QCOMPARE(item1->property("color"), red);
+ QCOMPARE(item2->property("color"), blue);
+ QCOMPARE(item3->property("color"), blue);
+ QCOMPARE(item4->property("color"), blue);
+
+ item2->setFocus(true);
+ QCOMPARE(item1->property("color"), blue);
+ QCOMPARE(item2->property("color"), red);
+ QCOMPARE(item3->property("color"), blue);
+ QCOMPARE(item4->property("color"), blue);
+
+ item3->setFocus(true);
+ QCOMPARE(item1->property("color"), blue);
+ QCOMPARE(item2->property("color"), red);
+ QCOMPARE(item3->property("color"), red);
+ QCOMPARE(item4->property("color"), blue);
+
+ item4->setFocus(true);
+ QCOMPARE(item1->property("color"), blue);
+ QCOMPARE(item2->property("color"), red);
+ QCOMPARE(item3->property("color"), blue);
+ QCOMPARE(item4->property("color"), red);
+
+ item4->setFocus(false);
+ QCOMPARE(item1->property("color"), blue);
+ QCOMPARE(item2->property("color"), red);
+ QCOMPARE(item3->property("color"), blue);
+ QCOMPARE(item4->property("color"), blue);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::qtBug13380()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("qtBug13380.qml")));
+
+ view->show();
+ QVERIFY(view->rootObject());
+ view->requestActivateWindow();
+ qApp->processEvents();
+
+ QTest::qWaitForWindowShown(view);
+
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+ QVERIFY(view->rootObject()->property("noFocus").toBool());
+
+ view->rootObject()->setProperty("showRect", true);
+ QVERIFY(view->rootObject()->property("noFocus").toBool());
+
+ delete view;
+}
+
+void tst_qquickfocusscope::forceActiveFocus()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("forceActiveFocus.qml")));
+
+ view->show();
+ view->requestActivateWindow();
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ QQuickItem *rootObject = view->rootObject();
+ QVERIFY(rootObject);
+
+ QQuickItem *scope = findItem<QQuickItem>(rootObject, QLatin1String("scope"));
+ QQuickItem *itemA1 = findItem<QQuickItem>(rootObject, QLatin1String("item-a1"));
+ QQuickItem *scopeA = findItem<QQuickItem>(rootObject, QLatin1String("scope-a"));
+ QQuickItem *itemA2 = findItem<QQuickItem>(rootObject, QLatin1String("item-a2"));
+ QQuickItem *itemB1 = findItem<QQuickItem>(rootObject, QLatin1String("item-b1"));
+ QQuickItem *scopeB = findItem<QQuickItem>(rootObject, QLatin1String("scope-b"));
+ QQuickItem *itemB2 = findItem<QQuickItem>(rootObject, QLatin1String("item-b2"));
+
+ QVERIFY(scope);
+ QVERIFY(itemA1);
+ QVERIFY(scopeA);
+ QVERIFY(itemA2);
+ QVERIFY(itemB1);
+ QVERIFY(scopeB);
+ QVERIFY(itemB2);
+
+ QSignalSpy rootSpy(rootObject, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy scopeSpy(scope, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy scopeASpy(scopeA, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy scopeBSpy(scopeB, SIGNAL(activeFocusChanged(bool)));
+
+ // First, walk the focus from item-a1 down to item-a2 and back again
+ itemA1->forceActiveFocus();
+ QVERIFY(itemA1->hasActiveFocus());
+ QVERIFY(!rootObject->hasActiveFocus());
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ scopeA->forceActiveFocus();
+ QVERIFY(!itemA1->hasActiveFocus());
+ QVERIFY(scopeA->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 1);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ itemA2->forceActiveFocus();
+ QVERIFY(!itemA1->hasActiveFocus());
+ QVERIFY(itemA2->hasActiveFocus());
+ QVERIFY(scopeA->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 1);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ scopeA->forceActiveFocus();
+ QVERIFY(!itemA1->hasActiveFocus());
+ QVERIFY(itemA2->hasActiveFocus());
+ QVERIFY(scopeA->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 1);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ itemA1->forceActiveFocus();
+ QVERIFY(itemA1->hasActiveFocus());
+ QVERIFY(!scopeA->hasActiveFocus());
+ QVERIFY(!itemA2->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 2);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ // Then jump back and forth between branch 'a' and 'b'
+ itemB1->forceActiveFocus();
+ QVERIFY(itemB1->hasActiveFocus());
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ scopeA->forceActiveFocus();
+ QVERIFY(!itemA1->hasActiveFocus());
+ QVERIFY(!itemB1->hasActiveFocus());
+ QVERIFY(scopeA->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 3);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ scopeB->forceActiveFocus();
+ QVERIFY(!scopeA->hasActiveFocus());
+ QVERIFY(!itemB1->hasActiveFocus());
+ QVERIFY(scopeB->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 4);
+ QCOMPARE(scopeBSpy.count(), 1);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ itemA2->forceActiveFocus();
+ QVERIFY(!scopeB->hasActiveFocus());
+ QVERIFY(itemA2->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 5);
+ QCOMPARE(scopeBSpy.count(), 2);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ itemB2->forceActiveFocus();
+ QVERIFY(!itemA2->hasActiveFocus());
+ QVERIFY(itemB2->hasActiveFocus());
+ QCOMPARE(scopeASpy.count(), 6);
+ QCOMPARE(scopeBSpy.count(), 3);
+ QCOMPARE(rootSpy.count(), 0);
+ QCOMPARE(scopeSpy.count(), 1);
+
+ delete view;
+}
+
+void tst_qquickfocusscope::canvasFocus()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(QUrl::fromLocalFile(TESTDATA("canvasFocus.qml")));
+
+ QQuickView alternateView;
+
+ QQuickItem *rootObject = view->rootObject();
+ QVERIFY(rootObject);
+
+ QQuickItem *rootItem = view->rootItem();
+ QQuickItem *scope1 = findItem<QQuickItem>(rootObject, QLatin1String("scope1"));
+ QQuickItem *item1 = findItem<QQuickItem>(rootObject, QLatin1String("item1"));
+ QQuickItem *scope2 = findItem<QQuickItem>(rootObject, QLatin1String("scope2"));
+ QQuickItem *item2 = findItem<QQuickItem>(rootObject, QLatin1String("item2"));
+
+ QVERIFY(scope1);
+ QVERIFY(item1);
+ QVERIFY(scope2);
+ QVERIFY(item2);
+
+ QSignalSpy rootFocusSpy(rootItem, SIGNAL(focusChanged(bool)));
+ QSignalSpy scope1FocusSpy(scope1, SIGNAL(focusChanged(bool)));
+ QSignalSpy item1FocusSpy(item1, SIGNAL(focusChanged(bool)));
+ QSignalSpy scope2FocusSpy(scope2, SIGNAL(focusChanged(bool)));
+ QSignalSpy item2FocusSpy(item2, SIGNAL(focusChanged(bool)));
+ QSignalSpy rootActiveFocusSpy(rootItem, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy scope1ActiveFocusSpy(scope1, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy item1ActiveFocusSpy(item1, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy scope2ActiveFocusSpy(scope2, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy item2ActiveFocusSpy(item2, SIGNAL(activeFocusChanged(bool)));
+
+ QEXPECT_FAIL("", "QTBUG-22415", Abort);
+ QCOMPARE(rootItem->hasFocus(), false);
+ QCOMPARE(rootItem->hasActiveFocus(), false);
+ QCOMPARE(scope1->hasFocus(), true);
+ QCOMPARE(scope1->hasActiveFocus(), false);
+ QCOMPARE(item1->hasFocus(), true);
+ QCOMPARE(item1->hasActiveFocus(), false);
+ QCOMPARE(scope2->hasFocus(), false);
+ QCOMPARE(scope2->hasActiveFocus(), false);
+ QCOMPARE(item2->hasFocus(), false);
+ QCOMPARE(item2->hasActiveFocus(), false);
+
+ view->show();
+ view->requestActivateWindow();
+
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(view == qGuiApp->focusWindow());
+
+ // Now the canvas has focus, active focus given to item1
+ QCOMPARE(rootItem->hasFocus(), true);
+ QCOMPARE(rootItem->hasActiveFocus(), true);
+ QCOMPARE(scope1->hasFocus(), true);
+ QCOMPARE(scope1->hasActiveFocus(), true);
+ QCOMPARE(item1->hasFocus(), true);
+ QCOMPARE(item1->hasActiveFocus(), true);
+ QCOMPARE(scope2->hasFocus(), false);
+ QCOMPARE(scope2->hasActiveFocus(), false);
+ QCOMPARE(item2->hasFocus(), false);
+ QCOMPARE(item2->hasActiveFocus(), false);
+
+ QCOMPARE(rootFocusSpy.count(), 1);
+ QCOMPARE(rootActiveFocusSpy.count(), 1);
+ QCOMPARE(scope1FocusSpy.count(), 0);
+ QCOMPARE(scope1ActiveFocusSpy.count(), 1);
+ QCOMPARE(item1FocusSpy.count(), 0);
+ QCOMPARE(item1ActiveFocusSpy.count(), 1);
+
+
+ // view->hide(); // seemingly doesn't remove focus, so have an another view steal it.
+ alternateView.show();
+ alternateView.requestActivateWindow();
+ QTest::qWaitForWindowShown(&alternateView);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &alternateView);
+
+ QCOMPARE(rootItem->hasFocus(), false);
+ QCOMPARE(rootItem->hasActiveFocus(), false);
+ QCOMPARE(scope1->hasFocus(), true);
+ QCOMPARE(scope1->hasActiveFocus(), false);
+ QCOMPARE(item1->hasFocus(), true);
+ QCOMPARE(item1->hasActiveFocus(), false);
+
+ QCOMPARE(rootFocusSpy.count(), 2);
+ QCOMPARE(rootActiveFocusSpy.count(), 2);
+ QCOMPARE(scope1FocusSpy.count(), 0);
+ QCOMPARE(scope1ActiveFocusSpy.count(), 2);
+ QCOMPARE(item1FocusSpy.count(), 0);
+ QCOMPARE(item1ActiveFocusSpy.count(), 2);
+
+
+ // canvas does not have focus, so item2 will not get active focus
+ item2->forceActiveFocus();
+
+ QCOMPARE(rootItem->hasFocus(), false);
+ QCOMPARE(rootItem->hasActiveFocus(), false);
+ QCOMPARE(scope1->hasFocus(), false);
+ QCOMPARE(scope1->hasActiveFocus(), false);
+ QCOMPARE(item1->hasFocus(), true);
+ QCOMPARE(item1->hasActiveFocus(), false);
+ QCOMPARE(scope2->hasFocus(), true);
+ QCOMPARE(scope2->hasActiveFocus(), false);
+ QCOMPARE(item2->hasFocus(), true);
+ QCOMPARE(item2->hasActiveFocus(), false);
+
+ QCOMPARE(rootFocusSpy.count(), 2);
+ QCOMPARE(rootActiveFocusSpy.count(), 2);
+ QCOMPARE(scope1FocusSpy.count(), 1);
+ QCOMPARE(scope1ActiveFocusSpy.count(), 2);
+ QCOMPARE(item1FocusSpy.count(), 0);
+ QCOMPARE(item1ActiveFocusSpy.count(), 2);
+ QCOMPARE(scope2FocusSpy.count(), 1);
+ QCOMPARE(scope2ActiveFocusSpy.count(), 0);
+ QCOMPARE(item2FocusSpy.count(), 1);
+ QCOMPARE(item2ActiveFocusSpy.count(), 0);
+
+ // give the canvas focus, and item2 will get active focus
+ view->show();
+ view->requestActivateWindow();
+ QTest::qWaitForWindowShown(view);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == view);
+
+ QCOMPARE(rootItem->hasFocus(), true);
+ QCOMPARE(rootItem->hasActiveFocus(), true);
+ QCOMPARE(scope2->hasFocus(), true);
+ QCOMPARE(scope2->hasActiveFocus(), true);
+ QCOMPARE(item2->hasFocus(), true);
+ QCOMPARE(item2->hasActiveFocus(), true);
+ QCOMPARE(rootFocusSpy.count(), 3);
+ QCOMPARE(rootActiveFocusSpy.count(), 3);
+ QCOMPARE(scope2FocusSpy.count(), 1);
+ QCOMPARE(scope2ActiveFocusSpy.count(), 1);
+ QCOMPARE(item2FocusSpy.count(), 1);
+ QCOMPARE(item2ActiveFocusSpy.count(), 1);
+
+ delete view;
+}
+
+QTEST_MAIN(tst_qquickfocusscope)
+
+#include "tst_qquickfocusscope.moc"
diff --git a/tests/auto/declarative/qquickgridview/data/ComponentView.qml b/tests/auto/qtquick2/qquickgridview/data/ComponentView.qml
index 12ab6c92d1..12ab6c92d1 100644
--- a/tests/auto/declarative/qquickgridview/data/ComponentView.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/ComponentView.qml
diff --git a/tests/auto/declarative/qquickgridview/data/asyncloader.qml b/tests/auto/qtquick2/qquickgridview/data/asyncloader.qml
index ab66f20a1e..ab66f20a1e 100644
--- a/tests/auto/declarative/qquickgridview/data/asyncloader.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/asyncloader.qml
diff --git a/tests/auto/declarative/qquickgridview/data/attachedSignals.qml b/tests/auto/qtquick2/qquickgridview/data/attachedSignals.qml
index 73c10d8caf..73c10d8caf 100644
--- a/tests/auto/declarative/qquickgridview/data/attachedSignals.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/attachedSignals.qml
diff --git a/tests/auto/declarative/qquickgridview/data/creationContext.qml b/tests/auto/qtquick2/qquickgridview/data/creationContext.qml
index 79a682788b..79a682788b 100644
--- a/tests/auto/declarative/qquickgridview/data/creationContext.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/creationContext.qml
diff --git a/tests/auto/declarative/qquickgridview/data/displaygrid.qml b/tests/auto/qtquick2/qquickgridview/data/displaygrid.qml
index 1da4fe50ac..1da4fe50ac 100644
--- a/tests/auto/declarative/qquickgridview/data/displaygrid.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/displaygrid.qml
diff --git a/tests/auto/declarative/qquickgridview/data/footer.qml b/tests/auto/qtquick2/qquickgridview/data/footer.qml
index 9083f9f57c..9083f9f57c 100644
--- a/tests/auto/declarative/qquickgridview/data/footer.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/footer.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview-enforcerange.qml b/tests/auto/qtquick2/qquickgridview/data/gridview-enforcerange.qml
index 2bfe7da78e..2bfe7da78e 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview-enforcerange.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview-enforcerange.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview-initCurrent.qml b/tests/auto/qtquick2/qquickgridview/data/gridview-initCurrent.qml
index 624f639962..624f639962 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview-initCurrent.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview-initCurrent.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview-noCurrent.qml b/tests/auto/qtquick2/qquickgridview/data/gridview-noCurrent.qml
index 600716e2d4..600716e2d4 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview-noCurrent.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview-noCurrent.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview1.qml b/tests/auto/qtquick2/qquickgridview/data/gridview1.qml
index 4bf6f0b952..4bf6f0b952 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview1.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview1.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview2.qml b/tests/auto/qtquick2/qquickgridview/data/gridview2.qml
index 5fb45a1613..5fb45a1613 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview2.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview2.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview3.qml b/tests/auto/qtquick2/qquickgridview/data/gridview3.qml
index a8c1c5a0f7..a8c1c5a0f7 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview3.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview3.qml
diff --git a/tests/auto/declarative/qquickgridview/data/gridview4.qml b/tests/auto/qtquick2/qquickgridview/data/gridview4.qml
index eed3a2bdb1..eed3a2bdb1 100644
--- a/tests/auto/declarative/qquickgridview/data/gridview4.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/gridview4.qml
diff --git a/tests/auto/declarative/qquickgridview/data/header.qml b/tests/auto/qtquick2/qquickgridview/data/header.qml
index 648e2a2298..648e2a2298 100644
--- a/tests/auto/declarative/qquickgridview/data/header.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/header.qml
diff --git a/tests/auto/declarative/qquickgridview/data/manual-highlight.qml b/tests/auto/qtquick2/qquickgridview/data/manual-highlight.qml
index c2f1d20fb1..c2f1d20fb1 100644
--- a/tests/auto/declarative/qquickgridview/data/manual-highlight.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/manual-highlight.qml
diff --git a/tests/auto/declarative/qquickgridview/data/margins.qml b/tests/auto/qtquick2/qquickgridview/data/margins.qml
index d369658a91..d369658a91 100644
--- a/tests/auto/declarative/qquickgridview/data/margins.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/margins.qml
diff --git a/tests/auto/declarative/qquickgridview/data/mirroring.qml b/tests/auto/qtquick2/qquickgridview/data/mirroring.qml
index b9aff501c1..b9aff501c1 100644
--- a/tests/auto/declarative/qquickgridview/data/mirroring.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/mirroring.qml
diff --git a/tests/auto/declarative/qquickgridview/data/propertychangestest.qml b/tests/auto/qtquick2/qquickgridview/data/propertychangestest.qml
index 97efbe78f5..97efbe78f5 100644
--- a/tests/auto/declarative/qquickgridview/data/propertychangestest.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/propertychangestest.qml
diff --git a/tests/auto/declarative/qquickgridview/data/resizeview.qml b/tests/auto/qtquick2/qquickgridview/data/resizeview.qml
index 1f730a4a8a..1f730a4a8a 100644
--- a/tests/auto/declarative/qquickgridview/data/resizeview.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/resizeview.qml
diff --git a/tests/auto/declarative/qquickgridview/data/setindex.qml b/tests/auto/qtquick2/qquickgridview/data/setindex.qml
index ef80f3a2fb..ef80f3a2fb 100644
--- a/tests/auto/declarative/qquickgridview/data/setindex.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/setindex.qml
diff --git a/tests/auto/declarative/qquickgridview/data/snapToRow.qml b/tests/auto/qtquick2/qquickgridview/data/snapToRow.qml
index f079a048f0..f079a048f0 100644
--- a/tests/auto/declarative/qquickgridview/data/snapToRow.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/snapToRow.qml
diff --git a/tests/auto/declarative/qquickgridview/data/unaligned.qml b/tests/auto/qtquick2/qquickgridview/data/unaligned.qml
index 445400e8b4..445400e8b4 100644
--- a/tests/auto/declarative/qquickgridview/data/unaligned.qml
+++ b/tests/auto/qtquick2/qquickgridview/data/unaligned.qml
diff --git a/tests/auto/qtquick2/qquickgridview/qquickgridview.pro b/tests/auto/qtquick2/qquickgridview/qquickgridview.pro
new file mode 100644
index 0000000000..b43e720162
--- /dev/null
+++ b/tests/auto/qtquick2/qquickgridview/qquickgridview.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickgridview
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickgridview.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+CONFIG += insignificant_test #QTBUG-22807
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib widgets
diff --git a/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
new file mode 100644
index 0000000000..cc0f7b7225
--- /dev/null
+++ b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
@@ -0,0 +1,3705 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtWidgets/qstringlistmodel.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtDeclarative/private/qlistmodelinterface_p.h>
+#include <QtQuick/private/qquickgridview_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
+#include "../../shared/util.h"
+#include <QtGui/qguiapplication.h>
+
+Q_DECLARE_METATYPE(Qt::LayoutDirection)
+Q_DECLARE_METATYPE(QQuickGridView::Flow)
+
+class tst_QQuickGridView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickGridView();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void items();
+ void changed();
+ void inserted();
+ void inserted_more();
+ void inserted_more_data();
+ void insertBeforeVisible();
+ void insertBeforeVisible_data();
+ void removed();
+ void addOrRemoveBeforeVisible();
+ void addOrRemoveBeforeVisible_data();
+ void clear();
+ void moved();
+ void moved_data();
+ void multipleChanges();
+ void multipleChanges_data();
+ void swapWithFirstItem();
+ void changeFlow();
+ void currentIndex();
+ void noCurrentIndex();
+ void defaultValues();
+ void properties();
+ void propertyChanges();
+ void componentChanges();
+ void modelChanges();
+ void positionViewAtIndex();
+ void positionViewAtIndex_rightToLeft();
+ void mirroring();
+ void snapping();
+ void resetModel();
+ void enforceRange();
+ void enforceRange_rightToLeft();
+ void QTBUG_8456();
+ void manualHighlight();
+ void footer();
+ void footer_data();
+ void header();
+ void header_data();
+ void resizeViewAndRepaint();
+ void indexAt();
+ void onAdd();
+ void onAdd_data();
+ void onRemove();
+ void onRemove_data();
+ void columnCount();
+ void margins();
+ void creationContext();
+ void snapToRow_data();
+ void snapToRow();
+ void unaligned();
+ void cacheBuffer();
+ void asynchronous();
+
+private:
+ QQuickView *createView();
+ void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &id, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QQuickItem *parent, const QString &objectName);
+ void dumpTree(QQuickItem *parent, int depth = 0);
+};
+
+template<typename T>
+void tst_qquickgridview_move(int from, int to, int n, T *items)
+{
+ if (n == 1) {
+ items->move(from, to);
+ } else {
+ T replaced;
+ int i=0;
+ typename T::ConstIterator it=items->begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=items->begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ typename T::ConstIterator f=replaced.begin();
+ typename T::Iterator t=items->begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+}
+
+void tst_QQuickGridView::initTestCase()
+{
+}
+
+void tst_QQuickGridView::cleanupTestCase()
+{
+
+}
+
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void addItems(const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
+ for (int i=0; i<items.count(); i++)
+ list.append(QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void removeItems(int index, int count) {
+ emit beginRemoveRows(QModelIndex(), index, index+count-1);
+ while (count--)
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void moveItems(int from, int to, int count) {
+ emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
+ tst_qquickgridview_move(from, to, count, &list);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+ void clear() {
+ int count = list.count();
+ emit beginRemoveRows(QModelIndex(), 0, count-1);
+ list.clear();
+ emit endRemoveRows();
+ }
+
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QQuickGridView::tst_QQuickGridView()
+{
+}
+
+void tst_QQuickGridView::items()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Billy", "22345");
+ model.addItem("Sam", "2945");
+ model.addItem("Ben", "04321");
+ model.addItem("Jim", "0780");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(gridview->count(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ // set an empty model and confirm that items are destroyed
+ TestModel model2;
+ ctxt->setContextProperty("testModel", &model2);
+
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ QTRY_VERIFY(itemCount == 0);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::changed()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Billy", "22345");
+ model.addItem("Sam", "2945");
+ model.addItem("Ben", "04321");
+ model.addItem("Jim", "0780");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickFlickable *gridview = findItem<QQuickFlickable>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::inserted()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+ // Checks that onAdd is called
+ int added = canvas->rootObject()->property("added").toInt();
+ QTRY_COMPARE(added, 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ QTRY_COMPARE(gridview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ for (int i = model.count(); i < 30; ++i)
+ model.insertItem(i, "Hello", QString::number(i));
+
+ gridview->setContentY(120);
+
+ // Insert item outside visible area
+ model.insertItem(1, "Hello", "1324");
+
+ QTRY_VERIFY(gridview->contentY() == 120);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::inserted_more()
+{
+ QFETCH(qreal, contentY);
+ QFETCH(int, insertIndex);
+ QFETCH(int, insertCount);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ gridview->setContentY(contentY);
+
+ QList<QPair<QString, QString> > newData;
+ for (int i=0; i<insertCount; i++)
+ newData << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.insertItems(insertIndex, newData);
+ QTRY_COMPARE(gridview->property("count").toInt(), model.count());
+
+ // check visibleItems.first() is in correct position
+ QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item0);
+ QCOMPARE(item0->y(), itemsOffsetAfterMove);
+
+ QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
+ int firstVisibleIndex = -1;
+ for (int i=0; i<items.count(); i++) {
+ if (items[i]->y() >= contentY) {
+ QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
+ firstVisibleIndex = e.evaluate().toInt();
+ break;
+ }
+ }
+ QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+
+ QCOMPARE(item->x(), (i%3)*80.0);
+ QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
+
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::inserted_more_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<int>("insertCount");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ QTest::newRow("add 1, before visible items")
+ << 120.0 // show 6-23
+ << 5 << 1
+ << 0.0; // insert 1 above first visible, grid is rearranged; first visible moves forward within its row
+ // new 1st visible item is at 0
+
+ QTest::newRow("add 2, before visible items")
+ << 120.0 // show 6-23
+ << 5 << 2
+ << 0.0; // insert 2 above first visible, grid is rearranged; first visible moves forward within its row
+
+ QTest::newRow("add 3, before visible items")
+ << 120.0 // show 6-23
+ << 5 << 3
+ << -60.0; // insert 3 (1 row) above first visible in negative pos, first visible does not move
+
+ QTest::newRow("add 5, before visible items")
+ << 120.0 // show 6-23
+ << 5 << 5
+ << -60.0; // insert 1 row + 2 items above first visible, 1 row added at negative pos,
+ // grid is rearranged and first visible moves forward within its row
+
+ QTest::newRow("add 6, before visible items")
+ << 120.0 // show 6-23
+ << 5 << 6
+ << -60.0 * 2; // insert 2 rows above first visible in negative pos, first visible does not move
+
+
+
+ QTest::newRow("add 1, at start of visible, content at start")
+ << 0.0
+ << 0 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, at start of visible, content at start")
+ << 0.0
+ << 0 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, at start of visible, content not at start")
+ << 120.0 // show 6-23
+ << 6 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, at start of visible, content not at start")
+ << 120.0 // show 6-23
+ << 6 << 3
+ << 0.0;
+
+
+ QTest::newRow("add 1, at end of visible, content at start")
+ << 0.0
+ << 17 << 1
+ << 0.0;
+
+ QTest::newRow("add 1, at end of visible, content at start")
+ << 0.0
+ << 17 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, at end of visible, content not at start")
+ << 120.0 // show 6-23
+ << 23 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, at end of visible, content not at start")
+ << 120.0 // show 6-23
+ << 23 << 3
+ << 0.0;
+
+
+ QTest::newRow("add 1, after visible, content at start")
+ << 0.0
+ << 20 << 1
+ << 0.0;
+
+ QTest::newRow("add 1, after visible, content at start")
+ << 0.0
+ << 20 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, after visible, content not at start")
+ << 120.0 // show 6-23
+ << 24 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, after visible, content not at start")
+ << 120.0 // show 6-23
+ << 24 << 3
+ << 0.0;
+}
+
+void tst_QQuickGridView::insertBeforeVisible()
+{
+ QFETCH(int, insertIndex);
+ QFETCH(int, insertCount);
+ QFETCH(int, cacheBuffer);
+
+ QQuickText *name;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ gridview->setCacheBuffer(cacheBuffer);
+
+ // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
+ int firstVisibleIndex = 20; // move to an index where the top item is not visible
+ gridview->setContentY(firstVisibleIndex * 20.0);
+ gridview->setCurrentIndex(firstVisibleIndex);
+ qApp->processEvents();
+ QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
+ QVERIFY(item);
+ QCOMPARE(item->y(), gridview->contentY());
+
+ QList<QPair<QString, QString> > newData;
+ for (int i=0; i<insertCount; i++)
+ newData << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.insertItems(insertIndex, newData);
+ QTRY_COMPARE(gridview->property("count").toInt(), model.count());
+
+ // now, moving to the top of the view should position the inserted items correctly
+ int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
+ gridview->setCurrentIndex(0);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QCOMPARE(item->x(), (i%3)*80.0);
+ QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::insertBeforeVisible_data()
+{
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<int>("insertCount");
+ QTest::addColumn<int>("cacheBuffer");
+
+ QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
+ QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
+ QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
+
+ QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
+ QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
+ QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
+
+ QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 6 << 0;
+ QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 6 << 100;
+ QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 6 << 500;
+
+ QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 6 << 0;
+ QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 6 << 100;
+ QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 6 << 500;
+}
+
+void tst_QQuickGridView::removed()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.removeItem(1);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+
+ // Checks that onRemove is called
+ QString removed = canvas->rootObject()->property("removed").toString();
+ QTRY_COMPARE(removed, QString("Item1"));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove items not visible
+ model.removeItem(25);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove items before visible
+ gridview->setContentY(120);
+ gridview->setCurrentIndex(10);
+
+ // Setting currentIndex above shouldn't cause view to scroll
+ QTRY_COMPARE(gridview->contentY(), 120.0);
+
+ model.removeItem(1);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ // Confirm items positioned correctly
+ for (int i = 6; i < 18; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ // Remove currentIndex
+ QQuickItem *oldCurrent = gridview->currentItem();
+ model.removeItem(9);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QTRY_COMPARE(gridview->currentIndex(), 9);
+ QTRY_VERIFY(gridview->currentItem() != oldCurrent);
+
+ gridview->setContentY(0);
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60);
+ }
+
+ // remove item outside current view.
+ gridview->setCurrentIndex(32);
+ gridview->setContentY(240);
+
+ model.removeItem(30);
+ QTRY_VERIFY(gridview->currentIndex() == 31);
+
+ // remove current item beyond visible items.
+ gridview->setCurrentIndex(20);
+ gridview->setContentY(0);
+ model.removeItem(20);
+
+ QTRY_COMPARE(gridview->currentIndex(), 20);
+ QTRY_VERIFY(gridview->currentItem() != 0);
+
+ // remove item before current, but visible
+ gridview->setCurrentIndex(8);
+ gridview->setContentY(240);
+ oldCurrent = gridview->currentItem();
+ model.removeItem(6);
+
+ QTRY_COMPARE(gridview->currentIndex(), 7);
+ QTRY_VERIFY(gridview->currentItem() == oldCurrent);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::addOrRemoveBeforeVisible()
+{
+ // QTBUG-21588: ensure re-layout is done on grid after adding or removing
+ // items from before the visible area
+
+ QFETCH(bool, doAdd);
+ QFETCH(qreal, newTopContentY);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_COMPARE(name->text(), QString("Item0"));
+
+ gridview->setCurrentIndex(0);
+ qApp->processEvents();
+
+ // scroll down until item 0 is no longer drawn
+ // (bug not triggered if we just move using content y, since that doesn't
+ // refill and change the visible items)
+ gridview->setCurrentIndex(24);
+ qApp->processEvents();
+
+ QTRY_COMPARE(gridview->currentIndex(), 24);
+ QTRY_COMPARE(gridview->contentY(), 220.0);
+
+ QTest::qWait(100); // wait for refill to complete
+ QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0)); // 0 shouldn't be visible
+
+ if (doAdd) {
+ model.insertItem(0, "New Item", "New Item number");
+ QTRY_COMPARE(gridview->count(), 31);
+ } else {
+ model.removeItem(0);
+ QTRY_COMPARE(gridview->count(), 29);
+ }
+
+ // scroll back up and item 0 should be gone
+ gridview->setCurrentIndex(0);
+ qApp->processEvents();
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentY(), newTopContentY);
+
+ name = findItem<QQuickText>(contentItem, "textName", 0);
+ if (doAdd)
+ QCOMPARE(name->text(), QString("New Item"));
+ else
+ QCOMPARE(name->text(), QString("Item1"));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_VERIFY(item->x() == (i%3)*80);
+ QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
+{
+ QTest::addColumn<bool>("doAdd");
+ QTest::addColumn<qreal>("newTopContentY");
+
+ QTest::newRow("add") << true << -60.0;
+ QTest::newRow("remove") << false << 0.0;
+}
+
+void tst_QQuickGridView::clear()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QVERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ model.clear();
+
+ QVERIFY(gridview->count() == 0);
+ QVERIFY(gridview->currentItem() == 0);
+ QVERIFY(gridview->contentY() == 0);
+ QVERIFY(gridview->currentIndex() == -1);
+
+ // confirm sanity when adding an item to cleared list
+ model.addItem("New", "1");
+ QTRY_COMPARE(gridview->count(), 1);
+ QVERIFY(gridview->currentItem() != 0);
+ QVERIFY(gridview->currentIndex() == 0);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::moved()
+{
+ QFETCH(qreal, contentY);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, count);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickItem *currentItem = gridview->currentItem();
+ QTRY_VERIFY(currentItem != 0);
+
+ gridview->setContentY(contentY);
+ model.moveItems(from, to, count);
+
+ // wait for items to move
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly and indexes correct
+ int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ if (i >= firstVisibleIndex + 18) // index has moved out of view
+ continue;
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
+
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+
+ // current index should have been updated
+ if (item == currentItem)
+ QTRY_COMPARE(gridview->currentIndex(), i);
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::moved_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ // model starts with 30 items, each 80x60, in area 240x320
+ // 18 items should be visible at a time
+
+ QTest::newRow("move 1 forwards, within visible items")
+ << 0.0
+ << 1 << 8 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible")
+ << 120.0 // show 6-23
+ << 1 << 23 << 1
+ << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
+ << 120.0 // // show 6-23
+ << 0 << 6 << 1
+ << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 20 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 20 << 1
+ << 0.0;
+
+
+ QTest::newRow("move 1 backwards, within visible items")
+ << 0.0
+ << 10 << 5 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, within visible items (to first index)")
+ << 0.0
+ << 10 << 0 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible")
+ << 0.0
+ << 28 << 8 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 29 << 14 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible")
+ << 120.0 // show 6-23
+ << 7 << 1 << 1
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
+ << 120.0 // show 6-23
+ << 7 << 0 << 1
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
+
+
+ QTest::newRow("move multiple forwards, within visible items")
+ << 0.0
+ << 0 << 5 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, within visible items (move first item)")
+ << 0.0
+ << 10 << 0 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple forwards, before visible items")
+ << 120.0 // show 6-23
+ << 3 << 4 << 3 // 3, 4, 5 move to after 6
+ << 60.0; // row of 3,4,5 has moved down
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible")
+ << 120.0 // show 6-23
+ << 1 << 6 << 3
+ << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
+ << 120.0 // show 6-23
+ << 0 << 6 << 3
+ << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 16 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 16 << 3
+ << 0.0;
+
+
+ QTest::newRow("move multiple backwards, within visible items")
+ << 0.0
+ << 4 << 1 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible")
+ << 0.0
+ << 20 << 4 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 27 << 10 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible")
+ << 120.0 // show 6-23
+ << 16 << 1 << 3
+ << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
+ << 120.0 // show 6-23
+ << 16 << 0 << 3
+ << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
+}
+
+struct ListChange {
+ enum { Inserted, Removed, Moved, SetCurrent } type;
+ int index;
+ int count;
+ int to; // Move
+
+ static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
+ static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
+ static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
+ static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
+};
+Q_DECLARE_METATYPE(QList<ListChange>)
+
+void tst_QQuickGridView::multipleChanges()
+{
+ QFETCH(int, startCount);
+ QFETCH(QList<ListChange>, changes);
+ QFETCH(int, newCount);
+ QFETCH(int, newCurrentIndex);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < startCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ for (int i=0; i<changes.count(); i++) {
+ switch (changes[i].type) {
+ case ListChange::Inserted:
+ {
+ QList<QPair<QString, QString> > items;
+ for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
+ items << qMakePair(QString("new item " + j), QString::number(j));
+ model.insertItems(changes[i].index, items);
+ break;
+ }
+ case ListChange::Removed:
+ model.removeItems(changes[i].index, changes[i].count);
+ break;
+ case ListChange::Moved:
+ model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ break;
+ case ListChange::SetCurrent:
+ gridview->setCurrentIndex(changes[i].index);
+ break;
+ }
+ }
+
+ QTRY_COMPARE(gridview->count(), newCount);
+ QCOMPARE(gridview->count(), model.count());
+ QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i=0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::multipleChanges_data()
+{
+ QTest::addColumn<int>("startCount");
+ QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<int>("newCount");
+ QTest::addColumn<int>("newCurrentIndex");
+
+ QList<ListChange> changes;
+
+ for (int i=1; i<30; i++)
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
+
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all") << 30 << changes << 0 << -1;
+
+ changes.clear();
+ changes << ListChange::setCurrent(29);
+ for (int i=29; i>0; i--)
+ changes << ListChange::remove(i);
+ QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
+
+ QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
+ << ListChange::remove(0, 1)
+ << ListChange::insert(0, 1)
+ ) << 10 << 1;
+
+ QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(2, 1)
+ << ListChange::insert(2, 1)
+ ) << 10 << 3;
+
+ QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1, 3)
+ << ListChange::insert(2, 2)
+ ) << 9 << 1;
+
+ QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(1, 3)
+ << ListChange::move(1, 5, 1)
+ ) << 7 << 5;
+
+ QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::remove(4, 3)
+ << ListChange::move(4, 1, 1)
+ ) << 7 << 1;
+
+
+ QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ ) << 12 << 10;
+
+ QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ << ListChange::setCurrent(3)
+ << ListChange::insert(3, 2)
+ ) << 14 << 5;
+
+ QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 30)
+ << ListChange::remove(0, 30)
+ ) << 0 << -1;
+
+ QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
+ << ListChange::insert(1)
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1)
+ ) << 30 << 1;
+
+ QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 10)
+ << ListChange::remove(5, 10)
+ ) << 10 << 5;
+
+ QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 10, 3)
+ ) << 13 << 0;
+
+ QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 8, 5)
+ ) << 13 << 11;
+
+ QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(9)
+ << ListChange::insert(10, 3)
+ << ListChange::move(8, 0, 5)
+ ) << 13 << 1;
+
+
+ QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(1, 2, 2)
+ << ListChange::move(2, 1, 2)
+ ) << 10 << 1;
+
+ QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::move(1, 2, 3)
+ << ListChange::move(3, 0, 5)
+ ) << 10 << 0;
+
+ QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::remove(0)
+ ) << 9 << 0;
+
+ QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::insert(0)
+ ) << 11 << 1;
+
+ QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(5, 1, 3)
+ << ListChange::remove(1, 3)
+ ) << 7 << 1;
+
+ QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 1, 3)
+ << ListChange::insert(1, 5)
+ ) << 15 << 6;
+
+ QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(3)
+ << ListChange::move(0, 1, 2)
+ << ListChange::insert(3, 5)
+ ) << 15 << 8;
+
+
+ QTest::newRow("clear current") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 5)
+ << ListChange::setCurrent(-1)
+ << ListChange::remove(0, 5)
+ << ListChange::insert(0, 5)
+ ) << 5 << -1;
+}
+
+
+void tst_QQuickGridView::swapWithFirstItem()
+{
+ // QTBUG_9697
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ // ensure content position is stable
+ gridview->setContentY(0);
+ model.moveItem(10, 0);
+ QTRY_VERIFY(gridview->contentY() == 0);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::currentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 60; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+ canvas->show();
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(TESTDATA("gridview-initCurrent.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QVERIFY(gridview != 0);
+ QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ // current item should be third item
+ QCOMPARE(gridview->currentIndex(), 35);
+ QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
+ QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
+ QCOMPARE(gridview->contentY(), 400.0);
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), 36);
+ gridview->moveCurrentIndexDown();
+ QCOMPARE(gridview->currentIndex(), 39);
+ gridview->moveCurrentIndexUp();
+ QCOMPARE(gridview->currentIndex(), 36);
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), 35);
+
+ // wait until motion stops
+ QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
+
+ // no wrap
+ gridview->setCurrentIndex(0);
+ QCOMPARE(gridview->currentIndex(), 0);
+ // confirm that the velocity is updated
+ QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
+
+ gridview->moveCurrentIndexUp();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->setCurrentIndex(model.count()-1);
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ gridview->moveCurrentIndexDown();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ // with wrap
+ gridview->setWrapEnabled(true);
+
+ gridview->setCurrentIndex(0);
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ gridview->moveCurrentIndexLeft();
+ QCOMPARE(gridview->currentIndex(), model.count()-1);
+
+ qApp->processEvents();
+ QTRY_COMPARE(gridview->contentY(), 880.0);
+
+ gridview->moveCurrentIndexRight();
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ QTRY_COMPARE(gridview->contentY(), 0.0);
+
+
+ // footer should become visible if it is out of view, and then current index moves to the first row
+ canvas->rootObject()->setProperty("showFooter", true);
+ QTRY_VERIFY(gridview->footerItem());
+ gridview->setCurrentIndex(model.count()-3);
+ QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
+ gridview->setCurrentIndex(model.count()-2);
+ QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
+ canvas->rootObject()->setProperty("showFooter", false);
+
+ // header should become visible if it is out of view, and then current index moves to the last row
+ canvas->rootObject()->setProperty("showHeader", true);
+ QTRY_VERIFY(gridview->headerItem());
+ gridview->setCurrentIndex(3);
+ QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
+ gridview->setCurrentIndex(1);
+ QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
+ canvas->rootObject()->setProperty("showHeader", false);
+
+
+ // Test keys
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
+
+ gridview->setCurrentIndex(0);
+
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QCOMPARE(gridview->currentIndex(), 3);
+
+ QTest::keyClick(canvas, Qt::Key_Up);
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ // hold down Key_Down
+ for (int i=0; i<(model.count() / 3) - 1; i++) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Down);
+ QTRY_COMPARE(gridview->currentIndex(), 57);
+ QTRY_COMPARE(gridview->contentY(), 880.0);
+
+ // hold down Key_Up
+ for (int i=(model.count() / 3) - 1; i > 0; i--) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Up);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentY(), 0.0);
+
+
+ gridview->setFlow(QQuickGridView::TopToBottom);
+
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QVERIFY(qGuiApp->focusWindow() == canvas);
+ qApp->processEvents();
+
+ QTest::keyClick(canvas, Qt::Key_Right);
+ QCOMPARE(gridview->currentIndex(), 5);
+
+ QTest::keyClick(canvas, Qt::Key_Left);
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QCOMPARE(gridview->currentIndex(), 1);
+
+ QTest::keyClick(canvas, Qt::Key_Up);
+ QCOMPARE(gridview->currentIndex(), 0);
+
+ // hold down Key_Right
+ for (int i=0; i<(model.count() / 5) - 1; i++) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
+ }
+
+ QTest::keyRelease(canvas, Qt::Key_Right);
+ QTRY_COMPARE(gridview->currentIndex(), 55);
+ QTRY_COMPARE(gridview->contentX(), 720.0);
+
+ // hold down Key_Left
+ for (int i=(model.count() / 5) - 1; i > 0; i--) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Left);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentX(), 0.0);
+
+
+ // turn off auto highlight
+ gridview->setHighlightFollowsCurrentItem(false);
+ QVERIFY(gridview->highlightFollowsCurrentItem() == false);
+ QVERIFY(gridview->highlightItem());
+ qreal hlPosX = gridview->highlightItem()->x();
+ qreal hlPosY = gridview->highlightItem()->y();
+
+ gridview->setCurrentIndex(5);
+ QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
+ QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
+
+ // insert item before currentIndex
+ gridview->setCurrentIndex(28);
+ model.insertItem(0, "Foo", "1111");
+ QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
+
+ // check removing highlight by setting currentIndex to -1;
+ gridview->setCurrentIndex(-1);
+
+ QCOMPARE(gridview->currentIndex(), -1);
+ QVERIFY(!gridview->highlightItem());
+ QVERIFY(!gridview->currentItem());
+
+ gridview->setHighlightFollowsCurrentItem(true);
+
+ gridview->setFlow(QQuickGridView::LeftToRight);
+ gridview->setLayoutDirection(Qt::RightToLeft);
+
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
+ qApp->processEvents();
+
+ gridview->setCurrentIndex(35);
+
+ QTest::keyClick(canvas, Qt::Key_Right);
+ QCOMPARE(gridview->currentIndex(), 34);
+
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QCOMPARE(gridview->currentIndex(), 37);
+
+ QTest::keyClick(canvas, Qt::Key_Up);
+ QCOMPARE(gridview->currentIndex(), 34);
+
+ QTest::keyClick(canvas, Qt::Key_Left);
+ QCOMPARE(gridview->currentIndex(), 35);
+
+
+ // turn off auto highlight
+ gridview->setHighlightFollowsCurrentItem(false);
+ QVERIFY(gridview->highlightFollowsCurrentItem() == false);
+ QVERIFY(gridview->highlightItem());
+ hlPosX = gridview->highlightItem()->x();
+ hlPosY = gridview->highlightItem()->y();
+
+ gridview->setCurrentIndex(5);
+ QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
+ QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
+
+ // insert item before currentIndex
+ gridview->setCurrentIndex(28);
+ model.insertItem(0, "Foo", "1111");
+ QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
+
+ // check removing highlight by setting currentIndex to -1;
+ gridview->setCurrentIndex(-1);
+
+ QCOMPARE(gridview->currentIndex(), -1);
+ QVERIFY(!gridview->highlightItem());
+ QVERIFY(!gridview->currentItem());
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::noCurrentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 60; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(TESTDATA("gridview-noCurrent.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QVERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ // current index should be -1
+ QCOMPARE(gridview->currentIndex(), -1);
+ QVERIFY(!gridview->currentItem());
+ QVERIFY(!gridview->highlightItem());
+ QCOMPARE(gridview->contentY(), 0.0);
+
+ gridview->setCurrentIndex(5);
+ QCOMPARE(gridview->currentIndex(), 5);
+ QVERIFY(gridview->currentItem());
+ QVERIFY(gridview->highlightItem());
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::changeFlow()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal((i%3)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ ctxt->setContextProperty("testTopToBottom", QVariant(true));
+
+ // Confirm items positioned correctly and indexes correct
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal((i/5)*80));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ ctxt->setContextProperty("testRightToLeft", QVariant(true));
+
+ // Confirm items positioned correctly and indexes correct
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+ gridview->setContentX(100);
+ QTRY_COMPARE(gridview->contentX(), 100.);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+ QTRY_COMPARE(gridview->contentX(), 0.);
+
+ // Confirm items positioned correctly and indexes correct
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
+ QTRY_COMPARE(item->y(), qreal((i/3)*60));
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::defaultValues()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview3.qml")));
+ QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
+
+ QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj->model() == QVariant());
+ QTRY_VERIFY(obj->delegate() == 0);
+ QTRY_COMPARE(obj->currentIndex(), -1);
+ QTRY_VERIFY(obj->currentItem() == 0);
+ QTRY_COMPARE(obj->count(), 0);
+ QTRY_VERIFY(obj->highlight() == 0);
+ QTRY_VERIFY(obj->highlightItem() == 0);
+ QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
+ QTRY_VERIFY(obj->flow() == 0);
+ QTRY_COMPARE(obj->isWrapEnabled(), false);
+ QTRY_COMPARE(obj->cacheBuffer(), 0);
+ QTRY_COMPARE(obj->cellWidth(), qreal(100)); //### Should 100 be the default?
+ QTRY_COMPARE(obj->cellHeight(), qreal(100));
+ delete obj;
+}
+
+void tst_QQuickGridView::properties()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview2.qml")));
+ QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
+
+ QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj->model() != QVariant());
+ QTRY_VERIFY(obj->delegate() != 0);
+ QTRY_COMPARE(obj->currentIndex(), 0);
+ QTRY_VERIFY(obj->currentItem() != 0);
+ QTRY_COMPARE(obj->count(), 4);
+ QTRY_VERIFY(obj->highlight() != 0);
+ QTRY_VERIFY(obj->highlightItem() != 0);
+ QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
+ QTRY_VERIFY(obj->flow() == 0);
+ QTRY_COMPARE(obj->isWrapEnabled(), true);
+ QTRY_COMPARE(obj->cacheBuffer(), 200);
+ QTRY_COMPARE(obj->cellWidth(), qreal(100));
+ QTRY_COMPARE(obj->cellHeight(), qreal(100));
+ delete obj;
+}
+
+void tst_QQuickGridView::propertyChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
+ QTRY_VERIFY(gridView);
+
+ QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
+ QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
+ QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
+ QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
+
+ QTRY_COMPARE(gridView->isWrapEnabled(), true);
+ QTRY_COMPARE(gridView->cacheBuffer(), 10);
+ QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
+
+ gridView->setWrapEnabled(false);
+ gridView->setCacheBuffer(3);
+ gridView->setFlow(QQuickGridView::TopToBottom);
+
+ QTRY_COMPARE(gridView->isWrapEnabled(), false);
+ QTRY_COMPARE(gridView->cacheBuffer(), 3);
+ QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
+
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
+ QTRY_COMPARE(cacheBufferSpy.count(),1);
+ QTRY_COMPARE(flowSpy.count(),1);
+
+ gridView->setWrapEnabled(false);
+ gridView->setCacheBuffer(3);
+ gridView->setFlow(QQuickGridView::TopToBottom);
+
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
+ QTRY_COMPARE(cacheBufferSpy.count(),1);
+ QTRY_COMPARE(flowSpy.count(),1);
+
+ gridView->setFlow(QQuickGridView::LeftToRight);
+ QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
+
+ gridView->setWrapEnabled(true);
+ gridView->setCacheBuffer(5);
+ gridView->setLayoutDirection(Qt::RightToLeft);
+
+ QTRY_COMPARE(gridView->isWrapEnabled(), true);
+ QTRY_COMPARE(gridView->cacheBuffer(), 5);
+ QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
+
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
+ QTRY_COMPARE(cacheBufferSpy.count(),2);
+ QTRY_COMPARE(layoutSpy.count(),1);
+ QTRY_COMPARE(flowSpy.count(),2);
+
+ gridView->setWrapEnabled(true);
+ gridView->setCacheBuffer(5);
+ gridView->setLayoutDirection(Qt::RightToLeft);
+
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
+ QTRY_COMPARE(cacheBufferSpy.count(),2);
+ QTRY_COMPARE(layoutSpy.count(),1);
+ QTRY_COMPARE(flowSpy.count(),2);
+
+ gridView->setFlow(QQuickGridView::TopToBottom);
+ QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
+ QTRY_COMPARE(flowSpy.count(),3);
+
+ gridView->setFlow(QQuickGridView::TopToBottom);
+ QTRY_COMPARE(flowSpy.count(),3);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::componentChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
+ QTRY_VERIFY(gridView);
+
+ QDeclarativeComponent component(canvas->engine());
+ component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
+
+ QDeclarativeComponent delegateComponent(canvas->engine());
+ delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
+
+ QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
+ QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
+ QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
+ QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
+
+ gridView->setHighlight(&component);
+ gridView->setDelegate(&delegateComponent);
+ gridView->setHeader(&component);
+ gridView->setFooter(&component);
+
+ QTRY_COMPARE(gridView->highlight(), &component);
+ QTRY_COMPARE(gridView->delegate(), &delegateComponent);
+ QTRY_COMPARE(gridView->header(), &component);
+ QTRY_COMPARE(gridView->footer(), &component);
+
+ QTRY_COMPARE(highlightSpy.count(),1);
+ QTRY_COMPARE(delegateSpy.count(),1);
+ QTRY_COMPARE(headerSpy.count(),1);
+ QTRY_COMPARE(footerSpy.count(),1);
+
+ gridView->setHighlight(&component);
+ gridView->setDelegate(&delegateComponent);
+ gridView->setHeader(&component);
+ gridView->setFooter(&component);
+
+ QTRY_COMPARE(highlightSpy.count(),1);
+ QTRY_COMPARE(delegateSpy.count(),1);
+ QTRY_COMPARE(headerSpy.count(),1);
+ QTRY_COMPARE(footerSpy.count(),1);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::modelChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
+ QTRY_VERIFY(gridView);
+
+ QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
+ QTRY_VERIFY(alternateModel);
+ QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
+ QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
+
+ gridView->setModel(modelVariant);
+ QTRY_COMPARE(gridView->model(), modelVariant);
+ QTRY_COMPARE(modelSpy.count(),1);
+
+ gridView->setModel(modelVariant);
+ QTRY_COMPARE(modelSpy.count(),1);
+
+ gridView->setModel(QVariant());
+ QTRY_COMPARE(modelSpy.count(),2);
+ delete canvas;
+}
+
+void tst_QQuickGridView::positionViewAtIndex()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.);
+ QTRY_COMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on a currently visible item
+ gridview->positionViewAtIndex(4, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->indexAt(120, 90), 4);
+ QTRY_COMPARE(gridview->contentY(), 60.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.);
+ QTRY_COMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on an item beyond the visible items
+ gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->indexAt(40, 450), 21);
+ QTRY_COMPARE(gridview->contentY(), 420.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.);
+ QTRY_COMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position on an item that would leave empty space if positioned at the top
+ gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->indexAt(120, 630), 31);
+ QTRY_COMPARE(gridview->contentY(), 520.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.);
+ QTRY_COMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position at the beginning again
+ gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->indexAt(0, 0), 0);
+ QTRY_COMPARE(gridview->indexAt(40, 30), 0);
+ QTRY_COMPARE(gridview->indexAt(80, 60), 4);
+ QTRY_COMPARE(gridview->contentY(), 0.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.);
+ QTRY_COMPARE(item->y(), (i/3)*60.);
+ }
+
+ // Position at End
+ gridview->positionViewAtIndex(30, QQuickGridView::End);
+ QTRY_COMPARE(gridview->contentY(), 340.);
+
+ // Position in Center
+ gridview->positionViewAtIndex(15, QQuickGridView::Center);
+ QTRY_COMPARE(gridview->contentY(), 170.);
+
+ // Ensure at least partially visible
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentY(), 170.);
+
+ gridview->setContentY(302);
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentY(), 302.);
+
+ gridview->setContentY(360);
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentY(), 300.);
+
+ gridview->setContentY(60);
+ gridview->positionViewAtIndex(20, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentY(), 60.);
+
+ gridview->setContentY(20);
+ gridview->positionViewAtIndex(20, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentY(), 100.);
+
+ // Ensure completely visible
+ gridview->setContentY(120);
+ gridview->positionViewAtIndex(20, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentY(), 120.);
+
+ gridview->setContentY(302);
+ gridview->positionViewAtIndex(15, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentY(), 300.);
+
+ gridview->setContentY(60);
+ gridview->positionViewAtIndex(20, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentY(), 100.);
+
+ // Test for Top To Bottom layout
+ ctxt->setContextProperty("testTopToBottom", QVariant(true));
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), (i/5)*80.);
+ QTRY_COMPARE(item->y(), (i%5)*60.);
+ }
+
+ // Position at End
+ gridview->positionViewAtIndex(30, QQuickGridView::End);
+ QTRY_COMPARE(gridview->contentX(), 320.);
+ QTRY_COMPARE(gridview->contentY(), 0.);
+
+ // Position in Center
+ gridview->positionViewAtIndex(15, QQuickGridView::Center);
+ QTRY_COMPARE(gridview->contentX(), 160.);
+
+ // Ensure at least partially visible
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), 160.);
+
+ gridview->setContentX(170);
+ gridview->positionViewAtIndex(25, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), 170.);
+
+ gridview->positionViewAtIndex(30, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), 320.);
+
+ gridview->setContentX(170);
+ gridview->positionViewAtIndex(25, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentX(), 240.);
+
+ // positionViewAtBeginning
+ gridview->positionViewAtBeginning();
+ QTRY_COMPARE(gridview->contentX(), 0.);
+
+ gridview->setContentX(80);
+ canvas->rootObject()->setProperty("showHeader", true);
+ gridview->positionViewAtBeginning();
+ QTRY_COMPARE(gridview->contentX(), -30.);
+
+ // positionViewAtEnd
+ gridview->positionViewAtEnd();
+ QTRY_COMPARE(gridview->contentX(), 400.); // 8*80 - 240 (8 columns)
+
+ gridview->setContentX(80);
+ canvas->rootObject()->setProperty("showFooter", true);
+ gridview->positionViewAtEnd();
+ QTRY_COMPARE(gridview->contentX(), 430.);
+
+ // set current item to outside visible view, position at beginning
+ // and ensure highlight moves to current item
+ gridview->setCurrentIndex(6);
+ gridview->positionViewAtBeginning();
+ QTRY_COMPARE(gridview->contentX(), -30.);
+ QVERIFY(gridview->highlightItem());
+ QCOMPARE(gridview->highlightItem()->x(), 80.);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::snapping()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ gridview->setHeight(220);
+ QCOMPARE(gridview->height(), 220.);
+
+ gridview->positionViewAtIndex(12, QQuickGridView::Visible);
+ QCOMPARE(gridview->contentY(), 80.);
+
+ gridview->setContentY(0);
+ QCOMPARE(gridview->contentY(), 0.);
+
+ gridview->setSnapMode(QQuickGridView::SnapToRow);
+ QCOMPARE(gridview->snapMode(), QQuickGridView::SnapToRow);
+
+ gridview->positionViewAtIndex(12, QQuickGridView::Visible);
+ QCOMPARE(gridview->contentY(), 60.);
+
+ gridview->positionViewAtIndex(15, QQuickGridView::End);
+ QCOMPARE(gridview->contentY(), 120.);
+
+ delete canvas;
+
+}
+
+void tst_QQuickGridView::mirroring()
+{
+ QQuickView *canvasA = createView();
+ canvasA->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
+ QQuickGridView *gridviewA = findItem<QQuickGridView>(canvasA->rootObject(), "view");
+ QTRY_VERIFY(gridviewA != 0);
+
+ QQuickView *canvasB = createView();
+ canvasB->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
+ QQuickGridView *gridviewB = findItem<QQuickGridView>(canvasB->rootObject(), "view");
+ QTRY_VERIFY(gridviewA != 0);
+ qApp->processEvents();
+
+ QList<QString> objectNames;
+ objectNames << "item1" << "item2"; // << "item3"
+
+ gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+ gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
+ QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
+
+ // LTR != RTL
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+ gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
+
+ // LTR == LTR
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
+ QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
+ QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
+
+ // LTR != LTR+mirror
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
+
+ // RTL == LTR+mirror
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
+
+ // RTL != RTL+mirror
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+
+ // LTR == RTL+mirror
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
+
+ delete canvasA;
+ delete canvasB;
+}
+
+void tst_QQuickGridView::positionViewAtIndex_rightToLeft()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testTopToBottom", QVariant(true));
+ ctxt->setContextProperty("testRightToLeft", QVariant(true));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ }
+
+ // Position on a currently visible item
+ gridview->positionViewAtIndex(6, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->contentX(), -320.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ }
+
+ // Position on an item beyond the visible items
+ gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->contentX(), -560.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ }
+
+ // Position on an item that would leave empty space if positioned at the top
+ gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->contentX(), -640.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ }
+
+ // Position at the beginning again
+ gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
+ QTRY_COMPARE(gridview->contentX(), -240.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
+ QTRY_COMPARE(item->y(), qreal((i%5)*60));
+ }
+
+ // Position at End
+ gridview->positionViewAtIndex(30, QQuickGridView::End);
+ QTRY_COMPARE(gridview->contentX(), -560.);
+
+ // Position in Center
+ gridview->positionViewAtIndex(15, QQuickGridView::Center);
+ QTRY_COMPARE(gridview->contentX(), -400.);
+
+ // Ensure at least partially visible
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), -400.);
+
+ gridview->setContentX(-555.);
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), -555.);
+
+ gridview->setContentX(-239);
+ gridview->positionViewAtIndex(15, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), -320.);
+
+ gridview->setContentX(-239);
+ gridview->positionViewAtIndex(20, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), -400.);
+
+ gridview->setContentX(-640);
+ gridview->positionViewAtIndex(20, QQuickGridView::Visible);
+ QTRY_COMPARE(gridview->contentX(), -560.);
+
+ // Ensure completely visible
+ gridview->setContentX(-400);
+ gridview->positionViewAtIndex(20, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentX(), -400.);
+
+ gridview->setContentX(-315);
+ gridview->positionViewAtIndex(15, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentX(), -320.);
+
+ gridview->setContentX(-640);
+ gridview->positionViewAtIndex(20, QQuickGridView::Contain);
+ QTRY_COMPARE(gridview->contentX(), -560.);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::resetModel()
+{
+ QQuickView *canvas = createView();
+
+ QStringList strings;
+ strings << "one" << "two" << "three";
+ QStringListModel model(strings);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaygrid.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(gridview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
+ QTRY_VERIFY(display != 0);
+ QTRY_COMPARE(display->text(), strings.at(i));
+ }
+
+ strings.clear();
+ strings << "four" << "five" << "six" << "seven";
+ model.setStringList(strings);
+
+ QTRY_COMPARE(gridview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
+ QTRY_VERIFY(display != 0);
+ QTRY_COMPARE(display->text(), strings.at(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::enforceRange()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
+ qApp->processEvents();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
+ QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
+ QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // view should be positioned at the top of the range.
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(gridview->contentY(), -100.0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ // Check currentIndex is updated when contentItem moves
+ gridview->setContentY(0);
+ QTRY_COMPARE(gridview->currentIndex(), 2);
+
+ gridview->setCurrentIndex(5);
+ QTRY_COMPARE(gridview->contentY(), 100.);
+
+ TestModel model2;
+ for (int i = 0; i < 5; i++)
+ model2.addItem("Item" + QString::number(i), "");
+
+ ctxt->setContextProperty("testModel", &model2);
+ QCOMPARE(gridview->count(), 5);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::enforceRange_rightToLeft()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(true));
+ ctxt->setContextProperty("testTopToBottom", QVariant(true));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
+ qApp->processEvents();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
+ QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
+ QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ // view should be positioned at the top of the range.
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QTRY_COMPARE(gridview->contentX(), -140.);
+ QTRY_COMPARE(gridview->contentY(), 0.0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ // Check currentIndex is updated when contentItem moves
+ gridview->setContentX(-240);
+ QTRY_COMPARE(gridview->currentIndex(), 3);
+
+ gridview->setCurrentIndex(7);
+ QTRY_COMPARE(gridview->contentX(), -340.);
+ QTRY_COMPARE(gridview->contentY(), 0.0);
+
+ TestModel model2;
+ for (int i = 0; i < 5; i++)
+ model2.addItem("Item" + QString::number(i), "");
+
+ ctxt->setContextProperty("testModel", &model2);
+ QCOMPARE(gridview->count(), 5);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::QTBUG_8456()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("setindex.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::manualHighlight()
+{
+ QQuickView *canvas = createView();
+
+ QString filename(TESTDATA("manual-highlight.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
+ QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
+ QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
+
+ gridview->setCurrentIndex(2);
+
+ QTRY_COMPARE(gridview->currentIndex(), 2);
+ QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
+ QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
+ QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
+
+ gridview->positionViewAtIndex(8, QQuickGridView::Contain);
+
+ QTRY_COMPARE(gridview->currentIndex(), 2);
+ QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
+ QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
+ QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
+
+ gridview->setFlow(QQuickGridView::TopToBottom);
+ QTRY_COMPARE(gridview->flow(), QQuickGridView::TopToBottom);
+
+ gridview->setCurrentIndex(0);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
+ QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
+ QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
+
+ delete canvas;
+}
+
+
+void tst_QQuickGridView::footer()
+{
+ QFETCH(QQuickGridView::Flow, flow);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(QPointF, initialFooterPos);
+ QFETCH(QPointF, changedFooterPos);
+ QFETCH(QPointF, initialContentPos);
+ QFETCH(QPointF, changedContentPos);
+ QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, resizeContentPos);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 7; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("footer.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
+ QVERIFY(footer);
+
+ QVERIFY(footer == gridview->footerItem());
+
+ QCOMPARE(footer->pos(), initialFooterPos);
+ QCOMPARE(footer->width(), 100.);
+ QCOMPARE(footer->height(), 30.);
+ QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ if (flow == QQuickGridView::LeftToRight) {
+ // shrink by one row
+ model.removeItem(2);
+ QTRY_COMPARE(footer->y(), initialFooterPos.y() - gridview->cellHeight());
+ } else {
+ // shrink by one column
+ model.removeItem(2);
+ model.removeItem(3);
+ if (layoutDirection == Qt::LeftToRight)
+ QTRY_COMPARE(footer->x(), initialFooterPos.x() - gridview->cellWidth());
+ else
+ QTRY_COMPARE(footer->x(), initialFooterPos.x() + gridview->cellWidth());
+ }
+
+ // remove all items
+ model.clear();
+
+ QPointF posWhenNoItems(0, 0);
+ if (layoutDirection == Qt::RightToLeft)
+ posWhenNoItems.setX(flow == QQuickGridView::LeftToRight ? gridview->width() - footer->width() : -footer->width());
+ QTRY_COMPARE(footer->pos(), posWhenNoItems);
+
+ // if header is present, it's at a negative pos, so the footer should not move
+ canvas->rootObject()->setProperty("showHeader", true);
+ QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
+ QTRY_COMPARE(footer->pos(), posWhenNoItems);
+ canvas->rootObject()->setProperty("showHeader", false);
+
+ // add 30 items
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QSignalSpy footerItemSpy(gridview, SIGNAL(footerItemChanged()));
+ QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
+
+ QCOMPARE(footerItemSpy.count(), 1);
+
+ footer = findItem<QQuickText>(contentItem, "footer");
+ QVERIFY(!footer);
+ footer = findItem<QQuickText>(contentItem, "footer2");
+ QVERIFY(footer);
+
+ QVERIFY(footer == gridview->footerItem());
+
+ QCOMPARE(footer->pos(), changedFooterPos);
+ QCOMPARE(footer->width(), 50.);
+ QCOMPARE(footer->height(), 20.);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ gridview->positionViewAtEnd();
+ footer->setHeight(10);
+ footer->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::footer_data()
+{
+ QTest::addColumn<QQuickGridView::Flow>("flow");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QPointF>("initialFooterPos");
+ QTest::addColumn<QPointF>("changedFooterPos");
+ QTest::addColumn<QPointF>("initialContentPos");
+ QTest::addColumn<QPointF>("changedContentPos");
+ QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
+
+ // footer1 = 100 x 30
+ // footer2 = 50 x 20
+ // cells = 80 * 60
+ // view width = 240
+ // view height = 320
+
+ // footer below items, bottom left
+ QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
+ << QPointF(0, 3 * 60) // 180 = height of 3 rows (cell height is 60)
+ << QPointF(0, 10 * 60) // 30 items = 10 rows
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
+
+ // footer below items, bottom right
+ QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
+ << QPointF(240 - 100, 3 * 60)
+ << QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(240 - 80, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
+
+ // footer to right of items
+ QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
+ << QPointF(2 * 80, 0) // 2 columns, cell width 80
+ << QPointF(6 * 80, 0) // 30 items = 6 columns
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(6 * 80 - 240 + 40, 0);
+
+ // footer to left of items
+ QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
+ << QPointF(-(2 * 80) - 100, 0)
+ << QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
+ << QPointF(-240, 0)
+ << QPointF(-240, 0) // unchanged, footer change doesn't change content pos
+ << QPointF(-80, 0)
+ << QPointF(-(6 * 80) - 40, 0);
+}
+
+void tst_QQuickGridView::header()
+{
+ QFETCH(QQuickGridView::Flow, flow);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(QPointF, initialHeaderPos);
+ QFETCH(QPointF, changedHeaderPos);
+ QFETCH(QPointF, initialContentPos);
+ QFETCH(QPointF, changedContentPos);
+ QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, resizeContentPos);
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QQuickView *canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *header = findItem<QQuickText>(contentItem, "header");
+ QVERIFY(header);
+
+ QVERIFY(header == gridview->headerItem());
+
+ QCOMPARE(header->pos(), initialHeaderPos);
+ QCOMPARE(header->width(), 100.);
+ QCOMPARE(header->height(), 30.);
+ QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ model.clear();
+ QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
+
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QSignalSpy headerItemSpy(gridview, SIGNAL(headerItemChanged()));
+ QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
+
+ QCOMPARE(headerItemSpy.count(), 1);
+
+ header = findItem<QQuickText>(contentItem, "header");
+ QVERIFY(!header);
+ header = findItem<QQuickText>(contentItem, "header2");
+ QVERIFY(header);
+
+ QVERIFY(header == gridview->headerItem());
+
+ QCOMPARE(header->pos(), changedHeaderPos);
+ QCOMPARE(header->width(), 50.);
+ QCOMPARE(header->height(), 20.);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ header->setHeight(10);
+ header->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
+ delete canvas;
+
+
+ // QTBUG-21207 header should become visible if view resizes from initial empty size
+
+ canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
+
+ gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+
+ gridview->setWidth(240);
+ gridview->setHeight(320);
+ QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
+ QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::header_data()
+{
+ QTest::addColumn<QQuickGridView::Flow>("flow");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QPointF>("initialHeaderPos");
+ QTest::addColumn<QPointF>("changedHeaderPos");
+ QTest::addColumn<QPointF>("initialContentPos");
+ QTest::addColumn<QPointF>("changedContentPos");
+ QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
+
+ // header1 = 100 x 30
+ // header2 = 50 x 20
+ // cells = 80 x 60
+ // view width = 240
+
+ // header above items, top left
+ QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, 0)
+ << QPointF(0, -10);
+
+ // header above items, top right
+ QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
+ << QPointF(240 - 100, -30)
+ << QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(160, 0)
+ << QPointF(0, -10);
+
+ // header to left of items
+ QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
+ << QPointF(-100, 0)
+ << QPointF(-50, 0)
+ << QPointF(-100, 0)
+ << QPointF(-50, 0)
+ << QPointF(0, 0)
+ << QPointF(-40, 0);
+
+ // header to right of items
+ QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(-(240 - 100), 0)
+ << QPointF(-(240 - 50), 0)
+ << QPointF(-80, 0)
+ << QPointF(-(240 - 40), 0);
+}
+
+void tst_QQuickGridView::resizeViewAndRepaint()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("initialHeight", 100);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizeview.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // item at index 10 should not be currently visible
+ QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ gridview->setHeight(320);
+ QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ gridview->setHeight(100);
+ QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::indexAt()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Billy", "22345");
+ model.addItem("Sam", "2945");
+ model.addItem("Ben", "04321");
+ model.addItem("Jim", "0780");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(gridview->count(), model.count());
+
+ QCOMPARE(gridview->indexAt(0, 0), 0);
+ QCOMPARE(gridview->indexAt(79, 59), 0);
+ QCOMPARE(gridview->indexAt(80, 0), 1);
+ QCOMPARE(gridview->indexAt(0, 60), 3);
+ QCOMPARE(gridview->indexAt(240, 0), -1);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::onAdd()
+{
+ QFETCH(int, initialItemCount);
+ QFETCH(int, itemsToAdd);
+
+ const int delegateWidth = 50;
+ const int delegateHeight = 100;
+ TestModel model;
+ QQuickView *canvas = createView();
+ canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
+
+ // these initial items should not trigger GridView.onAdd
+ for (int i=0; i<initialItemCount; i++)
+ model.addItem("dummy value", "dummy value");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("delegateWidth", delegateWidth);
+ ctxt->setContextProperty("delegateHeight", delegateHeight);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
+
+ QObject *object = canvas->rootObject();
+ object->setProperty("width", canvas->width());
+ object->setProperty("height", canvas->height());
+ qApp->processEvents();
+
+ QList<QPair<QString, QString> > items;
+ for (int i=0; i<itemsToAdd; i++)
+ items << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.addItems(items);
+
+ QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
+ qApp->processEvents();
+
+ QVariantList result = object->property("addedDelegates").toList();
+ QTRY_COMPARE(result.count(), items.count());
+ for (int i=0; i<items.count(); i++)
+ QCOMPARE(result[i].toString(), items[i].first);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::onAdd_data()
+{
+ QTest::addColumn<int>("initialItemCount");
+ QTest::addColumn<int>("itemsToAdd");
+
+ QTest::newRow("0, add 1") << 0 << 1;
+ QTest::newRow("0, add 2") << 0 << 2;
+ QTest::newRow("0, add 10") << 0 << 10;
+
+ QTest::newRow("1, add 1") << 1 << 1;
+ QTest::newRow("1, add 2") << 1 << 2;
+ QTest::newRow("1, add 10") << 1 << 10;
+
+ QTest::newRow("5, add 1") << 5 << 1;
+ QTest::newRow("5, add 2") << 5 << 2;
+ QTest::newRow("5, add 10") << 5 << 10;
+}
+
+void tst_QQuickGridView::onRemove()
+{
+ QFETCH(int, initialItemCount);
+ QFETCH(int, indexToRemove);
+ QFETCH(int, removeCount);
+
+ const int delegateWidth = 50;
+ const int delegateHeight = 100;
+ TestModel model;
+ for (int i=0; i<initialItemCount; i++)
+ model.addItem(QString("value %1").arg(i), "dummy value");
+
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("delegateWidth", delegateWidth);
+ ctxt->setContextProperty("delegateHeight", delegateHeight);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
+ QObject *object = canvas->rootObject();
+
+ model.removeItems(indexToRemove, removeCount);
+ QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
+ QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::onRemove_data()
+{
+ QTest::addColumn<int>("initialItemCount");
+ QTest::addColumn<int>("indexToRemove");
+ QTest::addColumn<int>("removeCount");
+
+ QTest::newRow("remove first") << 1 << 0 << 1;
+ QTest::newRow("two items, remove first") << 2 << 0 << 1;
+ QTest::newRow("two items, remove last") << 2 << 1 << 1;
+ QTest::newRow("two items, remove all") << 2 << 0 << 2;
+
+ QTest::newRow("four items, remove first") << 4 << 0 << 1;
+ QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
+ QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
+ QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
+ QTest::newRow("four items, remove last") << 4 << 3 << 1;
+ QTest::newRow("four items, remove all") << 4 << 0 << 4;
+
+ QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
+ QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
+ QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
+}
+
+void tst_QQuickGridView::columnCount()
+{
+ QQuickView canvas;
+ canvas.setSource(QUrl::fromLocalFile(TESTDATA("gridview4.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ QQuickGridView *view = qobject_cast<QQuickGridView*>(canvas.rootObject());
+
+ QCOMPARE(view->cellWidth(), qreal(405)/qreal(9));
+ QCOMPARE(view->cellHeight(), qreal(100));
+
+ QList<QQuickItem*> items = findItems<QQuickItem>(view, "delegate");
+ QCOMPARE(items.size(), 18);
+ QCOMPARE(items.at(8)->y(), qreal(0));
+ QCOMPARE(items.at(9)->y(), qreal(100));
+}
+
+void tst_QQuickGridView::margins()
+{
+ {
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QCOMPARE(gridview->contentX(), -30.);
+ QCOMPARE(gridview->xOrigin(), 0.);
+
+ // check end bound
+ gridview->positionViewAtEnd();
+ qreal pos = gridview->contentX();
+ gridview->setContentX(pos + 80);
+ gridview->returnToBounds();
+ QTRY_COMPARE(gridview->contentX(), pos + 50);
+
+ // remove item before visible and check that left margin is maintained
+ // and xOrigin is updated
+ gridview->setContentX(200);
+ model.removeItems(0, 4);
+ QTest::qWait(100);
+ gridview->setContentX(-50);
+ gridview->returnToBounds();
+ QCOMPARE(gridview->xOrigin(), 100.);
+ QTRY_COMPARE(gridview->contentX(), 70.);
+
+ // reduce left margin
+ gridview->setLeftMargin(20);
+ QCOMPARE(gridview->xOrigin(), 100.);
+ QTRY_COMPARE(gridview->contentX(), 80.);
+
+ // check end bound
+ gridview->positionViewAtEnd();
+ QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
+ pos = gridview->contentX();
+ gridview->setContentX(pos + 80);
+ gridview->returnToBounds();
+ QTRY_COMPARE(gridview->contentX(), pos + 50);
+
+ // reduce right margin
+ pos = gridview->contentX();
+ gridview->setRightMargin(40);
+ QCOMPARE(gridview->xOrigin(), 0.);
+ QTRY_COMPARE(gridview->contentX(), pos-10);
+
+ delete canvas;
+ }
+ {
+ //RTL
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(true));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QCOMPARE(gridview->contentX(), -240+30.);
+ QCOMPARE(gridview->xOrigin(), 0.);
+
+ // check end bound
+ gridview->positionViewAtEnd();
+ qreal pos = gridview->contentX();
+ gridview->setContentX(pos - 80);
+ gridview->returnToBounds();
+ QTRY_COMPARE(gridview->contentX(), pos - 50);
+
+ // remove item before visible and check that left margin is maintained
+ // and xOrigin is updated
+ gridview->setContentX(-400);
+ model.removeItems(0, 4);
+ QTest::qWait(100);
+ gridview->setContentX(-240+50);
+ gridview->returnToBounds();
+ QCOMPARE(gridview->xOrigin(), -100.);
+ QTRY_COMPARE(gridview->contentX(), -240-70.);
+
+ // reduce left margin (i.e. right side due to RTL)
+ pos = gridview->contentX();
+ gridview->setLeftMargin(20);
+ QCOMPARE(gridview->xOrigin(), -100.);
+ QTRY_COMPARE(gridview->contentX(), -240-80.);
+
+ // check end bound
+ gridview->positionViewAtEnd();
+ QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
+ pos = gridview->contentX();
+ gridview->setContentX(pos - 80);
+ gridview->returnToBounds();
+ QTRY_COMPARE(gridview->contentX(), pos - 50);
+
+ // reduce right margin (i.e. left side due to RTL)
+ pos = gridview->contentX();
+ gridview->setRightMargin(40);
+ QCOMPARE(gridview->xOrigin(), 0.);
+ QTRY_COMPARE(gridview->contentX(), pos+10);
+
+ delete canvas;
+ }
+}
+
+void tst_QQuickGridView::creationContext()
+{
+ QQuickView canvas;
+ canvas.setGeometry(0,0,240,320);
+ canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
+ qApp->processEvents();
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
+ QVERIFY(rootItem);
+ QVERIFY(rootItem->property("count").toInt() > 0);
+
+ QQuickItem *item;
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+}
+
+void tst_QQuickGridView::snapToRow_data()
+{
+ QTest::addColumn<QQuickGridView::Flow>("flow");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<int>("highlightRangeMode");
+ QTest::addColumn<QPoint>("flickStart");
+ QTest::addColumn<QPoint>("flickEnd");
+ QTest::addColumn<qreal>("snapAlignment");
+ QTest::addColumn<qreal>("endExtent");
+ QTest::addColumn<qreal>("startExtent");
+
+ QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
+
+ QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
+}
+
+void tst_QQuickGridView::snapToRow()
+{
+ QFETCH(QQuickGridView::Flow, flow);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(int, highlightRangeMode);
+ QFETCH(QPoint, flickStart);
+ QFETCH(QPoint, flickEnd);
+ QFETCH(qreal, snapAlignment);
+ QFETCH(qreal, endExtent);
+ QFETCH(qreal, startExtent);
+
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToRow.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+ gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // confirm that a flick hits an item boundary
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ if (flow == QQuickGridView::LeftToRight)
+ QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
+ else
+ QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
+
+ // flick to end
+ do {
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ } while (flow == QQuickGridView::LeftToRight
+ ? !gridview->isAtYEnd()
+ : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
+
+ if (flow == QQuickGridView::LeftToRight)
+ QCOMPARE(gridview->contentY(), endExtent);
+ else
+ QCOMPARE(gridview->contentX(), endExtent);
+
+ // flick to start
+ do {
+ flick(canvas, flickEnd, flickStart, 180);
+ QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
+ } while (flow == QQuickGridView::LeftToRight
+ ? !gridview->isAtYBeginning()
+ : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
+
+ if (flow == QQuickGridView::LeftToRight)
+ QCOMPARE(gridview->contentY(), startExtent);
+ else
+ QCOMPARE(gridview->contentX(), startExtent);
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::unaligned()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 10; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("unaligned.qml")));
+ qApp->processEvents();
+
+ QQuickGridView *gridview = qobject_cast<QQuickGridView*>(canvas->rootObject());
+ QVERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ for (int i = 0; i < 10; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
+ QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
+ }
+
+ // appending
+ for (int i = 10; i < 18; ++i) {
+ model.addItem("Item" + QString::number(i), "");
+ QQuickItem *item = 0;
+ QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
+ QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
+ QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
+ }
+
+ // inserting
+ for (int i = 0; i < 10; ++i) {
+ model.insertItem(i, "Item" + QString::number(i), "");
+ QQuickItem *item = 0;
+ QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
+ QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
+ QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
+ }
+
+ // removing
+ model.removeItems(7, 10);
+ QTRY_COMPARE(model.count(), gridview->count());
+ for (int i = 0; i < 18; ++i) {
+ QQuickItem *item = 0;
+ QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
+ QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
+ QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
+ }
+
+ delete canvas;
+}
+
+QQuickView *tst_QQuickGridView::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ return canvas;
+}
+
+void tst_QQuickGridView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+ const int pointCount = 5;
+ QPoint diff = to - from;
+
+ // send press, five equally spaced moves, and release.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+ for (int i = 0; i < pointCount; ++i) {
+ QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ QTest::qWait(duration/pointCount);
+ QCoreApplication::processEvents();
+ }
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
+void tst_QQuickGridView::cacheBuffer()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 90; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
+ QVERIFY(gridview != 0);
+
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+ QVERIFY(gridview->delegate() != 0);
+ QVERIFY(gridview->model() != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0);
+ }
+
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ canvas->rootObject()->setProperty("cacheBuffer", 200);
+ QTRY_VERIFY(gridview->cacheBuffer() == 200);
+
+ // items will be created one at a time
+ for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(gridview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ int newItemCount = 0;
+ newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < newItemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0);
+ }
+
+ // move view and confirm items in view are visible immediately and outside are created async
+ gridview->setContentY(300);
+
+ for (int i = 15; i < 34; ++i) { // 34 due to staggered item creation
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item);
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0);
+ }
+
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
+
+ // ensure buffered items are created
+ for (int i = 34; i < qMin(44,model.count()); ++i) {
+ QQuickItem *item = 0;
+ while (!item) {
+ qGuiApp->processEvents(); // allow refill to happen
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(gridview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickGridView::asynchronous()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ canvas->setSource(TESTDATA("asyncloader.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootObject);
+
+ QQuickGridView *gridview = 0;
+ while (!gridview) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ gridview = rootObject->findChild<QQuickGridView*>("view");
+ }
+
+ // items will be created one at a time
+ for (int i = 0; i < 12; ++i) {
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(gridview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ // verify positioning
+ QQuickItem *contentItem = gridview->contentItem();
+ for (int i = 0; i < 12; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item->x() == (i%3)*100);
+ QVERIFY(item->y() == (i/3)*100);
+ }
+
+ delete canvas;
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QQuickGridView::findItem(QQuickItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
+ if (context) {
+ if (context->contextProperty("index").toInt() == index) {
+ return static_cast<T*>(item);
+ }
+ }
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QQuickGridView::findItems(QQuickItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ items.append(static_cast<T*>(item));
+ //qDebug() << " found:" << item;
+ }
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+void tst_QQuickGridView::dumpTree(QQuickItem *parent, int depth)
+{
+ static QString padding(" ");
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
+ qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
+ dumpTree(item, depth+1);
+ }
+}
+
+
+QTEST_MAIN(tst_QQuickGridView)
+
+#include "tst_qquickgridview.moc"
+
diff --git a/tests/auto/declarative/qquickimage/data/aspectratio.qml b/tests/auto/qtquick2/qquickimage/data/aspectratio.qml
index b26f0e1f04..b26f0e1f04 100644
--- a/tests/auto/declarative/qquickimage/data/aspectratio.qml
+++ b/tests/auto/qtquick2/qquickimage/data/aspectratio.qml
diff --git a/tests/auto/declarative/qquickimage/data/big.jpeg b/tests/auto/qtquick2/qquickimage/data/big.jpeg
index bed7bd65c3..bed7bd65c3 100644
--- a/tests/auto/declarative/qquickimage/data/big.jpeg
+++ b/tests/auto/qtquick2/qquickimage/data/big.jpeg
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/big256.png b/tests/auto/qtquick2/qquickimage/data/big256.png
index 1dc1596d03..1dc1596d03 100644
--- a/tests/auto/declarative/qquickimage/data/big256.png
+++ b/tests/auto/qtquick2/qquickimage/data/big256.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/colors.png b/tests/auto/qtquick2/qquickimage/data/colors.png
index dfb62f3d64..dfb62f3d64 100644
--- a/tests/auto/declarative/qquickimage/data/colors.png
+++ b/tests/auto/qtquick2/qquickimage/data/colors.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/colors1.png b/tests/auto/qtquick2/qquickimage/data/colors1.png
index dfb62f3d64..dfb62f3d64 100644
--- a/tests/auto/declarative/qquickimage/data/colors1.png
+++ b/tests/auto/qtquick2/qquickimage/data/colors1.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/green.png b/tests/auto/qtquick2/qquickimage/data/green.png
index 0a2e153ba1..0a2e153ba1 100644
--- a/tests/auto/declarative/qquickimage/data/green.png
+++ b/tests/auto/qtquick2/qquickimage/data/green.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/heart-win32.png b/tests/auto/qtquick2/qquickimage/data/heart-win32.png
index 351da13772..351da13772 100644
--- a/tests/auto/declarative/qquickimage/data/heart-win32.png
+++ b/tests/auto/qtquick2/qquickimage/data/heart-win32.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/heart.png b/tests/auto/qtquick2/qquickimage/data/heart.png
index abe97fee4b..abe97fee4b 100644
--- a/tests/auto/declarative/qquickimage/data/heart.png
+++ b/tests/auto/qtquick2/qquickimage/data/heart.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/heart.svg b/tests/auto/qtquick2/qquickimage/data/heart.svg
index 8c982cd93c..8c982cd93c 100644
--- a/tests/auto/declarative/qquickimage/data/heart.svg
+++ b/tests/auto/qtquick2/qquickimage/data/heart.svg
diff --git a/tests/auto/declarative/qquickimage/data/heart200-win32.png b/tests/auto/qtquick2/qquickimage/data/heart200-win32.png
index 4976ff98ba..4976ff98ba 100644
--- a/tests/auto/declarative/qquickimage/data/heart200-win32.png
+++ b/tests/auto/qtquick2/qquickimage/data/heart200-win32.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/heart200.png b/tests/auto/qtquick2/qquickimage/data/heart200.png
index 7fbb13c5bb..7fbb13c5bb 100644
--- a/tests/auto/declarative/qquickimage/data/heart200.png
+++ b/tests/auto/qtquick2/qquickimage/data/heart200.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/htiling.qml b/tests/auto/qtquick2/qquickimage/data/htiling.qml
index f192f931c9..f192f931c9 100644
--- a/tests/auto/declarative/qquickimage/data/htiling.qml
+++ b/tests/auto/qtquick2/qquickimage/data/htiling.qml
diff --git a/tests/auto/declarative/qquickimage/data/mirror.qml b/tests/auto/qtquick2/qquickimage/data/mirror.qml
index 98fddf083e..98fddf083e 100644
--- a/tests/auto/declarative/qquickimage/data/mirror.qml
+++ b/tests/auto/qtquick2/qquickimage/data/mirror.qml
diff --git a/tests/auto/declarative/qquickimage/data/nullpixmap.qml b/tests/auto/qtquick2/qquickimage/data/nullpixmap.qml
index d52f41f164..d52f41f164 100644
--- a/tests/auto/declarative/qquickimage/data/nullpixmap.qml
+++ b/tests/auto/qtquick2/qquickimage/data/nullpixmap.qml
diff --git a/tests/auto/declarative/qquickimage/data/pattern.png b/tests/auto/qtquick2/qquickimage/data/pattern.png
index d3d5e1e007..d3d5e1e007 100644
--- a/tests/auto/declarative/qquickimage/data/pattern.png
+++ b/tests/auto/qtquick2/qquickimage/data/pattern.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/qtbug_16389.qml b/tests/auto/qtquick2/qquickimage/data/qtbug_16389.qml
index 7b8adecb11..7b8adecb11 100644
--- a/tests/auto/declarative/qquickimage/data/qtbug_16389.qml
+++ b/tests/auto/qtquick2/qquickimage/data/qtbug_16389.qml
diff --git a/tests/auto/declarative/qquickimage/data/qtbug_22125.qml b/tests/auto/qtquick2/qquickimage/data/qtbug_22125.qml
index 9b68c0a125..9b68c0a125 100644
--- a/tests/auto/declarative/qquickimage/data/qtbug_22125.qml
+++ b/tests/auto/qtquick2/qquickimage/data/qtbug_22125.qml
diff --git a/tests/auto/declarative/qquickimage/data/rect.png b/tests/auto/qtquick2/qquickimage/data/rect.png
index d564a2d5a5..d564a2d5a5 100644
--- a/tests/auto/declarative/qquickimage/data/rect.png
+++ b/tests/auto/qtquick2/qquickimage/data/rect.png
Binary files differ
diff --git a/tests/auto/declarative/qquickimage/data/vtiling.qml b/tests/auto/qtquick2/qquickimage/data/vtiling.qml
index f730f6e050..f730f6e050 100644
--- a/tests/auto/declarative/qquickimage/data/vtiling.qml
+++ b/tests/auto/qtquick2/qquickimage/data/vtiling.qml
diff --git a/tests/auto/qtquick2/qquickimage/qquickimage.pro b/tests/auto/qtquick2/qquickimage/qquickimage.pro
new file mode 100644
index 0000000000..fd2af3b677
--- /dev/null
+++ b/tests/auto/qtquick2/qquickimage/qquickimage.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickimage
+macx:CONFIG -= app_bundle
+
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qquickimage.cpp ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickimage/tst_qquickimage.cpp b/tests/auto/qtquick2/qquickimage/tst_qquickimage.cpp
new file mode 100644
index 0000000000..a7883626c6
--- /dev/null
+++ b/tests/auto/qtquick2/qquickimage/tst_qquickimage.cpp
@@ -0,0 +1,732 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QTextDocument>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QDir>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquickimage_p.h>
+#include <private/qquickimagebase_p.h>
+#include <private/qquickloader_p.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtTest/QSignalSpy>
+#include <QtGui/QPainter>
+#include <QtGui/QImageReader>
+
+#include "../../shared/util.h"
+#include "../../shared/testhttpserver.h"
+
+#define SERVER_PORT 14451
+#define SERVER_ADDR "http://127.0.0.1:14451"
+
+Q_DECLARE_METATYPE(QQuickImageBase::Status)
+
+class tst_qquickimage : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickimage();
+
+private slots:
+ void noSource();
+ void imageSource();
+ void imageSource_data();
+ void clearSource();
+ void resized();
+ void preserveAspectRatio();
+ void smooth();
+ void mirror();
+ void svg();
+ void geometry();
+ void geometry_data();
+ void big();
+ void tiling_QTBUG_6716();
+ void tiling_QTBUG_6716_data();
+ void noLoading();
+ void paintedWidthHeight();
+ void sourceSize_QTBUG_14303();
+ void sourceSize_QTBUG_16389();
+ void nullPixmapPaint();
+ void imageCrash_QTBUG_22125();
+
+private:
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &id, int index=-1);
+
+ QDeclarativeEngine engine;
+};
+
+tst_qquickimage::tst_qquickimage()
+{
+}
+
+void tst_qquickimage::noSource()
+{
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->source(), QUrl());
+ QVERIFY(obj->status() == QQuickImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
+ QCOMPARE(obj->progress(), 0.0);
+
+ delete obj;
+}
+
+void tst_qquickimage::imageSource_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<double>("width");
+ QTest::addColumn<double>("height");
+ QTest::addColumn<bool>("remote");
+ QTest::addColumn<bool>("async");
+ QTest::addColumn<bool>("cache");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << true << "";
+ QTest::newRow("local no cache") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << false << "";
+ QTest::newRow("local async") << QUrl::fromLocalFile(TESTDATA("colors1.png")).toString() << 120.0 << 120.0 << false << true << true << "";
+ QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << 0.0 << 0.0 << false
+ << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString();
+ QTest::newRow("local async not found") << QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString() << 0.0 << 0.0 << false
+ << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString();
+ QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << "";
+ QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
+ if (QImageReader::supportedImageFormats().contains("svg"))
+ QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << "";
+
+ QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
+ << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
+
+}
+
+void tst_qquickimage::imageSource()
+{
+ QFETCH(QString, source);
+ QFETCH(double, width);
+ QFETCH(double, height);
+ QFETCH(bool, remote);
+ QFETCH(bool, async);
+ QFETCH(bool, cache);
+ QFETCH(QString, error);
+
+ TestHTTPServer server(SERVER_PORT);
+ if (remote) {
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+ server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
+ }
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
+
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: "
+ + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
+ + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ if (async)
+ QVERIFY(obj->asynchronous() == true);
+ else
+ QVERIFY(obj->asynchronous() == false);
+
+ if (cache)
+ QVERIFY(obj->cache() == true);
+ else
+ QVERIFY(obj->cache() == false);
+
+ if (remote || async)
+ QTRY_VERIFY(obj->status() == QQuickImage::Loading);
+
+ QCOMPARE(obj->source(), remote ? source : QUrl(source));
+
+ if (error.isEmpty()) {
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QCOMPARE(obj->width(), qreal(width));
+ QCOMPARE(obj->height(), qreal(height));
+ QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
+ QCOMPARE(obj->progress(), 1.0);
+ } else {
+ QTRY_VERIFY(obj->status() == QQuickImage::Error);
+ }
+
+ delete obj;
+}
+
+void tst_qquickimage::clearSource()
+{
+ QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QQuickImage::Ready);
+ QCOMPARE(obj->width(), 120.);
+ QCOMPARE(obj->height(), 120.);
+ QCOMPARE(obj->progress(), 1.0);
+
+ ctxt->setContextProperty("srcImage", "");
+ QVERIFY(obj->source().isEmpty());
+ QVERIFY(obj->status() == QQuickImage::Null);
+ QCOMPARE(obj->width(), 0.);
+ QCOMPARE(obj->height(), 0.);
+ QCOMPARE(obj->progress(), 0.0);
+
+ delete obj;
+}
+
+void tst_qquickimage::resized()
+{
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
+ delete obj;
+}
+
+
+void tst_qquickimage::preserveAspectRatio()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->show();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
+ QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ QVERIFY(image != 0);
+ image->setWidth(80.0);
+ QCOMPARE(image->width(), 80.);
+ QCOMPARE(image->height(), 80.);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
+ image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ image->setHeight(60.0);
+ QVERIFY(image != 0);
+ QCOMPARE(image->height(), 60.);
+ QCOMPARE(image->width(), 60.);
+ delete canvas;
+}
+
+void tst_qquickimage::smooth()
+{
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.);
+ QCOMPARE(obj->height(), 300.);
+ QCOMPARE(obj->smooth(), true);
+ QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
+
+ delete obj;
+}
+
+void tst_qquickimage::mirror()
+{
+ QSKIP("Test is broken on multiple levels, will need incremental fixes");
+
+ QMap<QQuickImage::FillMode, QImage> screenshots;
+ QList<QQuickImage::FillMode> fillModes;
+ fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
+ << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally;
+
+ qreal width = 300;
+ qreal height = 250;
+
+ foreach (QQuickImage::FillMode fillMode, fillModes) {
+ QQuickView *canvas = new QQuickView;
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml")));
+
+ QQuickImage *obj = canvas->rootObject()->findChild<QQuickImage*>("image");
+ QVERIFY(obj != 0);
+
+ obj->setFillMode(fillMode);
+ obj->setProperty("mirror", true);
+ canvas->show();
+
+ QImage screenshot = canvas->grabFrameBuffer();
+ screenshots[fillMode] = screenshot;
+ delete canvas;
+ }
+
+ foreach (QQuickImage::FillMode fillMode, fillModes) {
+ QPixmap srcPixmap;
+ QVERIFY(srcPixmap.load(TESTDATA("pattern.png")));
+
+ QPixmap expected(width, height);
+ expected.fill();
+ QPainter p_e(&expected);
+ QTransform transform;
+ transform.translate(width, 0).scale(-1, 1.0);
+ p_e.setTransform(transform);
+
+ switch (fillMode) {
+ case QQuickImage::Stretch:
+ p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
+ break;
+ case QQuickImage::PreserveAspectFit:
+ p_e.drawPixmap(QRect(25, 0, height, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
+ break;
+ case QQuickImage::PreserveAspectCrop:
+ {
+ qreal ratio = width/srcPixmap.width(); // width is the longer side
+ QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio);
+ rect.moveCenter(QRect(0, 0, width, height).center());
+ p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
+ break;
+ }
+ case QQuickImage::Tile:
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ break;
+ case QQuickImage::TileVertically:
+ transform.scale(width / srcPixmap.width(), 1.0);
+ p_e.setTransform(transform);
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ break;
+ case QQuickImage::TileHorizontally:
+ transform.scale(1.0, height / srcPixmap.height());
+ p_e.setTransform(transform);
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ break;
+ case QQuickImage::Pad:
+ break;
+ }
+
+ QImage img = expected.toImage();
+ QEXPECT_FAIL("", "QTBUG-21005 fails", Continue);
+ QCOMPARE(screenshots[fillMode], img);
+ }
+}
+
+void tst_qquickimage::svg()
+{
+ if (!QImageReader::supportedImageFormats().contains("svg"))
+ QSKIP("svg support not available");
+
+ QString src = QUrl::fromLocalFile(TESTDATA("heart.svg")).toString();
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 300.0);
+ QCOMPARE(obj->height(), 300.0);
+ obj->setSourceSize(QSize(200,200));
+
+ QCOMPARE(obj->width(), 200.0);
+ QCOMPARE(obj->height(), 200.0);
+ delete obj;
+}
+
+void tst_qquickimage::geometry_data()
+{
+ QTest::addColumn<QString>("fillMode");
+ QTest::addColumn<bool>("explicitWidth");
+ QTest::addColumn<bool>("explicitHeight");
+ QTest::addColumn<double>("itemWidth");
+ QTest::addColumn<double>("paintedWidth");
+ QTest::addColumn<double>("boundingWidth");
+ QTest::addColumn<double>("itemHeight");
+ QTest::addColumn<double>("paintedHeight");
+ QTest::addColumn<double>("boundingHeight");
+
+ // tested image has width 200, height 100
+
+ // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match
+ QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
+ QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0;
+ QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0;
+ QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0;
+
+ // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match
+ QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
+ QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0;
+ QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
+ QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
+
+ // bounding rect, painted rect and item rect are equal in stretching and tiling images
+ QStringList fillModes;
+ fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
+ foreach (QString fillMode, fillModes) {
+ QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
+ QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
+ QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
+ QTest::newRow(QString(fillMode + " explicit width 300, height 400").toLatin1()) << fillMode << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 400.0 << 400.0;
+ }
+}
+
+void tst_qquickimage::geometry()
+{
+ QFETCH(QString, fillMode);
+ QFETCH(bool, explicitWidth);
+ QFETCH(bool, explicitHeight);
+ QFETCH(double, itemWidth);
+ QFETCH(double, itemHeight);
+ QFETCH(double, paintedWidth);
+ QFETCH(double, paintedHeight);
+ QFETCH(double, boundingWidth);
+ QFETCH(double, boundingHeight);
+
+ QString src = QUrl::fromLocalFile(TESTDATA("rect.png")).toString();
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; ";
+
+ if (explicitWidth)
+ componentStr.append("width: 300; ");
+ if (explicitHeight)
+ componentStr.append("height: 400; ");
+ componentStr.append("}");
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->width(), itemWidth);
+ QCOMPARE(obj->paintedWidth(), paintedWidth);
+ QCOMPARE(obj->boundingRect().width(), boundingWidth);
+
+ QCOMPARE(obj->height(), itemHeight);
+ QCOMPARE(obj->paintedHeight(), paintedHeight);
+ QCOMPARE(obj->boundingRect().height(), boundingHeight);
+ delete obj;
+}
+
+void tst_qquickimage::big()
+{
+ // If the JPEG loader does not implement scaling efficiently, it would
+ // have to build a 400 MB image. That would be a bug in the JPEG loader.
+
+ QString src = QUrl::fromLocalFile(TESTDATA("big.jpeg")).toString();
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }";
+
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 100.0);
+ QCOMPARE(obj->height(), 256.0);
+
+ delete obj;
+}
+
+// As tiling_QTBUG_6716 doesn't complete, it doesn't delete the
+// canvas which causes leak warnings. Use this delete on stack
+// destruction pattern to work around this.
+template<typename T>
+struct AutoDelete {
+ AutoDelete(T *t) : t(t) {}
+ ~AutoDelete() { delete t; }
+private:
+ T *t;
+};
+
+void tst_qquickimage::tiling_QTBUG_6716()
+{
+ QSKIP("Test is broken on multiple levels, will need incremental fixes");
+
+ QFETCH(QString, source);
+
+ QQuickView *canvas = new QQuickView(0);
+ AutoDelete<QQuickView> del(canvas);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA(source)));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickImage *tiling = findItem<QQuickImage>(canvas->rootObject(), "tiling");
+
+ QVERIFY(tiling != 0);
+ QImage img = canvas->grabFrameBuffer();
+ for (int x = 0; x < tiling->width(); ++x) {
+ for (int y = 0; y < tiling->height(); ++y) {
+ QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
+ }
+ }
+}
+
+void tst_qquickimage::tiling_QTBUG_6716_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::newRow("vertical_tiling") << "vtiling.qml";
+ QTest::newRow("horizontal_tiling") << "htiling.qml";
+}
+
+void tst_qquickimage::noLoading()
+{
+ qRegisterMetaType<QQuickImageBase::Status>();
+
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+ server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
+
+ QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; cache: true }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart.png")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QQuickImage::Ready);
+
+ QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
+ QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
+ QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
+
+ // Loading local file
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 1);
+ QTRY_COMPARE(progressSpy.count(), 0);
+ QTRY_COMPARE(statusSpy.count(), 0);
+
+ // Loading remote file
+ ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
+ QTRY_VERIFY(obj->status() == QQuickImage::Loading);
+ QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 2);
+ QTRY_COMPARE(progressSpy.count(), 2);
+ QTRY_COMPARE(statusSpy.count(), 2);
+
+ // Loading remote file again - should not go through 'Loading' state.
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
+ ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 4);
+ QTRY_COMPARE(progressSpy.count(), 2);
+ QTRY_COMPARE(statusSpy.count(), 2);
+
+ delete obj;
+}
+
+void tst_qquickimage::paintedWidthHeight()
+{
+ {
+ QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }";
+
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 200.0);
+ QCOMPARE(obj->height(), 25.0);
+ QCOMPARE(obj->paintedWidth(), 25.0);
+ QCOMPARE(obj->paintedHeight(), 25.0);
+
+ delete obj;
+ }
+
+ {
+ QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
+ QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->width(), 26.0);
+ QCOMPARE(obj->height(), 175.0);
+ QCOMPARE(obj->paintedWidth(), 26.0);
+ QCOMPARE(obj->paintedHeight(), 26.0);
+
+ delete obj;
+ }
+}
+
+void tst_qquickimage::sourceSize_QTBUG_14303()
+{
+ QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
+ QDeclarativeContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+
+ QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
+
+ QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+
+ QTRY_COMPARE(obj->sourceSize().width(), 200);
+ QTRY_COMPARE(obj->sourceSize().height(), 200);
+ QTRY_COMPARE(sourceSizeSpy.count(), 0);
+
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
+ QTRY_COMPARE(obj->sourceSize().width(), 120);
+ QTRY_COMPARE(obj->sourceSize().height(), 120);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
+
+ ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
+ QTRY_COMPARE(obj->sourceSize().width(), 200);
+ QTRY_COMPARE(obj->sourceSize().height(), 200);
+ QTRY_COMPARE(sourceSizeSpy.count(), 2);
+
+ delete obj;
+}
+
+void tst_qquickimage::sourceSize_QTBUG_16389()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug_16389.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickImage *image = findItem<QQuickImage>(canvas->rootObject(), "iconImage");
+ QQuickItem *handle = findItem<QQuickItem>(canvas->rootObject(), "blueHandle");
+
+ QCOMPARE(image->sourceSize().width(), 200);
+ QCOMPARE(image->sourceSize().height(), 200);
+ QCOMPARE(image->paintedWidth(), 0.0);
+ QCOMPARE(image->paintedHeight(), 0.0);
+
+ handle->setY(20);
+
+ QCOMPARE(image->sourceSize().width(), 200);
+ QCOMPARE(image->sourceSize().height(), 200);
+ QCOMPARE(image->paintedWidth(), 20.0);
+ QCOMPARE(image->paintedHeight(), 20.0);
+
+ delete canvas;
+}
+
+static int numberOfWarnings = 0;
+static void checkWarnings(QtMsgType, const char *msg)
+{
+ if (!QString(msg).contains("QGLContext::makeCurrent(): Failed."))
+ numberOfWarnings++;
+}
+
+// QTBUG-15690
+void tst_qquickimage::nullPixmapPaint()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("nullpixmap.qml")));
+ canvas->show();
+
+ QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ QTRY_VERIFY(image != 0);
+ image->setSource(SERVER_ADDR + QString("/no-such-file.png"));
+
+ QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings);
+
+ // used to print "QTransform::translate with NaN called"
+ QPixmap pm = QPixmap::fromImage(canvas->grabFrameBuffer());
+ qInstallMsgHandler(previousMsgHandler);
+ QVERIFY(numberOfWarnings == 0);
+ delete image;
+}
+
+void tst_qquickimage::imageCrash_QTBUG_22125()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""), TestHTTPServer::Delay);
+
+ {
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("qtbug_22125.qml")));
+ view.show();
+ qApp->processEvents();
+ qApp->processEvents();
+ // shouldn't crash when the view drops out of scope due to
+ // QDeclarativePixmapData attempting to dereference a pointer to
+ // the destroyed reader.
+ }
+
+ // shouldn't crash when deleting cancelled QDeclarativePixmapReplys.
+ QTest::qWait(520); // Delay mode delays for 500 ms.
+ qApp->processEvents(QEventLoop::DeferredDeletion);
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_qquickimage::findItem(QQuickItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeExpression e(qmlContext(item), item, "index");
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_qquickimage)
+
+#include "tst_qquickimage.moc"
diff --git a/tests/auto/declarative/qquickitem/data/order.1.qml b/tests/auto/qtquick2/qquickitem/data/order.1.qml
index 963288b257..963288b257 100644
--- a/tests/auto/declarative/qquickitem/data/order.1.qml
+++ b/tests/auto/qtquick2/qquickitem/data/order.1.qml
diff --git a/tests/auto/declarative/qquickitem/data/order.2.qml b/tests/auto/qtquick2/qquickitem/data/order.2.qml
index 5609c77e28..5609c77e28 100644
--- a/tests/auto/declarative/qquickitem/data/order.2.qml
+++ b/tests/auto/qtquick2/qquickitem/data/order.2.qml
diff --git a/tests/auto/qtquick2/qquickitem/qquickitem.pro b/tests/auto/qtquick2/qquickitem/qquickitem.pro
new file mode 100644
index 0000000000..2ebe76b09c
--- /dev/null
+++ b/tests/auto/qtquick2/qquickitem/qquickitem.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickitem
+SOURCES += tst_qquickitem.cpp
+
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private v8-private declarative-private quick-private widgets testlib
diff --git a/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp b/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp
new file mode 100644
index 0000000000..fd7433b64e
--- /dev/null
+++ b/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp
@@ -0,0 +1,1190 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickcanvas.h>
+#include <QtQuick/qquickview.h>
+#include <QtWidgets/QGraphicsSceneMouseEvent>
+#include "private/qquickfocusscope_p.h"
+#include "private/qquickitem_p.h"
+#include <QDebug>
+#include <QTimer>
+#include "../../shared/util.h"
+
+class TestItem : public QQuickItem
+{
+Q_OBJECT
+public:
+ TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {}
+
+ bool focused;
+ int pressCount;
+ int releaseCount;
+ int wheelCount;
+protected:
+ virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
+ virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
+ virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
+ virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
+ virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
+};
+
+class TestPolishItem : public QQuickItem
+{
+Q_OBJECT
+public:
+ TestPolishItem(QQuickItem *parent)
+ : QQuickItem(parent), wasPolished(false) {
+ QTimer::singleShot(10, this, SLOT(doPolish()));
+ }
+
+ bool wasPolished;
+
+protected:
+ virtual void updatePolish() {
+ wasPolished = true;
+ }
+
+public slots:
+ void doPolish() {
+ polish();
+ }
+};
+
+class TestFocusScope : public QQuickFocusScope
+{
+Q_OBJECT
+public:
+ TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
+
+ bool focused;
+protected:
+ virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
+ virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
+};
+
+class tst_qquickitem : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickitem();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void noCanvas();
+ void simpleFocus();
+ void scopedFocus();
+ void addedToCanvas();
+ void changeParent();
+
+ void constructor();
+ void setParentItem();
+
+ void visible();
+ void enabled();
+
+ void mouseGrab();
+ void polishOutsideAnimation();
+
+ void wheelEvent_data();
+ void wheelEvent();
+ void hoverEvent_data();
+ void hoverEvent();
+ void hoverEventInParent();
+
+ void paintOrder_data();
+ void paintOrder();
+
+private:
+
+ enum PaintOrderOp {
+ NoOp, Append, Remove, StackBefore, StackAfter, SetZ
+ };
+
+ void ensureFocus(QWindow *w) {
+ w->show();
+ w->requestActivateWindow();
+ qApp->processEvents();
+ }
+};
+
+tst_qquickitem::tst_qquickitem()
+{
+}
+
+void tst_qquickitem::initTestCase()
+{
+}
+
+void tst_qquickitem::cleanupTestCase()
+{
+}
+
+// Focus has no effect when outside a canvas
+void tst_qquickitem::noCanvas()
+{
+ QQuickItem *root = new TestItem;
+ QQuickItem *child = new TestItem(root);
+ QQuickItem *scope = new TestItem(root);
+ QQuickFocusScope *scopedChild = new TestFocusScope(scope);
+ QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
+
+ QCOMPARE(root->hasFocus(), false);
+ QCOMPARE(child->hasFocus(), false);
+ QCOMPARE(scope->hasFocus(), false);
+ QCOMPARE(scopedChild->hasFocus(), false);
+ QCOMPARE(scopedChild2->hasFocus(), false);
+
+ root->setFocus(true);
+ scope->setFocus(true);
+ scopedChild2->setFocus(true);
+ QCOMPARE(root->hasFocus(), true);
+ QCOMPARE(child->hasFocus(), false);
+ QCOMPARE(scope->hasFocus(), true);
+ QCOMPARE(scopedChild->hasFocus(), false);
+ QCOMPARE(scopedChild2->hasFocus(), true);
+
+ root->setFocus(false);
+ child->setFocus(true);
+ scopedChild->setFocus(true);
+ scope->setFocus(false);
+ QCOMPARE(root->hasFocus(), false);
+ QCOMPARE(child->hasFocus(), true);
+ QCOMPARE(scope->hasFocus(), false);
+ QCOMPARE(scopedChild->hasFocus(), true);
+ QCOMPARE(scopedChild2->hasFocus(), true);
+
+ delete root;
+}
+
+struct FocusData {
+ FocusData() : focus(false), activeFocus(false) {}
+
+ void set(bool f, bool af) { focus = f; activeFocus = af; }
+ bool focus;
+ bool activeFocus;
+};
+struct FocusState : public QHash<QQuickItem *, FocusData>
+{
+ FocusState() : activeFocusItem(0) {}
+ FocusState &operator<<(QQuickItem *item) {
+ insert(item, FocusData());
+ return *this;
+ }
+
+ void active(QQuickItem *i) {
+ activeFocusItem = i;
+ }
+ QQuickItem *activeFocusItem;
+};
+
+#define FVERIFY() \
+ do { \
+ if (focusState.activeFocusItem) { \
+ QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
+ if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
+ QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
+ else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
+ QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
+ } else { \
+ QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
+ } \
+ for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
+ iter != focusState.end(); \
+ iter++) { \
+ QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
+ QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
+ } \
+ } while (false)
+
+// Tests a simple set of top-level scoped items
+void tst_qquickitem::simpleFocus()
+{
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem *l1c1 = new TestItem(canvas.rootItem());
+ QQuickItem *l1c2 = new TestItem(canvas.rootItem());
+ QQuickItem *l1c3 = new TestItem(canvas.rootItem());
+
+ QQuickItem *l2c1 = new TestItem(l1c1);
+ QQuickItem *l2c2 = new TestItem(l1c1);
+ QQuickItem *l2c3 = new TestItem(l1c3);
+
+ FocusState focusState;
+ focusState << l1c1 << l1c2 << l1c3
+ << l2c1 << l2c2 << l2c3;
+ FVERIFY();
+
+ l1c1->setFocus(true);
+ focusState[l1c1].set(true, true);
+ focusState.active(l1c1);
+ FVERIFY();
+
+ l2c3->setFocus(true);
+ focusState[l1c1].set(false, false);
+ focusState[l2c3].set(true, true);
+ focusState.active(l2c3);
+ FVERIFY();
+
+ l1c3->setFocus(true);
+ focusState[l2c3].set(false, false);
+ focusState[l1c3].set(true, true);
+ focusState.active(l1c3);
+ FVERIFY();
+
+ l1c2->setFocus(false);
+ FVERIFY();
+
+ l1c3->setFocus(false);
+ focusState[l1c3].set(false, false);
+ focusState.active(0);
+ FVERIFY();
+
+ l2c1->setFocus(true);
+ focusState[l2c1].set(true, true);
+ focusState.active(l2c1);
+ FVERIFY();
+}
+
+// Items with a focus scope
+void tst_qquickitem::scopedFocus()
+{
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem *l1c1 = new TestItem(canvas.rootItem());
+ QQuickItem *l1c2 = new TestItem(canvas.rootItem());
+ QQuickItem *l1c3 = new TestItem(canvas.rootItem());
+
+ QQuickItem *l2c1 = new TestItem(l1c1);
+ QQuickItem *l2c2 = new TestItem(l1c1);
+ QQuickItem *l2c3 = new TestFocusScope(l1c3);
+
+ QQuickItem *l3c1 = new TestItem(l2c3);
+ QQuickItem *l3c2 = new TestFocusScope(l2c3);
+
+ QQuickItem *l4c1 = new TestItem(l3c2);
+ QQuickItem *l4c2 = new TestItem(l3c2);
+
+ FocusState focusState;
+ focusState << l1c1 << l1c2 << l1c3
+ << l2c1 << l2c2 << l2c3
+ << l3c1 << l3c2
+ << l4c1 << l4c2;
+ FVERIFY();
+
+ l4c2->setFocus(true);
+ focusState[l4c2].set(true, false);
+ FVERIFY();
+
+ l4c1->setFocus(true);
+ focusState[l4c2].set(false, false);
+ focusState[l4c1].set(true, false);
+ FVERIFY();
+
+ l1c1->setFocus(true);
+ focusState[l1c1].set(true, true);
+ focusState.active(l1c1);
+ FVERIFY();
+
+ l3c2->setFocus(true);
+ focusState[l3c2].set(true, false);
+ FVERIFY();
+
+ l2c3->setFocus(true);
+ focusState[l1c1].set(false, false);
+ focusState[l2c3].set(true, true);
+ focusState[l3c2].set(true, true);
+ focusState[l4c1].set(true, true);
+ focusState.active(l4c1);
+ FVERIFY();
+
+ l3c2->setFocus(false);
+ focusState[l3c2].set(false, false);
+ focusState[l4c1].set(true, false);
+ focusState.active(l2c3);
+ FVERIFY();
+
+ l3c2->setFocus(true);
+ focusState[l3c2].set(true, true);
+ focusState[l4c1].set(true, true);
+ focusState.active(l4c1);
+ FVERIFY();
+
+ l4c1->setFocus(false);
+ focusState[l4c1].set(false, false);
+ focusState.active(l3c2);
+ FVERIFY();
+
+ l1c3->setFocus(true);
+ focusState[l1c3].set(true, true);
+ focusState[l2c3].set(false, false);
+ focusState[l3c2].set(true, false);
+ focusState.active(l1c3);
+ FVERIFY();
+}
+
+// Tests focus corrects itself when a tree is added to a canvas for the first time
+void tst_qquickitem::addedToCanvas()
+{
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem *item = new TestItem;
+
+ FocusState focusState;
+ focusState << item;
+
+ item->setFocus(true);
+ focusState[item].set(true, false);
+ FVERIFY();
+
+ item->setParentItem(canvas.rootItem());
+ focusState[item].set(true, true);
+ focusState.active(item);
+ FVERIFY();
+ }
+
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem *item = new TestItem(canvas.rootItem());
+
+ QQuickItem *tree = new TestItem;
+ QQuickItem *c1 = new TestItem(tree);
+ QQuickItem *c2 = new TestItem(tree);
+
+ FocusState focusState;
+ focusState << item << tree << c1 << c2;
+
+ item->setFocus(true);
+ c1->setFocus(true);
+ c2->setFocus(true);
+ focusState[item].set(true, true);
+ focusState[c1].set(true, false);
+ focusState[c2].set(true, false);
+ focusState.active(item);
+ FVERIFY();
+
+ tree->setParentItem(item);
+ focusState[c1].set(false, false);
+ focusState[c2].set(false, false);
+ FVERIFY();
+ }
+
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem *tree = new TestItem;
+ QQuickItem *c1 = new TestItem(tree);
+ QQuickItem *c2 = new TestItem(tree);
+
+ FocusState focusState;
+ focusState << tree << c1 << c2;
+ c1->setFocus(true);
+ c2->setFocus(true);
+ focusState[c1].set(true, false);
+ focusState[c2].set(true, false);
+ FVERIFY();
+
+ tree->setParentItem(canvas.rootItem());
+ focusState[c1].set(true, true);
+ focusState[c2].set(false, false);
+ focusState.active(c1);
+ FVERIFY();
+ }
+
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *tree = new TestFocusScope;
+ QQuickItem *c1 = new TestItem(tree);
+ QQuickItem *c2 = new TestItem(tree);
+
+ FocusState focusState;
+ focusState << tree << c1 << c2;
+ c1->setFocus(true);
+ c2->setFocus(true);
+ focusState[c1].set(true, false);
+ focusState[c2].set(true, false);
+ FVERIFY();
+
+ tree->setParentItem(canvas.rootItem());
+ focusState[c1].set(true, false);
+ focusState[c2].set(false, false);
+ FVERIFY();
+
+ tree->setFocus(true);
+ focusState[tree].set(true, true);
+ focusState[c1].set(true, true);
+ focusState.active(c1);
+ FVERIFY();
+ }
+
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *tree = new TestFocusScope;
+ QQuickItem *c1 = new TestItem(tree);
+ QQuickItem *c2 = new TestItem(tree);
+
+ FocusState focusState;
+ focusState << tree << c1 << c2;
+ tree->setFocus(true);
+ c1->setFocus(true);
+ c2->setFocus(true);
+ focusState[tree].set(true, false);
+ focusState[c1].set(true, 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);
+ FVERIFY();
+ }
+
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+ QQuickItem *tree = new TestFocusScope;
+ QQuickItem *c1 = new TestItem(tree);
+ QQuickItem *c2 = new TestItem(tree);
+
+ FocusState focusState;
+ focusState << child << tree << c1 << c2;
+ child->setFocus(true);
+ tree->setFocus(true);
+ c1->setFocus(true);
+ c2->setFocus(true);
+ focusState[child].set(true, true);
+ focusState[tree].set(true, false);
+ focusState[c1].set(true, 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);
+ FVERIFY();
+
+ tree->setFocus(true);
+ focusState[child].set(false, false);
+ focusState[tree].set(true, true);
+ focusState[c1].set(true, true);
+ focusState.active(c1);
+ FVERIFY();
+ }
+}
+
+void tst_qquickitem::changeParent()
+{
+ // Parent to no parent
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+
+ FocusState focusState;
+ focusState << child;
+ FVERIFY();
+
+ child->setFocus(true);
+ focusState[child].set(true, true);
+ focusState.active(child);
+ FVERIFY();
+
+ child->setParentItem(0);
+ focusState[child].set(true, false);
+ focusState.active(0);
+ FVERIFY();
+ }
+
+ // Different parent, same focus scope
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+ QQuickItem *child2 = new TestItem(canvas.rootItem());
+
+ FocusState focusState;
+ focusState << child << child2;
+ FVERIFY();
+
+ child->setFocus(true);
+ focusState[child].set(true, true);
+ focusState.active(child);
+ FVERIFY();
+
+ child->setParentItem(child2);
+ FVERIFY();
+ }
+
+ // Different parent, different focus scope
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+ QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
+ QQuickItem *item = new TestItem(child);
+
+ FocusState focusState;
+ focusState << child << child2 << item;
+ FVERIFY();
+
+ item->setFocus(true);
+ focusState[item].set(true, true);
+ focusState.active(item);
+ FVERIFY();
+
+ item->setParentItem(child2);
+ focusState[item].set(true, false);
+ focusState.active(0);
+ FVERIFY();
+ }
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+ QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
+ QQuickItem *item = new TestItem(child2);
+
+ FocusState focusState;
+ focusState << child << child2 << item;
+ FVERIFY();
+
+ item->setFocus(true);
+ focusState[item].set(true, false);
+ focusState.active(0);
+ FVERIFY();
+
+ item->setParentItem(child);
+ focusState[item].set(true, true);
+ focusState.active(item);
+ FVERIFY();
+ }
+ {
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ QQuickItem *child = new TestItem(canvas.rootItem());
+ QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
+ QQuickItem *item = new TestItem(child2);
+
+ FocusState focusState;
+ focusState << child << child2 << item;
+ FVERIFY();
+
+ child->setFocus(true);
+ item->setFocus(true);
+ focusState[child].set(true, true);
+ focusState[item].set(true, false);
+ focusState.active(child);
+ FVERIFY();
+
+ item->setParentItem(child);
+ focusState[item].set(false, false);
+ FVERIFY();
+ }
+
+}
+
+void tst_qquickitem::constructor()
+{
+ QQuickItem *root = new QQuickItem;
+ QVERIFY(root->parent() == 0);
+ QVERIFY(root->parentItem() == 0);
+
+ QQuickItem *child1 = new QQuickItem(root);
+ QVERIFY(child1->parent() == root);
+ QVERIFY(child1->parentItem() == root);
+ QCOMPARE(root->childItems().count(), 1);
+ QCOMPARE(root->childItems().at(0), child1);
+
+ QQuickItem *child2 = new QQuickItem(root);
+ QVERIFY(child2->parent() == root);
+ QVERIFY(child2->parentItem() == root);
+ QCOMPARE(root->childItems().count(), 2);
+ QCOMPARE(root->childItems().at(0), child1);
+ QCOMPARE(root->childItems().at(1), child2);
+
+ delete root;
+}
+
+void tst_qquickitem::setParentItem()
+{
+ QQuickItem *root = new QQuickItem;
+ QVERIFY(root->parent() == 0);
+ QVERIFY(root->parentItem() == 0);
+
+ QQuickItem *child1 = new QQuickItem;
+ QVERIFY(child1->parent() == 0);
+ QVERIFY(child1->parentItem() == 0);
+
+ child1->setParentItem(root);
+ QVERIFY(child1->parent() == 0);
+ QVERIFY(child1->parentItem() == root);
+ QCOMPARE(root->childItems().count(), 1);
+ QCOMPARE(root->childItems().at(0), child1);
+
+ QQuickItem *child2 = new QQuickItem;
+ QVERIFY(child2->parent() == 0);
+ QVERIFY(child2->parentItem() == 0);
+ child2->setParentItem(root);
+ QVERIFY(child2->parent() == 0);
+ QVERIFY(child2->parentItem() == root);
+ QCOMPARE(root->childItems().count(), 2);
+ QCOMPARE(root->childItems().at(0), child1);
+ QCOMPARE(root->childItems().at(1), child2);
+
+ child1->setParentItem(0);
+ QVERIFY(child1->parent() == 0);
+ QVERIFY(child1->parentItem() == 0);
+ QCOMPARE(root->childItems().count(), 1);
+ QCOMPARE(root->childItems().at(0), child2);
+
+ delete root;
+
+ QVERIFY(child1->parent() == 0);
+ QVERIFY(child1->parentItem() == 0);
+ QVERIFY(child2->parent() == 0);
+ QVERIFY(child2->parentItem() == 0);
+
+ delete child1;
+ delete child2;
+}
+
+void tst_qquickitem::visible()
+{
+ QQuickItem *root = new QQuickItem;
+
+ QQuickItem *child1 = new QQuickItem;
+ child1->setParentItem(root);
+
+ QQuickItem *child2 = new QQuickItem;
+ child2->setParentItem(root);
+
+ QVERIFY(child1->isVisible());
+ QVERIFY(child2->isVisible());
+
+ root->setVisible(false);
+ QVERIFY(!child1->isVisible());
+ QVERIFY(!child2->isVisible());
+
+ root->setVisible(true);
+ QVERIFY(child1->isVisible());
+ QVERIFY(child2->isVisible());
+
+ child1->setVisible(false);
+ QVERIFY(!child1->isVisible());
+ QVERIFY(child2->isVisible());
+
+ child2->setParentItem(child1);
+ QVERIFY(!child1->isVisible());
+ QVERIFY(!child2->isVisible());
+
+ child2->setParentItem(root);
+ QVERIFY(!child1->isVisible());
+ QVERIFY(child2->isVisible());
+
+ delete root;
+ delete child1;
+ delete child2;
+}
+
+void tst_qquickitem::enabled()
+{
+ QQuickItem *root = new QQuickItem;
+
+ QQuickItem *child1 = new QQuickItem;
+ child1->setParentItem(root);
+
+ QQuickItem *child2 = new QQuickItem;
+ child2->setParentItem(root);
+
+ QVERIFY(child1->isEnabled());
+ QVERIFY(child2->isEnabled());
+
+ root->setEnabled(false);
+ QVERIFY(!child1->isEnabled());
+ QVERIFY(!child2->isEnabled());
+
+ root->setEnabled(true);
+ QVERIFY(child1->isEnabled());
+ QVERIFY(child2->isEnabled());
+
+ child1->setEnabled(false);
+ QVERIFY(!child1->isEnabled());
+ QVERIFY(child2->isEnabled());
+
+ child2->setParentItem(child1);
+ QVERIFY(!child1->isEnabled());
+ QVERIFY(!child2->isEnabled());
+
+ child2->setParentItem(root);
+ QVERIFY(!child1->isEnabled());
+ QVERIFY(child2->isEnabled());
+
+ delete root;
+ delete child1;
+ delete child2;
+}
+
+void tst_qquickitem::mouseGrab()
+{
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(200, 200);
+ canvas->show();
+
+ TestItem *child1 = new TestItem;
+ child1->setAcceptedMouseButtons(Qt::LeftButton);
+ child1->setSize(QSizeF(200, 100));
+ child1->setParentItem(canvas->rootItem());
+
+ TestItem *child2 = new TestItem;
+ child2->setAcceptedMouseButtons(Qt::LeftButton);
+ child2->setY(51);
+ child2->setSize(QSizeF(200, 100));
+ child2->setParentItem(canvas->rootItem());
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(100);
+ QVERIFY(canvas->mouseGrabberItem() == child1);
+ QTest::qWait(100);
+
+ QCOMPARE(child1->pressCount, 1);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QVERIFY(canvas->mouseGrabberItem() == 0);
+ QCOMPARE(child1->releaseCount, 1);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QVERIFY(canvas->mouseGrabberItem() == child1);
+ QCOMPARE(child1->pressCount, 2);
+ child1->setEnabled(false);
+ QVERIFY(canvas->mouseGrabberItem() == 0);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QCOMPARE(child1->releaseCount, 1);
+ child1->setEnabled(true);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QVERIFY(canvas->mouseGrabberItem() == child1);
+ QCOMPARE(child1->pressCount, 3);
+ child1->setVisible(false);
+ QVERIFY(canvas->mouseGrabberItem() == 0);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QCOMPARE(child1->releaseCount, 1);
+ child1->setVisible(true);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QVERIFY(canvas->mouseGrabberItem() == child1);
+ QCOMPARE(child1->pressCount, 4);
+ child2->grabMouse();
+ QVERIFY(canvas->mouseGrabberItem() == child2);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QCOMPARE(child1->releaseCount, 1);
+ QCOMPARE(child2->releaseCount, 1);
+
+ child2->grabMouse();
+ QVERIFY(canvas->mouseGrabberItem() == child2);
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QCOMPARE(child1->pressCount, 4);
+ QCOMPARE(child2->pressCount, 1);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::qWait(50);
+ QCOMPARE(child1->releaseCount, 1);
+ QCOMPARE(child2->releaseCount, 2);
+
+ delete child1;
+ delete child2;
+ delete canvas;
+}
+
+void tst_qquickitem::polishOutsideAnimation()
+{
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(200, 200);
+ canvas->show();
+
+ TestPolishItem *item = new TestPolishItem(canvas->rootItem());
+ item->setSize(QSizeF(200, 100));
+ QTest::qWait(50);
+ QTRY_VERIFY(item->wasPolished);
+
+ delete item;
+ delete canvas;
+}
+
+void tst_qquickitem::wheelEvent_data()
+{
+ QTest::addColumn<bool>("visible");
+ QTest::addColumn<bool>("enabled");
+
+ QTest::newRow("visible and enabled") << true << true;
+ QTest::newRow("visible and disabled") << true << false;
+ QTest::newRow("invisible and enabled") << false << true;
+ QTest::newRow("invisible and disabled") << false << false;
+}
+
+void tst_qquickitem::wheelEvent()
+{
+ QFETCH(bool, visible);
+ QFETCH(bool, enabled);
+
+ const bool shouldReceiveWheelEvents = visible && enabled;
+
+ QQuickCanvas *canvas = new QQuickCanvas;
+ canvas->resize(200, 200);
+ canvas->show();
+
+ TestItem *item = new TestItem;
+ item->setSize(QSizeF(200, 100));
+ item->setParentItem(canvas->rootItem());
+
+ item->setEnabled(enabled);
+ item->setVisible(visible);
+
+ QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
+ event.setAccepted(false);
+ QApplication::sendEvent(canvas, &event);
+
+ if (shouldReceiveWheelEvents) {
+ QVERIFY(event.isAccepted());
+ QCOMPARE(item->wheelCount, 1);
+ } else {
+ QVERIFY(!event.isAccepted());
+ QCOMPARE(item->wheelCount, 0);
+ }
+
+ delete canvas;
+}
+
+class HoverItem : public QQuickItem
+{
+Q_OBJECT
+public:
+ HoverItem(QQuickItem *parent = 0)
+ : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
+ { }
+ void resetCounters() {
+ hoverEnterCount = 0;
+ hoverMoveCount = 0;
+ hoverLeaveCount = 0;
+ }
+ int hoverEnterCount;
+ int hoverMoveCount;
+ int hoverLeaveCount;
+protected:
+ virtual void hoverEnterEvent(QHoverEvent *event) {
+ event->accept();
+ ++hoverEnterCount;
+ }
+ virtual void hoverMoveEvent(QHoverEvent *event) {
+ event->accept();
+ ++hoverMoveCount;
+ }
+ virtual void hoverLeaveEvent(QHoverEvent *event) {
+ event->accept();
+ ++hoverLeaveCount;
+ }
+};
+
+void tst_qquickitem::hoverEvent_data()
+{
+ QTest::addColumn<bool>("visible");
+ QTest::addColumn<bool>("enabled");
+ QTest::addColumn<bool>("acceptHoverEvents");
+
+ QTest::newRow("visible, enabled, accept hover") << true << true << true;
+ QTest::newRow("visible, disabled, accept hover") << true << false << true;
+ QTest::newRow("invisible, enabled, accept hover") << false << true << true;
+ QTest::newRow("invisible, disabled, accept hover") << false << false << true;
+
+ QTest::newRow("visible, enabled, not accept hover") << true << true << false;
+ QTest::newRow("visible, disabled, not accept hover") << true << false << false;
+ QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
+ QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
+}
+
+// ### For some unknown reason QTest::mouseMove() isn't working correctly.
+static void sendMouseMove(QObject *object, const QPoint &position)
+{
+ QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
+ QApplication::sendEvent(object, &moveEvent);
+}
+
+void tst_qquickitem::hoverEvent()
+{
+ QFETCH(bool, visible);
+ QFETCH(bool, enabled);
+ QFETCH(bool, acceptHoverEvents);
+
+ QQuickCanvas *canvas = new QQuickCanvas();
+ canvas->resize(200, 200);
+ canvas->show();
+
+ HoverItem *item = new HoverItem;
+ item->setSize(QSizeF(100, 100));
+ item->setParentItem(canvas->rootItem());
+
+ item->setEnabled(enabled);
+ item->setVisible(visible);
+ item->setAcceptHoverEvents(acceptHoverEvents);
+
+ const QPoint outside(150, 150);
+ const QPoint inside(50, 50);
+ const QPoint anotherInside(51, 51);
+
+ sendMouseMove(canvas, outside);
+ item->resetCounters();
+
+ // Enter, then move twice inside, then leave.
+ sendMouseMove(canvas, inside);
+ sendMouseMove(canvas, anotherInside);
+ sendMouseMove(canvas, inside);
+ sendMouseMove(canvas, outside);
+
+ const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
+ if (shouldReceiveHoverEvents) {
+ QCOMPARE(item->hoverEnterCount, 1);
+ QCOMPARE(item->hoverMoveCount, 2);
+ QCOMPARE(item->hoverLeaveCount, 1);
+ } else {
+ QCOMPARE(item->hoverEnterCount, 0);
+ QCOMPARE(item->hoverMoveCount, 0);
+ QCOMPARE(item->hoverLeaveCount, 0);
+ }
+
+ delete canvas;
+}
+
+void tst_qquickitem::hoverEventInParent()
+{
+ QQuickCanvas *canvas = new QQuickCanvas();
+ canvas->resize(200, 200);
+ canvas->show();
+
+ HoverItem *parentItem = new HoverItem(canvas->rootItem());
+ parentItem->setSize(QSizeF(200, 200));
+ parentItem->setAcceptHoverEvents(true);
+
+ HoverItem *leftItem = new HoverItem(parentItem);
+ leftItem->setSize(QSizeF(100, 200));
+ leftItem->setAcceptHoverEvents(true);
+
+ HoverItem *rightItem = new HoverItem(parentItem);
+ rightItem->setSize(QSizeF(100, 200));
+ rightItem->setPos(QPointF(100, 0));
+ rightItem->setAcceptHoverEvents(true);
+
+ const QPoint insideLeft(50, 100);
+ const QPoint insideRight(150, 100);
+
+ sendMouseMove(canvas, insideLeft);
+ parentItem->resetCounters();
+ leftItem->resetCounters();
+ rightItem->resetCounters();
+
+ sendMouseMove(canvas, insideRight);
+ QCOMPARE(parentItem->hoverEnterCount, 0);
+ QCOMPARE(parentItem->hoverLeaveCount, 0);
+ QCOMPARE(leftItem->hoverEnterCount, 0);
+ QCOMPARE(leftItem->hoverLeaveCount, 1);
+ QCOMPARE(rightItem->hoverEnterCount, 1);
+ QCOMPARE(rightItem->hoverLeaveCount, 0);
+
+ sendMouseMove(canvas, insideLeft);
+ QCOMPARE(parentItem->hoverEnterCount, 0);
+ QCOMPARE(parentItem->hoverLeaveCount, 0);
+ QCOMPARE(leftItem->hoverEnterCount, 1);
+ QCOMPARE(leftItem->hoverLeaveCount, 1);
+ QCOMPARE(rightItem->hoverEnterCount, 1);
+ QCOMPARE(rightItem->hoverLeaveCount, 1);
+
+ delete canvas;
+}
+
+void tst_qquickitem::paintOrder_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<int>("op");
+ QTest::addColumn<QVariant>("param1");
+ QTest::addColumn<QVariant>("param2");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("test 1 noop") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(NoOp) << QVariant() << QVariant()
+ << (QStringList() << "1" << "2" << "3");
+ QTest::newRow("test 1 add") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(Append) << QVariant("new") << QVariant()
+ << (QStringList() << "1" << "2" << "3" << "new");
+ QTest::newRow("test 1 remove") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(Remove) << QVariant(1) << QVariant()
+ << (QStringList() << "1" << "3");
+ QTest::newRow("test 1 stack before") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(StackBefore) << QVariant(2) << QVariant(1)
+ << (QStringList() << "1" << "3" << "2");
+ QTest::newRow("test 1 stack after") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(StackAfter) << QVariant(0) << QVariant(1)
+ << (QStringList() << "2" << "1" << "3");
+ QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(SetZ) << QVariant(1) << QVariant(qreal(1.))
+ << (QStringList() << "1" << "3" << "2");
+
+ QTest::newRow("test 2 noop") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(NoOp) << QVariant() << QVariant()
+ << (QStringList() << "1" << "3" << "2");
+ QTest::newRow("test 2 add") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(Append) << QVariant("new") << QVariant()
+ << (QStringList() << "1" << "3" << "new" << "2");
+ QTest::newRow("test 2 remove 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(Remove) << QVariant(1) << QVariant()
+ << (QStringList() << "1" << "3");
+ QTest::newRow("test 2 remove 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(Remove) << QVariant(2) << QVariant()
+ << (QStringList() << "1" << "2");
+ QTest::newRow("test 2 stack before 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(StackBefore) << QVariant(1) << QVariant(0)
+ << (QStringList() << "1" << "3" << "2");
+ QTest::newRow("test 2 stack before 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(StackBefore) << QVariant(2) << QVariant(0)
+ << (QStringList() << "3" << "1" << "2");
+ QTest::newRow("test 2 stack after 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(StackAfter) << QVariant(0) << QVariant(1)
+ << (QStringList() << "1" << "3" << "2");
+ QTest::newRow("test 2 stack after 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml"))
+ << int(StackAfter) << QVariant(0) << QVariant(2)
+ << (QStringList() << "3" << "1" << "2");
+ QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml"))
+ << int(SetZ) << QVariant(2) << QVariant(qreal(2.))
+ << (QStringList() << "1" << "2" << "3");
+}
+
+void tst_qquickitem::paintOrder()
+{
+ QFETCH(QUrl, source);
+ QFETCH(int, op);
+ QFETCH(QVariant, param1);
+ QFETCH(QVariant, param2);
+ QFETCH(QStringList, expected);
+
+ QQuickView view;
+ view.setSource(source);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+ QVERIFY(root);
+
+ switch (op) {
+ case Append: {
+ QQuickItem *item = new QQuickItem(root);
+ item->setObjectName(param1.toString());
+ }
+ break;
+ case Remove: {
+ QQuickItem *item = root->childItems().at(param1.toInt());
+ delete item;
+ }
+ break;
+ case StackBefore: {
+ QQuickItem *item1 = root->childItems().at(param1.toInt());
+ QQuickItem *item2 = root->childItems().at(param2.toInt());
+ item1->stackBefore(item2);
+ }
+ break;
+ case StackAfter: {
+ QQuickItem *item1 = root->childItems().at(param1.toInt());
+ QQuickItem *item2 = root->childItems().at(param2.toInt());
+ item1->stackAfter(item2);
+ }
+ break;
+ case SetZ: {
+ QQuickItem *item = root->childItems().at(param1.toInt());
+ item->setZ(param2.toReal());
+ }
+ break;
+ default:
+ break;
+ }
+
+ QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
+
+ QStringList items;
+ for (int i = 0; i < list.count(); ++i)
+ items << list.at(i)->objectName();
+
+ QCOMPARE(items, expected);
+}
+
+
+QTEST_MAIN(tst_qquickitem)
+
+#include "tst_qquickitem.moc"
diff --git a/tests/auto/declarative/qquickitem2/data/childrenProperty.qml b/tests/auto/qtquick2/qquickitem2/data/childrenProperty.qml
index 85ddbc1446..85ddbc1446 100644
--- a/tests/auto/declarative/qquickitem2/data/childrenProperty.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/childrenProperty.qml
diff --git a/tests/auto/declarative/qquickitem2/data/childrenRect.qml b/tests/auto/qtquick2/qquickitem2/data/childrenRect.qml
index ebc57aefbe..ebc57aefbe 100644
--- a/tests/auto/declarative/qquickitem2/data/childrenRect.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/childrenRect.qml
diff --git a/tests/auto/declarative/qquickitem2/data/childrenRectBug.qml b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug.qml
index 86a4f19c5c..86a4f19c5c 100644
--- a/tests/auto/declarative/qquickitem2/data/childrenRectBug.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug.qml
diff --git a/tests/auto/declarative/qquickitem2/data/childrenRectBug2.qml b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug2.qml
index 6e80ed28af..6e80ed28af 100644
--- a/tests/auto/declarative/qquickitem2/data/childrenRectBug2.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug2.qml
diff --git a/tests/auto/declarative/qquickitem2/data/childrenRectBug3.qml b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug3.qml
index 518e76509e..518e76509e 100644
--- a/tests/auto/declarative/qquickitem2/data/childrenRectBug3.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/childrenRectBug3.qml
diff --git a/tests/auto/declarative/qquickitem2/data/implicitsize.qml b/tests/auto/qtquick2/qquickitem2/data/implicitsize.qml
index cc6aaf7d60..cc6aaf7d60 100644
--- a/tests/auto/declarative/qquickitem2/data/implicitsize.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/implicitsize.qml
diff --git a/tests/auto/declarative/qquickitem2/data/keynavigationtest.qml b/tests/auto/qtquick2/qquickitem2/data/keynavigationtest.qml
index aacb621fb0..aacb621fb0 100644
--- a/tests/auto/declarative/qquickitem2/data/keynavigationtest.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/keynavigationtest.qml
diff --git a/tests/auto/declarative/qquickitem2/data/keynavigationtest_implicit.qml b/tests/auto/qtquick2/qquickitem2/data/keynavigationtest_implicit.qml
index 92d4ae23de..92d4ae23de 100644
--- a/tests/auto/declarative/qquickitem2/data/keynavigationtest_implicit.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/keynavigationtest_implicit.qml
diff --git a/tests/auto/declarative/qquickitem2/data/keyspriority.qml b/tests/auto/qtquick2/qquickitem2/data/keyspriority.qml
index 114cf0488a..114cf0488a 100644
--- a/tests/auto/declarative/qquickitem2/data/keyspriority.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/keyspriority.qml
diff --git a/tests/auto/declarative/qquickitem2/data/keystest.qml b/tests/auto/qtquick2/qquickitem2/data/keystest.qml
index c70e0061f5..c70e0061f5 100644
--- a/tests/auto/declarative/qquickitem2/data/keystest.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/keystest.qml
diff --git a/tests/auto/declarative/qquickitem2/data/layoutmirroring.qml b/tests/auto/qtquick2/qquickitem2/data/layoutmirroring.qml
index 036819740c..036819740c 100644
--- a/tests/auto/declarative/qquickitem2/data/layoutmirroring.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/layoutmirroring.qml
diff --git a/tests/auto/declarative/qquickitem2/data/mapCoordinates.qml b/tests/auto/qtquick2/qquickitem2/data/mapCoordinates.qml
index 566cb220ff..566cb220ff 100644
--- a/tests/auto/declarative/qquickitem2/data/mapCoordinates.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/mapCoordinates.qml
diff --git a/tests/auto/declarative/qquickitem2/data/propertychanges.qml b/tests/auto/qtquick2/qquickitem2/data/propertychanges.qml
index 3fa5ea9c23..3fa5ea9c23 100644
--- a/tests/auto/declarative/qquickitem2/data/propertychanges.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/propertychanges.qml
diff --git a/tests/auto/declarative/qquickitem2/data/qtbug_16871.qml b/tests/auto/qtquick2/qquickitem2/data/qtbug_16871.qml
index f1e7377730..f1e7377730 100644
--- a/tests/auto/declarative/qquickitem2/data/qtbug_16871.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/qtbug_16871.qml
diff --git a/tests/auto/declarative/qquickitem2/data/resourcesProperty.qml b/tests/auto/qtquick2/qquickitem2/data/resourcesProperty.qml
index b8f18bb375..b8f18bb375 100644
--- a/tests/auto/declarative/qquickitem2/data/resourcesProperty.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/resourcesProperty.qml
diff --git a/tests/auto/declarative/qquickitem2/data/transformCrash.qml b/tests/auto/qtquick2/qquickitem2/data/transformCrash.qml
index 284e85f0e0..284e85f0e0 100644
--- a/tests/auto/declarative/qquickitem2/data/transformCrash.qml
+++ b/tests/auto/qtquick2/qquickitem2/data/transformCrash.qml
diff --git a/tests/auto/qtquick2/qquickitem2/qquickitem2.pro b/tests/auto/qtquick2/qquickitem2/qquickitem2.pro
new file mode 100644
index 0000000000..2a1d63633c
--- /dev/null
+++ b/tests/auto/qtquick2/qquickitem2/qquickitem2.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickitem2
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickitem.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qquickitem2/tst_qquickitem.cpp b/tests/auto/qtquick2/qquickitem2/tst_qquickitem.cpp
new file mode 100644
index 0000000000..f04b9bac36
--- /dev/null
+++ b/tests/auto/qtquick2/qquickitem2/tst_qquickitem.cpp
@@ -0,0 +1,1254 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qquickitem_p.h>
+#include "../../shared/util.h"
+
+class tst_QQuickItem : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickItem();
+
+private slots:
+ void initTestCase();
+ void keys();
+ void keysProcessingOrder();
+ void keyNavigation();
+ void keyNavigation_RightToLeft();
+ void keyNavigation_skipNotVisible();
+ void keyNavigation_implicitSetting();
+ void layoutMirroring();
+ void layoutMirroringIllegalParent();
+ void smooth();
+ void clip();
+ void mapCoordinates();
+ void mapCoordinates_data();
+ void propertyChanges();
+ void transforms();
+ void transforms_data();
+ void childrenRect();
+ void childrenRectBug();
+ void childrenRectBug2();
+ void childrenRectBug3();
+
+ void childrenProperty();
+ void resourcesProperty();
+
+ void transformCrash();
+ void implicitSize();
+ void qtbug_16871();
+private:
+ QDeclarativeEngine engine;
+};
+
+template<typename T>
+T *findItem(QQuickItem *parent, const QString &objectName)
+{
+ if (!parent)
+ return 0;
+
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QQuickItem::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ return static_cast<T*>(item);
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+class KeysTestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool processLast READ processLast NOTIFY processLastChanged)
+
+public:
+ KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0), mLast(false) {}
+
+ void reset() {
+ mKey = 0;
+ mText = QString();
+ mModifiers = 0;
+ mForwardedKey = 0;
+ }
+
+ bool processLast() const { return mLast; }
+ void setProcessLast(bool b) {
+ if (b != mLast) {
+ mLast = b;
+ emit processLastChanged();
+ }
+ }
+
+public slots:
+ void keyPress(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void keyRelease(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void forwardedKey(int key) {
+ mForwardedKey = key;
+ }
+
+signals:
+ void processLastChanged();
+
+public:
+ int mKey;
+ QString mText;
+ int mModifiers;
+ int mForwardedKey;
+ bool mLast;
+
+private:
+};
+
+class KeyTestItem : public QQuickItem
+{
+ Q_OBJECT
+public:
+ KeyTestItem(QQuickItem *parent=0) : QQuickItem(parent), mKey(0) {}
+
+protected:
+ void keyPressEvent(QKeyEvent *e) {
+ mKey = e->key();
+
+ if (e->key() == Qt::Key_A)
+ e->accept();
+ else
+ e->ignore();
+ }
+
+ void keyReleaseEvent(QKeyEvent *e) {
+ if (e->key() == Qt::Key_B)
+ e->accept();
+ else
+ e->ignore();
+ }
+
+public:
+ int mKey;
+};
+
+QML_DECLARE_TYPE(KeyTestItem);
+
+
+tst_QQuickItem::tst_QQuickItem()
+{
+}
+
+void tst_QQuickItem::initTestCase()
+{
+ qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
+}
+
+void tst_QQuickItem::keys()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ KeysTestObject *testObject = new KeysTestObject;
+ canvas->rootContext()->setContextProperty("keysTestObject", testObject);
+
+ canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
+ canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(true));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keystest.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QVERIFY(canvas->rootObject());
+ QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mText, QLatin1String("Return"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_0));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
+ QCOMPARE(testObject->mText, QLatin1String("0"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_9));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
+ QCOMPARE(testObject->mText, QLatin1String("9"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
+ QCOMPARE(testObject->mText, QLatin1String("Tab"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
+ QCOMPARE(testObject->mText, QLatin1String("Backtab"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(false));
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, 0);
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
+ QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), false);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, 0);
+ QVERIFY(!key.isAccepted());
+
+ canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
+ QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Return));
+ QVERIFY(key.isAccepted());
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickItem::keysProcessingOrder()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ KeysTestObject *testObject = new KeysTestObject;
+ canvas->rootContext()->setContextProperty("keysTestObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keyspriority.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ KeyTestItem *testItem = qobject_cast<KeyTestItem*>(canvas->rootObject());
+ QVERIFY(testItem);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ testObject->setProcessLast(true);
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, 0);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "B", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_B));
+ QCOMPARE(testObject->mText, QLatin1String("B"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyRelease, Qt::Key_B, Qt::NoModifier, "B", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, 0);
+ QVERIFY(key.isAccepted());
+
+ delete canvas;
+ delete testObject;
+}
+
+QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString)
+{
+ QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
+ QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
+ return itemPrivate;
+}
+
+QVariant childProperty(QQuickItem *rootItem, const char * itemString, const char * property)
+{
+ QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
+ return item->property(property);
+}
+
+bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
+{
+ QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
+ QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
+ return itemPrivate->anchors()->mirrored();
+}
+
+void tst_QQuickItem::layoutMirroring()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("layoutmirroring.qml")));
+ canvas->show();
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootItem);
+ QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
+ QVERIFY(rootPrivate);
+
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
+
+ QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
+ QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
+ QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
+ QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
+ QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
+ QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
+
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
+
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
+ QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
+
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
+
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
+
+ // load dynamic content using Loader that needs to inherit mirroring
+ rootItem->setProperty("state", "newContent");
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
+
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
+
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
+
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
+
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+
+ // disable inheritance
+ rootItem->setProperty("childrenInherit", false);
+
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
+
+ // re-enable inheritance
+ rootItem->setProperty("childrenInherit", true);
+
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
+ QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+
+ //
+ // dynamic parenting
+ //
+ QQuickItem *parentItem1 = new QQuickItem();
+ QQuickItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
+ QQuickItemPrivate::get(parentItem1)->isMirrorImplicit = false;
+ QQuickItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
+ QQuickItemPrivate::get(parentItem1)->resolveLayoutMirror();
+
+ // inherit in constructor
+ QQuickItem *childItem1 = new QQuickItem(parentItem1);
+ QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
+ QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
+
+ // inherit through a parent change
+ QQuickItem *childItem2 = new QQuickItem();
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+ childItem2->setParentItem(parentItem1);
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
+
+ // stop inherting through a parent change
+ QQuickItem *parentItem2 = new QQuickItem();
+ QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
+ QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
+ childItem2->setParentItem(parentItem2);
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
+ QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+
+ delete parentItem1;
+ delete parentItem2;
+}
+
+void tst_QQuickItem::layoutMirroringIllegalParent()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
+ QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_QQuickItem::keyNavigation()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ QVariant result;
+ QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
+ Q_RETURN_ARG(QVariant, result)));
+ QVERIFY(result.toBool());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // down
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // left
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // up
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // tab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ delete canvas;
+}
+
+void tst_QQuickItem::keyNavigation_RightToLeft()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootItem);
+ QQuickItemPrivate* rootItemPrivate = QQuickItemPrivate::get(rootItem);
+
+ rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true
+ rootItemPrivate->isMirrorImplicit = false;
+ rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true
+ rootItemPrivate->resolveLayoutMirror();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ QVariant result;
+ QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
+ Q_RETURN_ARG(QVariant, result)));
+ QVERIFY(result.toBool());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // left
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ delete canvas;
+}
+
+void tst_QQuickItem::keyNavigation_skipNotVisible()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // Set item 2 to not visible
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // tab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ //Set item 3 to not visible
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+
+ // tab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ delete canvas;
+}
+
+void tst_QQuickItem::keyNavigation_implicitSetting()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("keynavigationtest_implicit.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ QVariant result;
+ QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
+ Q_RETURN_ARG(QVariant, result)));
+ QVERIFY(result.toBool());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // back to item1
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // down
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // move to item4
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // left
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // back to item4
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // up
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // back to item4
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // tab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // back to item4
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QQuickItem>(canvas->rootObject(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+
+ delete canvas;
+}
+
+void tst_QQuickItem::smooth()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0; Item { smooth: false; }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QSignalSpy spy(item, SIGNAL(smoothChanged(bool)));
+
+ QVERIFY(item);
+ QVERIFY(!item->smooth());
+
+ item->setSmooth(true);
+ QVERIFY(item->smooth());
+ QCOMPARE(spy.count(),1);
+ QList<QVariant> arguments = spy.first();
+ QVERIFY(arguments.count() == 1);
+ QVERIFY(arguments.at(0).toBool() == true);
+
+ item->setSmooth(true);
+ QCOMPARE(spy.count(),1);
+
+ item->setSmooth(false);
+ QVERIFY(!item->smooth());
+ QCOMPARE(spy.count(),2);
+ item->setSmooth(false);
+ QCOMPARE(spy.count(),2);
+
+ delete item;
+}
+
+void tst_QQuickItem::clip()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0\nItem { clip: false\n }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QSignalSpy spy(item, SIGNAL(clipChanged(bool)));
+
+ QVERIFY(item);
+ QVERIFY(!item->clip());
+
+ item->setClip(true);
+ QVERIFY(item->clip());
+
+ QList<QVariant> arguments = spy.first();
+ QVERIFY(arguments.count() == 1);
+ QVERIFY(arguments.at(0).toBool() == true);
+
+ QCOMPARE(spy.count(),1);
+ item->setClip(true);
+ QCOMPARE(spy.count(),1);
+
+ item->setClip(false);
+ QVERIFY(!item->clip());
+ QCOMPARE(spy.count(),2);
+ item->setClip(false);
+ QCOMPARE(spy.count(),2);
+
+ delete item;
+}
+
+void tst_QQuickItem::mapCoordinates()
+{
+ QFETCH(int, x);
+ QFETCH(int, y);
+
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(300, 300));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root != 0);
+ QQuickItem *a = findItem<QQuickItem>(canvas->rootObject(), "itemA");
+ QVERIFY(a != 0);
+ QQuickItem *b = findItem<QQuickItem>(canvas->rootObject(), "itemB");
+ QVERIFY(b != 0);
+
+ QVariant result;
+
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
+
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
+
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
+
+ QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromScene(QPointF(x, y)));
+
+ QString warning1 = QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")).toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
+ QString warning2 = QUrl::fromLocalFile(TESTDATA("mapCoordinates.qml")).toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QVERIFY(result.toBool());
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QVERIFY(result.toBool());
+
+ delete canvas;
+}
+
+void tst_QQuickItem::mapCoordinates_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+
+ for (int i=-20; i<=20; i+=10)
+ QTest::newRow(QTest::toString(i)) << i << i;
+}
+
+void tst_QQuickItem::transforms_data()
+{
+ QTest::addColumn<QByteArray>("qml");
+ QTest::addColumn<QTransform>("transform");
+ QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
+ << QTransform(1,0,0,0,1,0,10,20,1);
+ QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
+ << QTransform(0,1,0,-1,0,0,0,0,1);
+ QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2 }")
+ << QTransform(1.5,0,0,0,-2,0,0,0,1);
+ QTest::newRow("sequence") << QByteArray("[ Translate { x: 10; y: 20 }, Scale { xScale: 1.5; yScale: -2 } ]")
+ << QTransform(1,0,0,0,1,0,10,20,1) * QTransform(1.5,0,0,0,-2,0,0,0,1);
+}
+
+void tst_QQuickItem::transforms()
+{
+ QFETCH(QByteArray, qml);
+ QFETCH(QTransform, transform);
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(item->itemTransform(0,0), transform);
+}
+
+void tst_QQuickItem::childrenProperty()
+{
+ QDeclarativeComponent component(&engine, TESTDATA("childrenProperty.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->property("test1").toBool(), true);
+ QCOMPARE(o->property("test2").toBool(), true);
+ QCOMPARE(o->property("test3").toBool(), true);
+ QCOMPARE(o->property("test4").toBool(), true);
+ QCOMPARE(o->property("test5").toBool(), true);
+ delete o;
+}
+
+void tst_QQuickItem::resourcesProperty()
+{
+ QDeclarativeComponent component(&engine, TESTDATA("resourcesProperty.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->property("test1").toBool(), true);
+ QCOMPARE(o->property("test2").toBool(), true);
+ QCOMPARE(o->property("test3").toBool(), true);
+ QCOMPARE(o->property("test4").toBool(), true);
+ QCOMPARE(o->property("test5").toBool(), true);
+ delete o;
+}
+
+void tst_QQuickItem::propertyChanges()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(300, 300));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
+
+ QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item");
+ QQuickItem *parentItem = findItem<QQuickItem>(canvas->rootObject(), "parentItem");
+
+ QVERIFY(item);
+ QVERIFY(parentItem);
+
+ QSignalSpy parentSpy(item, SIGNAL(parentChanged(QQuickItem *)));
+ QSignalSpy widthSpy(item, SIGNAL(widthChanged()));
+ QSignalSpy heightSpy(item, SIGNAL(heightChanged()));
+ QSignalSpy baselineOffsetSpy(item, SIGNAL(baselineOffsetChanged(qreal)));
+ QSignalSpy childrenRectSpy(parentItem, SIGNAL(childrenRectChanged(QRectF)));
+ QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool)));
+ QSignalSpy wantsFocusSpy(parentItem, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy childrenChangedSpy(parentItem, SIGNAL(childrenChanged()));
+ QSignalSpy xSpy(item, SIGNAL(xChanged()));
+ QSignalSpy ySpy(item, SIGNAL(yChanged()));
+
+ item->setParentItem(parentItem);
+ item->setWidth(100.0);
+ item->setHeight(200.0);
+ item->setFocus(true);
+ item->setBaselineOffset(10.0);
+
+ QCOMPARE(item->parentItem(), parentItem);
+ QCOMPARE(parentSpy.count(),1);
+ QList<QVariant> parentArguments = parentSpy.first();
+ QVERIFY(parentArguments.count() == 1);
+ QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
+ QCOMPARE(childrenChangedSpy.count(),1);
+
+ item->setParentItem(parentItem);
+ QCOMPARE(childrenChangedSpy.count(),1);
+
+ QCOMPARE(item->width(), 100.0);
+ QCOMPARE(widthSpy.count(),1);
+
+ QCOMPARE(item->height(), 200.0);
+ QCOMPARE(heightSpy.count(),1);
+
+ QCOMPARE(item->baselineOffset(), 10.0);
+ QCOMPARE(baselineOffsetSpy.count(),1);
+ QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
+ QVERIFY(baselineOffsetArguments.count() == 1);
+ QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
+
+ QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
+ QCOMPARE(childrenRectSpy.count(),1);
+ QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
+ QVERIFY(childrenRectArguments.count() == 1);
+ QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
+
+ QCOMPARE(item->hasActiveFocus(), true);
+ QCOMPARE(focusSpy.count(),1);
+ QList<QVariant> focusArguments = focusSpy.first();
+ QVERIFY(focusArguments.count() == 1);
+ QCOMPARE(focusArguments.at(0).toBool(), true);
+
+ QCOMPARE(parentItem->hasActiveFocus(), false);
+ QCOMPARE(parentItem->hasFocus(), false);
+ QCOMPARE(wantsFocusSpy.count(),0);
+
+ item->setX(10.0);
+ QCOMPARE(item->x(), 10.0);
+ QCOMPARE(xSpy.count(), 1);
+
+ item->setY(10.0);
+ QCOMPARE(item->y(), 10.0);
+ QCOMPARE(ySpy.count(), 1);
+
+ delete canvas;
+}
+
+void tst_QQuickItem::childrenRect()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRect.qml")));
+ canvas->setBaseSize(QSize(240,320));
+ canvas->show();
+
+ QQuickItem *o = canvas->rootObject();
+ QQuickItem *item = o->findChild<QQuickItem*>("testItem");
+ QCOMPARE(item->width(), qreal(0));
+ QCOMPARE(item->height(), qreal(0));
+
+ o->setProperty("childCount", 1);
+ QCOMPARE(item->width(), qreal(10));
+ QCOMPARE(item->height(), qreal(20));
+
+ o->setProperty("childCount", 5);
+ QCOMPARE(item->width(), qreal(50));
+ QCOMPARE(item->height(), qreal(100));
+
+ o->setProperty("childCount", 0);
+ QCOMPARE(item->width(), qreal(0));
+ QCOMPARE(item->height(), qreal(0));
+
+ delete o;
+ delete canvas;
+}
+
+// QTBUG-11383
+void tst_QQuickItem::childrenRectBug()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug.qml")));
+ canvas->show();
+
+ QQuickItem *o = canvas->rootObject();
+ QQuickItem *item = o->findChild<QQuickItem*>("theItem");
+ QCOMPARE(item->width(), qreal(200));
+ QCOMPARE(item->height(), qreal(100));
+ QCOMPARE(item->x(), qreal(100));
+
+ delete canvas;
+}
+
+// QTBUG-11465
+void tst_QQuickItem::childrenRectBug2()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug2.qml")));
+ canvas->show();
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(canvas->rootObject());
+ QVERIFY(rect);
+ QQuickItem *item = rect->findChild<QQuickItem*>("theItem");
+ QCOMPARE(item->width(), qreal(100));
+ QCOMPARE(item->height(), qreal(110));
+ QCOMPARE(item->x(), qreal(130));
+
+ QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+ rectPrivate->setState("row");
+ QCOMPARE(item->width(), qreal(210));
+ QCOMPARE(item->height(), qreal(50));
+ QCOMPARE(item->x(), qreal(75));
+
+ delete canvas;
+}
+
+// QTBUG-12722
+void tst_QQuickItem::childrenRectBug3()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("childrenRectBug3.qml")));
+ canvas->show();
+
+ //don't crash on delete
+ delete canvas;
+}
+
+// QTBUG-13893
+void tst_QQuickItem::transformCrash()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("transformCrash.qml")));
+ canvas->show();
+
+ delete canvas;
+}
+
+void tst_QQuickItem::implicitSize()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("implicitsize.qml")));
+ canvas->show();
+
+ QQuickItem *item = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(item);
+ QCOMPARE(item->width(), qreal(80));
+ QCOMPARE(item->height(), qreal(60));
+
+ QCOMPARE(item->implicitWidth(), qreal(200));
+ QCOMPARE(item->implicitHeight(), qreal(100));
+
+ QMetaObject::invokeMethod(item, "resetSize");
+
+ QCOMPARE(item->width(), qreal(200));
+ QCOMPARE(item->height(), qreal(100));
+
+ QMetaObject::invokeMethod(item, "changeImplicit");
+
+ QCOMPARE(item->implicitWidth(), qreal(150));
+ QCOMPARE(item->implicitHeight(), qreal(80));
+ QCOMPARE(item->width(), qreal(150));
+ QCOMPARE(item->height(), qreal(80));
+
+ delete canvas;
+}
+
+void tst_QQuickItem::qtbug_16871()
+{
+ QDeclarativeComponent component(&engine, TESTDATA("qtbug_16871.qml"));
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+ delete o;
+}
+
+QTEST_MAIN(tst_QQuickItem)
+
+#include "tst_qquickitem.moc"
diff --git a/tests/auto/declarative/qquicklistview/data/ComponentView.qml b/tests/auto/qtquick2/qquicklistview/data/ComponentView.qml
index 3e87be8799..3e87be8799 100644
--- a/tests/auto/declarative/qquicklistview/data/ComponentView.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/ComponentView.qml
diff --git a/tests/auto/declarative/qquicklistview/data/asyncloader.qml b/tests/auto/qtquick2/qquicklistview/data/asyncloader.qml
index f038f0960c..f038f0960c 100644
--- a/tests/auto/declarative/qquicklistview/data/asyncloader.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/asyncloader.qml
diff --git a/tests/auto/declarative/qquicklistview/data/attachedSignals.qml b/tests/auto/qtquick2/qquicklistview/data/attachedSignals.qml
index 2c3c0bbada..2c3c0bbada 100644
--- a/tests/auto/declarative/qquicklistview/data/attachedSignals.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/attachedSignals.qml
diff --git a/tests/auto/declarative/qquicklistview/data/creationContext.qml b/tests/auto/qtquick2/qquicklistview/data/creationContext.qml
index 79a682788b..79a682788b 100644
--- a/tests/auto/declarative/qquicklistview/data/creationContext.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/creationContext.qml
diff --git a/tests/auto/declarative/qquicklistview/data/displaylist.qml b/tests/auto/qtquick2/qquicklistview/data/displaylist.qml
index 4e8fd32f6a..4e8fd32f6a 100644
--- a/tests/auto/declarative/qquicklistview/data/displaylist.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/displaylist.qml
diff --git a/tests/auto/declarative/qquicklistview/data/fillModelOnComponentCompleted.qml b/tests/auto/qtquick2/qquicklistview/data/fillModelOnComponentCompleted.qml
index 906e6adb6b..906e6adb6b 100644
--- a/tests/auto/declarative/qquicklistview/data/fillModelOnComponentCompleted.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/fillModelOnComponentCompleted.qml
diff --git a/tests/auto/declarative/qquicklistview/data/footer.qml b/tests/auto/qtquick2/qquicklistview/data/footer.qml
index 2a5619999e..2a5619999e 100644
--- a/tests/auto/declarative/qquicklistview/data/footer.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/footer.qml
diff --git a/tests/auto/declarative/qquicklistview/data/header.qml b/tests/auto/qtquick2/qquicklistview/data/header.qml
index bf70310630..bf70310630 100644
--- a/tests/auto/declarative/qquicklistview/data/header.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/header.qml
diff --git a/tests/auto/declarative/qquicklistview/data/headerfooter.qml b/tests/auto/qtquick2/qquicklistview/data/headerfooter.qml
index 8e8463d645..8e8463d645 100644
--- a/tests/auto/declarative/qquicklistview/data/headerfooter.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/headerfooter.qml
diff --git a/tests/auto/declarative/qquicklistview/data/itemlist.qml b/tests/auto/qtquick2/qquicklistview/data/itemlist.qml
index 5c7ecdd5e8..5c7ecdd5e8 100644
--- a/tests/auto/declarative/qquicklistview/data/itemlist.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/itemlist.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-enforcerange-nohighlight.qml b/tests/auto/qtquick2/qquicklistview/data/listview-enforcerange-nohighlight.qml
index 1db1096499..1db1096499 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-enforcerange-nohighlight.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-enforcerange-nohighlight.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-enforcerange.qml b/tests/auto/qtquick2/qquicklistview/data/listview-enforcerange.qml
index f1bf6c2b57..f1bf6c2b57 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-enforcerange.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-enforcerange.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-initCurrent.qml b/tests/auto/qtquick2/qquicklistview/data/listview-initCurrent.qml
index c4f1860eda..c4f1860eda 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-initCurrent.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-initCurrent.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-noCurrent.qml b/tests/auto/qtquick2/qquicklistview/data/listview-noCurrent.qml
index 079966d8e4..079966d8e4 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-noCurrent.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-noCurrent.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-sections.qml b/tests/auto/qtquick2/qquicklistview/data/listview-sections.qml
index d5b8a4400d..d5b8a4400d 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-sections.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-sections.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listview-sections_delegate.qml b/tests/auto/qtquick2/qquicklistview/data/listview-sections_delegate.qml
index 496d8d7784..496d8d7784 100644
--- a/tests/auto/declarative/qquicklistview/data/listview-sections_delegate.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listview-sections_delegate.qml
diff --git a/tests/auto/declarative/qquicklistview/data/listviewtest.qml b/tests/auto/qtquick2/qquicklistview/data/listviewtest.qml
index 47b341c1fc..47b341c1fc 100644
--- a/tests/auto/declarative/qquicklistview/data/listviewtest.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/listviewtest.qml
diff --git a/tests/auto/declarative/qquicklistview/data/manual-highlight.qml b/tests/auto/qtquick2/qquicklistview/data/manual-highlight.qml
index aac4599f01..aac4599f01 100644
--- a/tests/auto/declarative/qquicklistview/data/manual-highlight.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/manual-highlight.qml
diff --git a/tests/auto/declarative/qquicklistview/data/margins.qml b/tests/auto/qtquick2/qquicklistview/data/margins.qml
index 19bbef500f..19bbef500f 100644
--- a/tests/auto/declarative/qquicklistview/data/margins.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/margins.qml
diff --git a/tests/auto/declarative/qquicklistview/data/propertychangestest.qml b/tests/auto/qtquick2/qquicklistview/data/propertychangestest.qml
index 146f3f13b0..146f3f13b0 100644
--- a/tests/auto/declarative/qquicklistview/data/propertychangestest.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/propertychangestest.qml
diff --git a/tests/auto/declarative/qquicklistview/data/qtbug-21742.qml b/tests/auto/qtquick2/qquicklistview/data/qtbug-21742.qml
index 774f9041fb..774f9041fb 100644
--- a/tests/auto/declarative/qquicklistview/data/qtbug-21742.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/qtbug-21742.qml
diff --git a/tests/auto/declarative/qquicklistview/data/qtbug14821.qml b/tests/auto/qtquick2/qquicklistview/data/qtbug14821.qml
index 0a5e0acbb4..0a5e0acbb4 100644
--- a/tests/auto/declarative/qquicklistview/data/qtbug14821.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/qtbug14821.qml
diff --git a/tests/auto/declarative/qquicklistview/data/qtbug16037.qml b/tests/auto/qtquick2/qquicklistview/data/qtbug16037.qml
index 21faeb3f32..21faeb3f32 100644
--- a/tests/auto/declarative/qquicklistview/data/qtbug16037.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/qtbug16037.qml
diff --git a/tests/auto/declarative/qquicklistview/data/resizeview.qml b/tests/auto/qtquick2/qquicklistview/data/resizeview.qml
index 071cdedf2e..071cdedf2e 100644
--- a/tests/auto/declarative/qquicklistview/data/resizeview.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/resizeview.qml
diff --git a/tests/auto/declarative/qquicklistview/data/rightToLeft.qml b/tests/auto/qtquick2/qquicklistview/data/rightToLeft.qml
index 6d77de26f4..6d77de26f4 100644
--- a/tests/auto/declarative/qquicklistview/data/rightToLeft.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/rightToLeft.qml
diff --git a/tests/auto/declarative/qquicklistview/data/sizelessthan1.qml b/tests/auto/qtquick2/qquicklistview/data/sizelessthan1.qml
index aa9dc20ae9..aa9dc20ae9 100644
--- a/tests/auto/declarative/qquicklistview/data/sizelessthan1.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/sizelessthan1.qml
diff --git a/tests/auto/declarative/qquicklistview/data/snapToItem.qml b/tests/auto/qtquick2/qquicklistview/data/snapToItem.qml
index 6f201072f0..6f201072f0 100644
--- a/tests/auto/declarative/qquicklistview/data/snapToItem.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/snapToItem.qml
diff --git a/tests/auto/declarative/qquicklistview/data/strictlyenforcerange.qml b/tests/auto/qtquick2/qquicklistview/data/strictlyenforcerange.qml
index 7960ac4abb..7960ac4abb 100644
--- a/tests/auto/declarative/qquicklistview/data/strictlyenforcerange.qml
+++ b/tests/auto/qtquick2/qquicklistview/data/strictlyenforcerange.qml
diff --git a/tests/auto/declarative/qquicklistview/incrementalmodel.cpp b/tests/auto/qtquick2/qquicklistview/incrementalmodel.cpp
index 53d30915f5..53d30915f5 100644
--- a/tests/auto/declarative/qquicklistview/incrementalmodel.cpp
+++ b/tests/auto/qtquick2/qquicklistview/incrementalmodel.cpp
diff --git a/tests/auto/declarative/qquicklistview/incrementalmodel.h b/tests/auto/qtquick2/qquicklistview/incrementalmodel.h
index a6cddb6b07..a6cddb6b07 100644
--- a/tests/auto/declarative/qquicklistview/incrementalmodel.h
+++ b/tests/auto/qtquick2/qquicklistview/incrementalmodel.h
diff --git a/tests/auto/qtquick2/qquicklistview/qquicklistview.pro b/tests/auto/qtquick2/qquicklistview/qquicklistview.pro
new file mode 100644
index 0000000000..be88679c62
--- /dev/null
+++ b/tests/auto/qtquick2/qquicklistview/qquicklistview.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquicklistview
+macx:CONFIG -= app_bundle
+
+HEADERS += incrementalmodel.h
+SOURCES += tst_qquicklistview.cpp incrementalmodel.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private widgets widgets-private v8-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp
new file mode 100644
index 0000000000..780033bbeb
--- /dev/null
+++ b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp
@@ -0,0 +1,4379 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtWidgets/QStringListModel>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickvisualitemmodel_p.h>
+#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
+#include <QtDeclarative/private/qlistmodelinterface_p.h>
+#include <QtQuick/private/qdeclarativechangeset_p.h>
+#include "../../shared/util.h"
+#include "incrementalmodel.h"
+#include <math.h>
+
+Q_DECLARE_METATYPE(Qt::LayoutDirection)
+Q_DECLARE_METATYPE(QQuickListView::Orientation)
+
+class tst_QQuickListView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickListView();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ // Test both QListModelInterface and QAbstractItemModel model types
+ void qListModelInterface_items();
+ void qAbstractItemModel_items();
+
+ void qListModelInterface_changed();
+ void qAbstractItemModel_changed();
+
+ void qListModelInterface_inserted();
+ void qListModelInterface_inserted_more();
+ void qListModelInterface_inserted_more_data();
+ void qAbstractItemModel_inserted();
+ void qAbstractItemModel_inserted_more();
+ void qAbstractItemModel_inserted_more_data();
+
+ void qListModelInterface_removed();
+ void qAbstractItemModel_removed();
+
+ void qListModelInterface_moved();
+ void qListModelInterface_moved_data();
+ void qAbstractItemModel_moved();
+ void qAbstractItemModel_moved_data();
+
+ void multipleChanges();
+ void multipleChanges_data();
+
+ void qListModelInterface_clear();
+ void qAbstractItemModel_clear();
+
+ void insertBeforeVisible();
+ void insertBeforeVisible_data();
+ void swapWithFirstItem();
+ void itemList();
+ void currentIndex_delayedItemCreation();
+ void currentIndex_delayedItemCreation_data();
+ void currentIndex();
+ void noCurrentIndex();
+ void enforceRange();
+ void enforceRange_withoutHighlight();
+ void spacing();
+ void sections();
+ void sectionsPositioning();
+ void sectionsDelegate();
+ void cacheBuffer();
+ void positionViewAtIndex();
+ void resetModel();
+ void propertyChanges();
+ void componentChanges();
+ void modelChanges();
+ void manualHighlight();
+ void header();
+ void header_data();
+ void header_delayItemCreation();
+ void footer();
+ void footer_data();
+ void headerFooter();
+ void resizeView();
+ void resizeViewAndRepaint();
+ void sizeLessThan1();
+ void QTBUG_14821();
+ void resizeDelegate();
+ void resizeFirstDelegate();
+ void QTBUG_16037();
+ void indexAt();
+ void incrementalModel();
+ void onAdd();
+ void onAdd_data();
+ void onRemove();
+ void onRemove_data();
+ void rightToLeft();
+ void test_mirroring();
+ void margins();
+ void creationContext();
+ void snapToItem_data();
+ void snapToItem();
+
+ void QTBUG_9791();
+ void QTBUG_11105();
+ void QTBUG_21742();
+
+ void asynchronous();
+
+private:
+ template <class T> void items();
+ template <class T> void changed();
+ template <class T> void inserted();
+ template <class T> void inserted_more();
+ template <class T> void removed(bool animated);
+ template <class T> void moved();
+ template <class T> void clear();
+ QQuickView *createView();
+ void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
+ QQuickItem *findVisibleChild(QQuickItem *parent, const QString &objectName);
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &id, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QQuickItem *parent, const QString &objectName);
+ void dumpTree(QQuickItem *parent, int depth = 0);
+
+ void inserted_more_data();
+ void moved_data();
+};
+
+void tst_QQuickListView::initTestCase()
+{
+}
+
+void tst_QQuickListView::cleanupTestCase()
+{
+
+}
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError NOTIFY changedError)
+ Q_PROPERTY(bool animate READ animate NOTIFY changedAnim)
+ Q_PROPERTY(bool invalidHighlight READ invalidHighlight NOTIFY changedHl)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
+
+public:
+ TestObject(QObject *parent = 0)
+ : QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
+ , mCacheBuffer(0) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; emit changedError(); }
+
+ bool animate() const { return mAnimate; }
+ void setAnimate(bool anim) { mAnimate = anim; emit changedAnim(); }
+
+ bool invalidHighlight() const { return mInvalidHighlight; }
+ void setInvalidHighlight(bool invalid) { mInvalidHighlight = invalid; emit changedHl(); }
+
+ int cacheBuffer() const { return mCacheBuffer; }
+ void setCacheBuffer(int buffer) { mCacheBuffer = buffer; emit changedCacheBuffer(); }
+
+signals:
+ void changedError();
+ void changedAnim();
+ void changedHl();
+ void changedCacheBuffer();
+
+public:
+ bool mError;
+ bool mAnimate;
+ bool mInvalidHighlight;
+ int mCacheBuffer;
+};
+
+template<typename T>
+void tst_qquicklistview_move(int from, int to, int n, T *items)
+{
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+ if (n == 1) {
+ items->move(from, to);
+ } else {
+ T replaced;
+ int i=0;
+ typename T::ConstIterator it=items->begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=items->begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ typename T::ConstIterator f=replaced.begin();
+ typename T::Iterator t=items->begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+}
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch (role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QVariant data(int index, int role) const
+ {
+ if (role==0)
+ return list.at(index).first;
+ if (role==1)
+ return list.at(index).second;
+ return QVariant();
+ }
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch (role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit itemsInserted(index, items.count());
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void removeItems(int index, int count) {
+ int c = count;
+ while (c--)
+ list.removeAt(index);
+ emit itemsRemoved(index, count);
+ }
+
+ void moveItem(int from, int to) {
+ list.move(from, to);
+ emit itemsMoved(from, to, 1);
+ }
+
+ void moveItems(int from, int to, int count) {
+ tst_qquicklistview_move(from, to, count, &list);
+ emit itemsMoved(from, to, count);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+ void clear() {
+ int count = list.count();
+ list.clear();
+ emit itemsRemoved(0, count);
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+class TestModel2 : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void addItems(const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
+ for (int i=0; i<items.count(); i++)
+ list.append(QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), index, index+items.count()-1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void removeItems(int index, int count) {
+ emit beginRemoveRows(QModelIndex(), index, index+count-1);
+ while (count--)
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void moveItems(int from, int to, int count) {
+ emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
+ tst_qquicklistview_move(from, to, count, &list);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+ void clear() {
+ int count = list.count();
+ emit beginRemoveRows(QModelIndex(), 0, count-1);
+ list.clear();
+ emit endRemoveRows();
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QQuickListView::tst_QQuickListView()
+{
+}
+
+template <class T>
+void tst_QQuickListView::items()
+{
+ QQuickView *canvas = createView();
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QTRY_VERIFY(testObject->error() == false);
+
+ QTRY_VERIFY(listview->highlightItem() != 0);
+ QTRY_COMPARE(listview->count(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ // current item should be first item
+ QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
+
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ // switch to other delegate
+ testObject->setAnimate(true);
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(listview->currentItem());
+
+ // set invalid highlight
+ testObject->setInvalidHighlight(true);
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(listview->currentItem());
+ QTRY_VERIFY(listview->highlightItem() == 0);
+
+ // back to normal highlight
+ testObject->setInvalidHighlight(false);
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(listview->currentItem());
+ QTRY_VERIFY(listview->highlightItem() != 0);
+
+ // set an empty model and confirm that items are destroyed
+ T model2;
+ ctxt->setContextProperty("testModel", &model2);
+
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ QTRY_VERIFY(itemCount == 0);
+
+ QTRY_COMPARE(listview->highlightResizeSpeed(), 1000.0);
+ QTRY_COMPARE(listview->highlightMoveSpeed(), 1000.0);
+
+ delete canvas;
+ delete testObject;
+}
+
+
+template <class T>
+void tst_QQuickListView::changed()
+{
+ QQuickView *canvas = createView();
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickFlickable *listview = findItem<QQuickFlickable>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+ delete canvas;
+ delete testObject;
+}
+
+template <class T>
+void tst_QQuickListView::inserted()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_COMPARE(item->y(), i*20.0);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
+
+ name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ QTRY_COMPARE(listview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_COMPARE(item->y(), i*20.0);
+ }
+
+ for (int i = model.count(); i < 30; ++i)
+ model.insertItem(i, "Hello", QString::number(i));
+
+ listview->setContentY(80);
+
+ // Insert item outside visible area
+ model.insertItem(1, "Hello", "1324");
+
+ QTRY_VERIFY(listview->contentY() == 80);
+
+ // Confirm items positioned correctly
+ for (int i = 5; i < 5+15; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.0 - 20.0);
+ }
+
+// QTRY_COMPARE(listview->contentItemHeight(), model.count() * 20.0);
+
+ // QTBUG-19675
+ model.clear();
+ model.insertItem(0, "Hello", "1234");
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->y(), 0.);
+ QVERIFY(listview->contentY() == 0);
+
+ delete canvas;
+ delete testObject;
+}
+
+template <class T>
+void tst_QQuickListView::inserted_more()
+{
+ QFETCH(qreal, contentY);
+ QFETCH(int, insertIndex);
+ QFETCH(int, insertCount);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ listview->setContentY(contentY);
+
+ QList<QPair<QString, QString> > newData;
+ for (int i=0; i<insertCount; i++)
+ newData << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.insertItems(insertIndex, newData);
+ QTRY_COMPARE(listview->property("count").toInt(), model.count());
+
+ // check visibleItems.first() is in correct position
+ QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item0);
+ QCOMPARE(item0->y(), itemsOffsetAfterMove);
+
+ QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
+ int firstVisibleIndex = -1;
+ for (int i=0; i<items.count(); i++) {
+ if (items[i]->y() >= contentY) {
+ QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
+ firstVisibleIndex = e.evaluate().toInt();
+ break;
+ }
+ }
+ QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::inserted_more_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<int>("insertCount");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ QTest::newRow("add 1, before visible items")
+ << 80.0 // show 4-19
+ << 3 << 1
+ << -20.0; // insert above first visible i.e. 0 is at -20, first visible should not move
+
+ QTest::newRow("add multiple, before visible")
+ << 80.0 // show 4-19
+ << 3 << 3
+ << -20.0 * 3; // again first visible should not move
+
+ QTest::newRow("add 1, at start of visible, content at start")
+ << 0.0
+ << 0 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, start of visible, content at start")
+ << 0.0
+ << 0 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, at start of visible, content not at start")
+ << 80.0 // show 4-19
+ << 4 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, at start of visible, content not at start")
+ << 80.0 // show 4-19
+ << 4 << 3
+ << 0.0;
+
+
+ QTest::newRow("add 1, at end of visible, content at start")
+ << 0.0
+ << 15 << 1
+ << 0.0;
+
+ QTest::newRow("add 1, at end of visible, content at start")
+ << 0.0
+ << 15 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, at end of visible, content not at start")
+ << 80.0 // show 4-19
+ << 19 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, at end of visible, content not at start")
+ << 80.0 // show 4-19
+ << 19 << 3
+ << 0.0;
+
+
+ QTest::newRow("add 1, after visible, content at start")
+ << 0.0
+ << 16 << 1
+ << 0.0;
+
+ QTest::newRow("add 1, after visible, content at start")
+ << 0.0
+ << 16 << 3
+ << 0.0;
+
+ QTest::newRow("add 1, after visible, content not at start")
+ << 80.0 // show 4-19
+ << 20 << 1
+ << 0.0;
+
+ QTest::newRow("add multiple, after visible, content not at start")
+ << 80.0 // show 4-19
+ << 20 << 3
+ << 0.0;
+}
+
+void tst_QQuickListView::insertBeforeVisible()
+{
+ QFETCH(int, insertIndex);
+ QFETCH(int, insertCount);
+ QFETCH(int, cacheBuffer);
+
+ QQuickText *name;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ listview->setCacheBuffer(cacheBuffer);
+
+ // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
+ int firstVisibleIndex = 20; // move to an index where the top item is not visible
+ listview->setContentY(firstVisibleIndex * 20.0);
+ listview->setCurrentIndex(firstVisibleIndex);
+ qApp->processEvents();
+ QTRY_COMPARE(listview->currentIndex(), firstVisibleIndex);
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
+ QVERIFY(item);
+ QCOMPARE(item->y(), listview->contentY());
+
+ QList<QPair<QString, QString> > newData;
+ for (int i=0; i<insertCount; i++)
+ newData << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.insertItems(insertIndex, newData);
+ QTRY_COMPARE(listview->property("count").toInt(), model.count());
+
+ // now, moving to the top of the view should position the inserted items correctly
+ int itemsOffsetAfterMove = -(insertCount * 20);
+ listview->setCurrentIndex(0);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QTRY_COMPARE(listview->contentY(), 0.0 + itemsOffsetAfterMove);
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::insertBeforeVisible_data()
+{
+ QTest::addColumn<int>("insertIndex");
+ QTest::addColumn<int>("insertCount");
+ QTest::addColumn<int>("cacheBuffer");
+
+ QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
+ QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
+ QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
+
+ QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
+ QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
+ QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
+
+ QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 3 << 0;
+ QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 3 << 100;
+ QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 3 << 500;
+
+ QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 3 << 0;
+ QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 3 << 100;
+ QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 3 << 500;
+}
+
+template <class T>
+void tst_QQuickListView::removed(bool /* animated */)
+{
+ QQuickView *canvas = createView();
+
+ T model;
+ for (int i = 0; i < 50; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.removeItem(1);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(1));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*20);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0); // post: top item starts at 20
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(),i*20.0 + 20.0);
+ }
+
+ // Remove items not visible
+ model.removeItem(18);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(),i*20.0+20.0);
+ }
+
+ // Remove items before visible
+ listview->setContentY(80);
+ listview->setCurrentIndex(10);
+
+ model.removeItem(1); // post: top item will be at 40
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ // Confirm items positioned correctly
+ for (int i = 2; i < 18; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(),40+i*20.0);
+ }
+
+ // Remove current index
+ QTRY_VERIFY(listview->currentIndex() == 9);
+ QQuickItem *oldCurrent = listview->currentItem();
+ model.removeItem(9);
+
+ QTRY_COMPARE(listview->currentIndex(), 9);
+ QTRY_VERIFY(listview->currentItem() != oldCurrent);
+
+ listview->setContentY(40); // That's the top now
+ // let transitions settle.
+ QTest::qWait(300);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(),40+i*20.0);
+ }
+
+ // remove current item beyond visible items.
+ listview->setCurrentIndex(20);
+ listview->setContentY(40);
+ model.removeItem(20);
+
+ QTRY_COMPARE(listview->currentIndex(), 20);
+ QTRY_VERIFY(listview->currentItem() != 0);
+
+ // remove item before current, but visible
+ listview->setCurrentIndex(8);
+ oldCurrent = listview->currentItem();
+ model.removeItem(6);
+
+ QTRY_COMPARE(listview->currentIndex(), 7);
+ QTRY_VERIFY(listview->currentItem() == oldCurrent);
+
+ listview->setContentY(80);
+ QTest::qWait(300);
+
+ // remove all visible items
+ model.removeItems(1, 18);
+ QTRY_COMPARE(listview->count() , model.count());
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i+1);
+ if (!item) qWarning() << "Item" << i+1 << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(),80+i*20.0);
+ }
+
+ model.removeItems(1, 17);
+ QTRY_COMPARE(listview->count() , model.count());
+
+ model.removeItems(2, 1);
+ QTRY_COMPARE(listview->count() , model.count());
+
+ model.addItem("New", "1");
+ QTRY_COMPARE(listview->count() , model.count());
+
+ QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", model.count()-1));
+ QCOMPARE(name->text(), QString("New"));
+
+ // Add some more items so that we don't run out
+ model.clear();
+ for (int i = 0; i < 50; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ // QTBUG-QTBUG-20575
+ listview->setCurrentIndex(0);
+ listview->setContentY(30);
+ model.removeItem(0);
+ QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", 0));
+
+ // QTBUG-19198 move to end and remove all visible items one at a time.
+ listview->positionViewAtEnd();
+ for (int i = 0; i < 18; ++i)
+ model.removeItems(model.count() - 1, 1);
+ QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() > 16);
+
+ delete canvas;
+ delete testObject;
+}
+
+template <class T>
+void tst_QQuickListView::clear()
+{
+ QQuickView *canvas = createView();
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ model.clear();
+
+ QTRY_VERIFY(listview->count() == 0);
+ QTRY_VERIFY(listview->currentItem() == 0);
+ QTRY_VERIFY(listview->contentY() == 0);
+ QVERIFY(listview->currentIndex() == -1);
+
+ // confirm sanity when adding an item to cleared list
+ model.addItem("New", "1");
+ QTRY_VERIFY(listview->count() == 1);
+ QVERIFY(listview->currentItem() != 0);
+ QVERIFY(listview->currentIndex() == 0);
+
+ delete canvas;
+ delete testObject;
+}
+
+template <class T>
+void tst_QQuickListView::moved()
+{
+ QFETCH(qreal, contentY);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, count);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickItem *currentItem = listview->currentItem();
+ QTRY_VERIFY(currentItem != 0);
+
+ listview->setContentY(contentY);
+ model.moveItems(from, to, count);
+
+ // wait for items to move
+ QTest::qWait(100);
+
+ QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
+ int firstVisibleIndex = -1;
+ for (int i=0; i<items.count(); i++) {
+ if (items[i]->y() >= contentY) {
+ QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
+ firstVisibleIndex = e.evaluate().toInt();
+ break;
+ }
+ }
+ QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+
+ // Confirm items positioned correctly and indexes correct
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ if (i >= firstVisibleIndex + 16) // index has moved out of view
+ continue;
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+
+ // current index should have been updated
+ if (item == currentItem)
+ QTRY_COMPARE(listview->currentIndex(), i);
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::moved_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ // model starts with 30 items, each 20px high, in area 320px high
+ // 16 items should be visible at a time
+ // itemsOffsetAfterMove should be > 0 whenever items above the visible pos have moved
+
+ QTest::newRow("move 1 forwards, within visible items")
+ << 0.0
+ << 1 << 4 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible")
+ << 80.0 // show 4-19
+ << 1 << 18 << 1
+ << 20.0; // removed 1 item above the first visible, so item 0 should drop down by 1 to minimize movement
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
+ << 80.0 // show 4-19
+ << 0 << 4 << 1
+ << 20.0; // first item has moved to below item4, everything drops down by size of 1 item
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 16 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 16 << 1
+ << 0.0;
+
+
+ QTest::newRow("move 1 backwards, within visible items")
+ << 0.0
+ << 4 << 1 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, within visible items (to first index)")
+ << 0.0
+ << 4 << 0 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible")
+ << 0.0
+ << 20 << 4 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 29 << 15 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible")
+ << 80.0 // show 4-19
+ << 16 << 1 << 1
+ << -20.0; // to minimize movement, item 0 moves to -20, and other items do not move
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
+ << 80.0 // show 4-19
+ << 16 << 0 << 1
+ << -20.0; // to minimize movement, item 16 (now at 0) moves to -20, and other items do not move
+
+
+ QTest::newRow("move multiple forwards, within visible items")
+ << 0.0
+ << 0 << 5 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple forwards, before visible items")
+ << 140.0 // show 7-22
+ << 4 << 5 << 3 // 4,5,6 move to below 7
+ << 20.0 * 3; // 4,5,6 moved down
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible")
+ << 80.0 // show 4-19
+ << 1 << 5 << 3
+ << 20.0 * 3; // moving 3 from above the content y should adjust y positions accordingly
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
+ << 80.0 // show 4-19
+ << 0 << 5 << 3
+ << 20.0 * 3; // moving 3 from above the content y should adjust y positions accordingly
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 16 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 16 << 3
+ << 0.0;
+
+
+ QTest::newRow("move multiple backwards, within visible items")
+ << 0.0
+ << 4 << 1 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, within visible items (move first item)")
+ << 0.0
+ << 10 << 0 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible")
+ << 0.0
+ << 20 << 4 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 27 << 10 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible")
+ << 80.0 // show 4-19
+ << 16 << 1 << 3
+ << -20.0 * 3; // to minimize movement, 0 moves by -60, and other items do not move
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
+ << 80.0 // show 4-19
+ << 16 << 0 << 3
+ << -20.0 * 3; // to minimize movement, 16,17,18 move to above item 0, and other items do not move
+}
+
+
+struct ListChange {
+ enum { Inserted, Removed, Moved, SetCurrent } type;
+ int index;
+ int count;
+ int to; // Move
+
+ static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
+ static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
+ static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
+ static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
+};
+Q_DECLARE_METATYPE(QList<ListChange>)
+
+void tst_QQuickListView::multipleChanges()
+{
+ QFETCH(int, startCount);
+ QFETCH(QList<ListChange>, changes);
+ QFETCH(int, newCount);
+ QFETCH(int, newCurrentIndex);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < startCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ for (int i=0; i<changes.count(); i++) {
+ switch (changes[i].type) {
+ case ListChange::Inserted:
+ {
+ QList<QPair<QString, QString> > items;
+ for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
+ items << qMakePair(QString("new item " + j), QString::number(j));
+ model.insertItems(changes[i].index, items);
+ break;
+ }
+ case ListChange::Removed:
+ model.removeItems(changes[i].index, changes[i].count);
+ break;
+ case ListChange::Moved:
+ model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ break;
+ case ListChange::SetCurrent:
+ listview->setCurrentIndex(changes[i].index);
+ break;
+ }
+ }
+
+ QTRY_COMPARE(listview->count(), newCount);
+ QCOMPARE(listview->count(), model.count());
+ QTRY_COMPARE(listview->currentIndex(), newCurrentIndex);
+
+ QQuickText *name;
+ QQuickText *number;
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i=0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ name = findItem<QQuickText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QQuickText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickListView::multipleChanges_data()
+{
+ QTest::addColumn<int>("startCount");
+ QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<int>("newCount");
+ QTest::addColumn<int>("newCurrentIndex");
+
+ QList<ListChange> changes;
+
+ for (int i=1; i<30; i++)
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
+
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all") << 30 << changes << 0 << -1;
+
+ changes.clear();
+ changes << ListChange::setCurrent(29);
+ for (int i=29; i>0; i--)
+ changes << ListChange::remove(i);
+ QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
+
+ QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
+ << ListChange::remove(0, 1)
+ << ListChange::insert(0, 1)
+ ) << 10 << 1;
+
+ QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(2, 1)
+ << ListChange::insert(2, 1)
+ ) << 10 << 3;
+
+ QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1, 3)
+ << ListChange::insert(2, 2)
+ ) << 9 << 1;
+
+ QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(1, 3)
+ << ListChange::move(1, 5, 1)
+ ) << 7 << 5;
+
+ QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::remove(4, 3)
+ << ListChange::move(4, 1, 1)
+ ) << 7 << 1;
+
+
+ QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ ) << 12 << 10;
+
+ QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ << ListChange::setCurrent(3)
+ << ListChange::insert(3, 2)
+ ) << 14 << 5;
+
+ QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 30)
+ << ListChange::remove(0, 30)
+ ) << 0 << -1;
+
+ QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
+ << ListChange::insert(1)
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1)
+ ) << 30 << 1;
+
+ QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 10)
+ << ListChange::remove(5, 10)
+ ) << 10 << 5;
+
+ QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 10, 3)
+ ) << 13 << 0;
+
+ QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 8, 5)
+ ) << 13 << 11;
+
+ QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(9)
+ << ListChange::insert(10, 3)
+ << ListChange::move(8, 0, 5)
+ ) << 13 << 1;
+
+
+ QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(1, 2, 2)
+ << ListChange::move(2, 1, 2)
+ ) << 10 << 1;
+
+ QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::move(1, 2, 3)
+ << ListChange::move(3, 0, 5)
+ ) << 10 << 0;
+
+ QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::remove(0)
+ ) << 9 << 0;
+
+ QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::insert(0)
+ ) << 11 << 1;
+
+ QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(5, 1, 3)
+ << ListChange::remove(1, 3)
+ ) << 7 << 1;
+
+ QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 1, 3)
+ << ListChange::insert(1, 5)
+ ) << 15 << 6;
+
+ QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(3)
+ << ListChange::move(0, 1, 2)
+ << ListChange::insert(3, 5)
+ ) << 15 << 8;
+
+
+ QTest::newRow("clear current") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 5)
+ << ListChange::setCurrent(-1)
+ << ListChange::remove(0, 5)
+ << ListChange::insert(0, 5)
+ ) << 5 << -1;
+}
+
+void tst_QQuickListView::swapWithFirstItem()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ // ensure content position is stable
+ listview->setContentY(0);
+ model.moveItem(1, 0);
+ QTRY_VERIFY(listview->contentY() == 0);
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickListView::enforceRange()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-enforcerange.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
+ QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
+ QTRY_COMPARE(listview->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // view should be positioned at the top of the range.
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(listview->contentY(), -100.0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
+ QTRY_VERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(0));
+ QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
+ QTRY_VERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(0));
+
+ // Check currentIndex is updated when contentItem moves
+ listview->setContentY(20);
+
+ QTRY_COMPARE(listview->currentIndex(), 6);
+
+ // change model
+ TestModel model2;
+ for (int i = 0; i < 5; i++)
+ model2.addItem("Item" + QString::number(i), "");
+
+ ctxt->setContextProperty("testModel", &model2);
+ QCOMPARE(listview->count(), 5);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::enforceRange_withoutHighlight()
+{
+ // QTBUG-20287
+ // If no highlight is set but StrictlyEnforceRange is used, the content should still move
+ // to the correct position (i.e. to the next/previous item, not next/previous section)
+ // when moving up/down via incrementCurrentIndex() and decrementCurrentIndex()
+
+ QQuickView *canvas = createView();
+ canvas->show();
+ QTest::qWait(200);
+
+ TestModel model;
+ model.addItem("Item 0", "a");
+ model.addItem("Item 1", "b");
+ model.addItem("Item 2", "b");
+ model.addItem("Item 3", "c");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-enforcerange-nohighlight.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ qreal expectedPos = -100.0;
+
+ expectedPos += 10.0; // scroll past 1st section's delegate (10px height)
+ QTRY_COMPARE(listview->contentY(), expectedPos);
+
+ expectedPos += 20 + 10; // scroll past 1st section and section delegate of 2nd section
+ QTest::keyClick(canvas, Qt::Key_Down);
+
+ QTRY_COMPARE(listview->contentY(), expectedPos);
+
+ expectedPos += 20; // scroll past 1st item of 2nd section
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QTRY_COMPARE(listview->contentY(), expectedPos);
+
+ expectedPos += 20 + 10; // scroll past 2nd item of 2nd section and section delegate of 3rd section
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QTRY_COMPARE(listview->contentY(), expectedPos);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::spacing()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*20);
+ }
+
+ listview->setSpacing(10);
+ QTRY_VERIFY(listview->spacing() == 10);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*30);
+ }
+
+ listview->setSpacing(0);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.0);
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::sections()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i/5));
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
+ QQuickText *next = findItem<QQuickText>(item, "nextSection");
+ QCOMPARE(next->text().toInt(), (i+1)/5);
+ }
+
+ QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged()));
+
+ // Remove section boundary
+ model.removeItem(5);
+ QTRY_COMPARE(listview->count(), model.count());
+
+ // New section header created
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 5);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 40.0);
+
+ model.insertItem(3, "New Item", "0");
+ QTRY_COMPARE(listview->count(), model.count());
+
+ // Section header moved
+ item = findItem<QQuickItem>(contentItem, "wrapper", 5);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 20.0);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 6);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 40.0);
+
+ // insert item which will become a section header
+ model.insertItem(6, "Replace header", "1");
+ QTRY_COMPARE(listview->count(), model.count());
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 6);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 40.0);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 7);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 20.0);
+
+ QTRY_COMPARE(listview->currentSection(), QString("0"));
+
+ listview->setContentY(140);
+ QTRY_COMPARE(listview->currentSection(), QString("1"));
+
+ QTRY_COMPARE(currentSectionChangedSpy.count(), 1);
+
+ listview->setContentY(20);
+ QTRY_COMPARE(listview->currentSection(), QString("0"));
+
+ QTRY_COMPARE(currentSectionChangedSpy.count(), 2);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 1);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 20.0);
+
+ // check that headers change when item changes
+ listview->setContentY(0);
+ model.modifyItem(0, "changed", "2");
+ QTest::qWait(300);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 1);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->height(), 40.0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::sectionsDelegate()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i/5));
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections_delegate.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20));
+ QQuickText *next = findItem<QQuickText>(item, "nextSection");
+ QCOMPARE(next->text().toInt(), (i+1)/5);
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*6));
+ }
+
+ model.modifyItem(0, "One", "aaa");
+ model.modifyItem(1, "Two", "aaa");
+ model.modifyItem(2, "Three", "aaa");
+ model.modifyItem(3, "Four", "aaa");
+ model.modifyItem(4, "Five", "aaa");
+ QTest::qWait(300);
+
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem,
+ "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*6));
+ }
+
+ // remove section boundary
+ model.removeItem(5);
+ QTRY_COMPARE(listview->count(), model.count());
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem,
+ "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
+ QVERIFY(item);
+ }
+
+ // QTBUG-17606
+ QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "sect_1");
+ QCOMPARE(items.count(), 1);
+
+ // QTBUG-17759
+ model.modifyItem(0, "One", "aaa");
+ model.modifyItem(1, "One", "aaa");
+ model.modifyItem(2, "One", "aaa");
+ model.modifyItem(3, "Four", "aaa");
+ model.modifyItem(4, "Four", "aaa");
+ model.modifyItem(5, "Four", "aaa");
+ model.modifyItem(6, "Five", "aaa");
+ model.modifyItem(7, "Five", "aaa");
+ model.modifyItem(8, "Five", "aaa");
+ model.modifyItem(9, "Two", "aaa");
+ model.modifyItem(10, "Two", "aaa");
+ model.modifyItem(11, "Two", "aaa");
+ QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_aaa").count(), 1);
+ canvas->rootObject()->setProperty("sectionProperty", "name");
+ // ensure view has settled.
+ QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_Four").count(), 1);
+ for (int i = 0; i < 4; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem,
+ "sect_" + model.name(i*3));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*4));
+ }
+
+ // QTBUG-17769
+ model.removeItems(10, 20);
+ // ensure view has settled.
+ QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 10);
+ // Drag view up beyond bounds
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,20));
+ {
+ QMouseEvent mv(QEvent::MouseMove, QPoint(20,0), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ }
+ {
+ QMouseEvent mv(QEvent::MouseMove, QPoint(20,-50), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ }
+ {
+ QMouseEvent mv(QEvent::MouseMove, QPoint(20,-200), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ }
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-200));
+ // view should settle back at 0
+ QTRY_COMPARE(listview->contentY(), 0.0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::sectionsPositioning()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i/5));
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listview-sections_delegate.qml")));
+ qApp->processEvents();
+ canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart | QQuickViewSection::NextLabelAtEnd)));
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*6));
+ }
+
+ QQuickItem *topItem = findVisibleChild(contentItem, "sect_0"); // section header
+ QVERIFY(topItem);
+ QCOMPARE(topItem->y(), 0.);
+
+ QQuickItem *bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
+ QVERIFY(bottomItem);
+ QCOMPARE(bottomItem->y(), 300.);
+
+ // move down a little and check that section header is at top
+ listview->setContentY(10);
+ QCOMPARE(topItem->y(), 0.);
+
+ // push the top header up
+ listview->setContentY(110);
+ topItem = findVisibleChild(contentItem, "sect_0"); // section header
+ QVERIFY(topItem);
+ QCOMPARE(topItem->y(), 100.);
+
+ QQuickItem *item = findVisibleChild(contentItem, "sect_1");
+ QVERIFY(item);
+ QCOMPARE(item->y(), 120.);
+
+ bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
+ QVERIFY(bottomItem);
+ QCOMPARE(bottomItem->y(), 410.);
+
+ // Move past section 0
+ listview->setContentY(120);
+ topItem = findVisibleChild(contentItem, "sect_0"); // section header
+ QVERIFY(!topItem);
+
+ // Push section footer down
+ listview->setContentY(70);
+ bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
+ QVERIFY(bottomItem);
+ QCOMPARE(bottomItem->y(), 380.);
+
+ // Change current section
+ listview->setContentY(10);
+ model.modifyItem(0, "One", "aaa");
+ model.modifyItem(1, "Two", "aaa");
+ model.modifyItem(2, "Three", "aaa");
+ model.modifyItem(3, "Four", "aaa");
+ model.modifyItem(4, "Five", "aaa");
+ QTest::qWait(300);
+
+ QTRY_COMPARE(listview->currentSection(), QString("aaa"));
+
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem,
+ "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*6));
+ }
+
+ topItem = findVisibleChild(contentItem, "sect_aaa"); // section header
+ QVERIFY(topItem);
+ QCOMPARE(topItem->y(), 10.);
+
+ // remove section boundary
+ listview->setContentY(120);
+ model.removeItem(5);
+ QTRY_COMPARE(listview->count(), model.count());
+ for (int i = 0; i < 3; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem,
+ "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
+ QVERIFY(item);
+ QTRY_COMPARE(item->y(), qreal(i*20*6));
+ }
+
+ QVERIFY(topItem = findVisibleChild(contentItem, "sect_1"));
+ QTRY_COMPARE(topItem->y(), 120.);
+
+ // Change the next section
+ listview->setContentY(0);
+ bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
+ QVERIFY(bottomItem);
+ QTRY_COMPARE(bottomItem->y(), 300.);
+
+ model.modifyItem(14, "New", "new");
+
+ QTRY_VERIFY(bottomItem = findVisibleChild(contentItem, "sect_new")); // section footer
+ QTRY_COMPARE(bottomItem->y(), 300.);
+
+ // Turn sticky footer off
+ listview->setContentY(40);
+ canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart)));
+ item = findVisibleChild(contentItem, "sect_new"); // inline label restored
+ QVERIFY(item);
+ QCOMPARE(item->y(), 360.);
+
+ // Turn sticky header off
+ listview->setContentY(30);
+ canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels)));
+ item = findVisibleChild(contentItem, "sect_aaa"); // inline label restored
+ QVERIFY(item);
+ QCOMPARE(item->y(), 0.);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::currentIndex_delayedItemCreation()
+{
+ QFETCH(bool, setCurrentToZero);
+
+ QQuickView *canvas = createView();
+
+ TestModel model;
+
+ // test currentIndexChanged() is emitted even if currentIndex = 0 on start up
+ // (since the currentItem will have changed and that shares the same index)
+ canvas->rootContext()->setContextProperty("setCurrentToZero", setCurrentToZero);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("fillModelOnComponentCompleted.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QSignalSpy spy(listview, SIGNAL(currentItemChanged()));
+ QCOMPARE(listview->currentIndex(), 0);
+ QTRY_COMPARE(spy.count(), 1);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::currentIndex_delayedItemCreation_data()
+{
+ QTest::addColumn<bool>("setCurrentToZero");
+
+ QTest::newRow("set to 0") << true;
+ QTest::newRow("don't set to 0") << false;
+}
+
+void tst_QQuickListView::currentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testWrap", QVariant(false));
+
+ QString filename(TESTDATA("listview-initCurrent.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // current item should be 20th item at startup
+ // and current item should be in view
+ QCOMPARE(listview->currentIndex(), 20);
+ QCOMPARE(listview->contentY(), 100.0);
+ QCOMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 20));
+ QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
+
+ // no wrap
+ listview->setCurrentIndex(0);
+ QCOMPARE(listview->currentIndex(), 0);
+ // confirm that the velocity is updated
+ QTRY_VERIFY(listview->verticalVelocity() != 0.0);
+
+ listview->incrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 1);
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ // with wrap
+ ctxt->setContextProperty("testWrap", QVariant(true));
+ QVERIFY(listview->isWrapEnabled());
+
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), model.count()-1);
+
+ QTRY_COMPARE(listview->contentY(), 280.0);
+
+ listview->incrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ QTRY_COMPARE(listview->contentY(), 0.0);
+
+
+ // footer should become visible if it is out of view, and then current index is set to count-1
+ canvas->rootObject()->setProperty("showFooter", true);
+ QTRY_VERIFY(listview->footerItem());
+ listview->setCurrentIndex(model.count()-2);
+ QTRY_VERIFY(listview->footerItem()->y() > listview->contentY() + listview->height());
+ listview->setCurrentIndex(model.count()-1);
+ QTRY_COMPARE(listview->contentY() + listview->height(), (20.0 * model.count()) + listview->footerItem()->height());
+ canvas->rootObject()->setProperty("showFooter", false);
+
+ // header should become visible if it is out of view, and then current index is set to 0
+ canvas->rootObject()->setProperty("showHeader", true);
+ QTRY_VERIFY(listview->headerItem());
+ listview->setCurrentIndex(1);
+ QTRY_VERIFY(listview->headerItem()->y() + listview->headerItem()->height() < listview->contentY());
+ listview->setCurrentIndex(0);
+ QTRY_COMPARE(listview->contentY(), -listview->headerItem()->height());
+ canvas->rootObject()->setProperty("showHeader", false);
+
+
+ // Test keys
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
+
+ listview->setCurrentIndex(0);
+
+ QTest::keyClick(canvas, Qt::Key_Down);
+ QCOMPARE(listview->currentIndex(), 1);
+
+ QTest::keyClick(canvas, Qt::Key_Up);
+ QCOMPARE(listview->currentIndex(), 0);
+
+ // hold down Key_Down
+ for (int i=0; i<model.count()-1; i++) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
+ QTRY_COMPARE(listview->currentIndex(), i+1);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Down);
+ QTRY_COMPARE(listview->currentIndex(), model.count()-1);
+ QTRY_COMPARE(listview->contentY(), 280.0);
+
+ // hold down Key_Up
+ for (int i=model.count()-1; i > 0; i--) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
+ QTRY_COMPARE(listview->currentIndex(), i-1);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Up);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QTRY_COMPARE(listview->contentY(), 0.0);
+
+
+ // turn off auto highlight
+ listview->setHighlightFollowsCurrentItem(false);
+ QVERIFY(listview->highlightFollowsCurrentItem() == false);
+
+ QVERIFY(listview->highlightItem());
+ qreal hlPos = listview->highlightItem()->y();
+
+ listview->setCurrentIndex(4);
+ QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
+
+ // insert item before currentIndex
+ listview->setCurrentIndex(28);
+ model.insertItem(0, "Foo", "1111");
+ QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
+
+ // check removing highlight by setting currentIndex to -1;
+ listview->setCurrentIndex(-1);
+
+ QCOMPARE(listview->currentIndex(), -1);
+ QVERIFY(!listview->highlightItem());
+ QVERIFY(!listview->currentItem());
+
+ delete canvas;
+}
+
+void tst_QQuickListView::noCurrentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(TESTDATA("listview-noCurrent.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // current index should be -1 at startup
+ // and we should not have a currentItem or highlightItem
+ QCOMPARE(listview->currentIndex(), -1);
+ QCOMPARE(listview->contentY(), 0.0);
+ QVERIFY(!listview->highlightItem());
+ QVERIFY(!listview->currentItem());
+
+ listview->setCurrentIndex(2);
+ QCOMPARE(listview->currentIndex(), 2);
+ QVERIFY(listview->highlightItem());
+ QVERIFY(listview->currentItem());
+
+ delete canvas;
+}
+
+void tst_QQuickListView::itemList()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("itemlist.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
+ QTRY_VERIFY(model != 0);
+
+ QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), 0.0);
+ QCOMPARE(item->height(), listview->height());
+
+ QQuickText *text = findItem<QQuickText>(contentItem, "text1");
+ QTRY_VERIFY(text);
+ QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
+
+ listview->setCurrentIndex(2);
+
+ item = findItem<QQuickItem>(contentItem, "item3");
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), 480.0);
+
+ text = findItem<QQuickText>(contentItem, "text3");
+ QTRY_VERIFY(text);
+ QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
+
+ delete canvas;
+}
+
+void tst_QQuickListView::cacheBuffer()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 90; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(listview->delegate() != 0);
+ QTRY_VERIFY(listview->model() != 0);
+ QTRY_VERIFY(listview->highlight() != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*20);
+ }
+
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ testObject->setCacheBuffer(200);
+ QTRY_VERIFY(listview->cacheBuffer() == 200);
+
+ // items will be created one at a time
+ for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(listview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ int newItemCount = 0;
+ newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < newItemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*20);
+ }
+
+ // move view and confirm items in view are visible immediately and outside are created async
+ listview->setContentY(300);
+
+ for (int i = 15; i < 32; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QVERIFY(item);
+ QVERIFY(item->y() == i*20);
+ }
+
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
+
+ // ensure buffered items are created
+ for (int i = 32; i < qMin(41,model.count()); ++i) {
+ QQuickItem *item = 0;
+ while (!item) {
+ qGuiApp->processEvents(); // allow refill to happen
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(listview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::positionViewAtIndex()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position on a currently visible item
+ listview->positionViewAtIndex(3, QQuickListView::Beginning);
+ QTRY_COMPARE(listview->contentY(), 60.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position on an item beyond the visible items
+ listview->positionViewAtIndex(22, QQuickListView::Beginning);
+ QTRY_COMPARE(listview->contentY(), 440.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position on an item that would leave empty space if positioned at the top
+ listview->positionViewAtIndex(28, QQuickListView::Beginning);
+ QTRY_COMPARE(listview->contentY(), 480.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position at the beginning again
+ listview->positionViewAtIndex(0, QQuickListView::Beginning);
+ QTRY_COMPARE(listview->contentY(), 0.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position at End using last index
+ listview->positionViewAtIndex(model.count()-1, QQuickListView::End);
+ QTRY_COMPARE(listview->contentY(), 480.);
+
+ // Confirm items positioned correctly
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 24; i < model.count(); ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ // Position at End
+ listview->positionViewAtIndex(20, QQuickListView::End);
+ QTRY_COMPARE(listview->contentY(), 100.);
+
+ // Position in Center
+ listview->positionViewAtIndex(15, QQuickListView::Center);
+ QTRY_COMPARE(listview->contentY(), 150.);
+
+ // Ensure at least partially visible
+ listview->positionViewAtIndex(15, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), 150.);
+
+ listview->setContentY(302);
+ listview->positionViewAtIndex(15, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), 302.);
+
+ listview->setContentY(320);
+ listview->positionViewAtIndex(15, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), 300.);
+
+ listview->setContentY(85);
+ listview->positionViewAtIndex(20, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), 85.);
+
+ listview->setContentY(75);
+ listview->positionViewAtIndex(20, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), 100.);
+
+ // Ensure completely visible
+ listview->setContentY(120);
+ listview->positionViewAtIndex(20, QQuickListView::Contain);
+ QTRY_COMPARE(listview->contentY(), 120.);
+
+ listview->setContentY(302);
+ listview->positionViewAtIndex(15, QQuickListView::Contain);
+ QTRY_COMPARE(listview->contentY(), 300.);
+
+ listview->setContentY(85);
+ listview->positionViewAtIndex(20, QQuickListView::Contain);
+ QTRY_COMPARE(listview->contentY(), 100.);
+
+ // positionAtBeginnging
+ listview->positionViewAtBeginning();
+ QTRY_COMPARE(listview->contentY(), 0.);
+
+ listview->setContentY(80);
+ canvas->rootObject()->setProperty("showHeader", true);
+ listview->positionViewAtBeginning();
+ QTRY_COMPARE(listview->contentY(), -30.);
+
+ // positionAtEnd
+ listview->positionViewAtEnd();
+ QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320
+
+ listview->setContentY(80);
+ canvas->rootObject()->setProperty("showFooter", true);
+ listview->positionViewAtEnd();
+ QTRY_COMPARE(listview->contentY(), 510.);
+
+ // set current item to outside visible view, position at beginning
+ // and ensure highlight moves to current item
+ listview->setCurrentIndex(1);
+ listview->positionViewAtBeginning();
+ QTRY_COMPARE(listview->contentY(), -30.);
+ QVERIFY(listview->highlightItem());
+ QCOMPARE(listview->highlightItem()->y(), 20.);
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::resetModel()
+{
+ QQuickView *canvas = createView();
+
+ QStringList strings;
+ strings << "one" << "two" << "three";
+ QStringListModel model(strings);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(listview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
+ QTRY_VERIFY(display != 0);
+ QTRY_COMPARE(display->text(), strings.at(i));
+ }
+
+ strings.clear();
+ strings << "four" << "five" << "six" << "seven";
+ model.setStringList(strings);
+
+ QTRY_COMPARE(listview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
+ QTRY_VERIFY(display != 0);
+ QTRY_COMPARE(display->text(), strings.at(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickListView::propertyChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
+ QTRY_VERIFY(listView);
+
+ QSignalSpy highlightFollowsCurrentItemSpy(listView, SIGNAL(highlightFollowsCurrentItemChanged()));
+ QSignalSpy preferredHighlightBeginSpy(listView, SIGNAL(preferredHighlightBeginChanged()));
+ QSignalSpy preferredHighlightEndSpy(listView, SIGNAL(preferredHighlightEndChanged()));
+ QSignalSpy highlightRangeModeSpy(listView, SIGNAL(highlightRangeModeChanged()));
+ QSignalSpy keyNavigationWrapsSpy(listView, SIGNAL(keyNavigationWrapsChanged()));
+ QSignalSpy cacheBufferSpy(listView, SIGNAL(cacheBufferChanged()));
+ QSignalSpy snapModeSpy(listView, SIGNAL(snapModeChanged()));
+
+ QTRY_COMPARE(listView->highlightFollowsCurrentItem(), true);
+ QTRY_COMPARE(listView->preferredHighlightBegin(), 0.0);
+ QTRY_COMPARE(listView->preferredHighlightEnd(), 0.0);
+ QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::ApplyRange);
+ QTRY_COMPARE(listView->isWrapEnabled(), true);
+ QTRY_COMPARE(listView->cacheBuffer(), 10);
+ QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapToItem);
+
+ listView->setHighlightFollowsCurrentItem(false);
+ listView->setPreferredHighlightBegin(1.0);
+ listView->setPreferredHighlightEnd(1.0);
+ listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
+ listView->setWrapEnabled(false);
+ listView->setCacheBuffer(3);
+ listView->setSnapMode(QQuickListView::SnapOneItem);
+
+ QTRY_COMPARE(listView->highlightFollowsCurrentItem(), false);
+ QTRY_COMPARE(listView->preferredHighlightBegin(), 1.0);
+ QTRY_COMPARE(listView->preferredHighlightEnd(), 1.0);
+ QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
+ QTRY_COMPARE(listView->isWrapEnabled(), false);
+ QTRY_COMPARE(listView->cacheBuffer(), 3);
+ QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapOneItem);
+
+ QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
+ QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
+ QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
+ QTRY_COMPARE(highlightRangeModeSpy.count(),1);
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
+ QTRY_COMPARE(cacheBufferSpy.count(),1);
+ QTRY_COMPARE(snapModeSpy.count(),1);
+
+ listView->setHighlightFollowsCurrentItem(false);
+ listView->setPreferredHighlightBegin(1.0);
+ listView->setPreferredHighlightEnd(1.0);
+ listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
+ listView->setWrapEnabled(false);
+ listView->setCacheBuffer(3);
+ listView->setSnapMode(QQuickListView::SnapOneItem);
+
+ QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
+ QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
+ QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
+ QTRY_COMPARE(highlightRangeModeSpy.count(),1);
+ QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
+ QTRY_COMPARE(cacheBufferSpy.count(),1);
+ QTRY_COMPARE(snapModeSpy.count(),1);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::componentChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
+ QTRY_VERIFY(listView);
+
+ QDeclarativeComponent component(canvas->engine());
+ component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
+
+ QDeclarativeComponent delegateComponent(canvas->engine());
+ delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
+
+ QSignalSpy highlightSpy(listView, SIGNAL(highlightChanged()));
+ QSignalSpy delegateSpy(listView, SIGNAL(delegateChanged()));
+ QSignalSpy headerSpy(listView, SIGNAL(headerChanged()));
+ QSignalSpy footerSpy(listView, SIGNAL(footerChanged()));
+
+ listView->setHighlight(&component);
+ listView->setHeader(&component);
+ listView->setFooter(&component);
+ listView->setDelegate(&delegateComponent);
+
+ QTRY_COMPARE(listView->highlight(), &component);
+ QTRY_COMPARE(listView->header(), &component);
+ QTRY_COMPARE(listView->footer(), &component);
+ QTRY_COMPARE(listView->delegate(), &delegateComponent);
+
+ QTRY_COMPARE(highlightSpy.count(),1);
+ QTRY_COMPARE(delegateSpy.count(),1);
+ QTRY_COMPARE(headerSpy.count(),1);
+ QTRY_COMPARE(footerSpy.count(),1);
+
+ listView->setHighlight(&component);
+ listView->setHeader(&component);
+ listView->setFooter(&component);
+ listView->setDelegate(&delegateComponent);
+
+ QTRY_COMPARE(highlightSpy.count(),1);
+ QTRY_COMPARE(delegateSpy.count(),1);
+ QTRY_COMPARE(headerSpy.count(),1);
+ QTRY_COMPARE(footerSpy.count(),1);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::modelChanges()
+{
+ QQuickView *canvas = createView();
+ QTRY_VERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
+
+ QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
+ QTRY_VERIFY(listView);
+
+ QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
+ QTRY_VERIFY(alternateModel);
+ QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
+ QSignalSpy modelSpy(listView, SIGNAL(modelChanged()));
+
+ listView->setModel(modelVariant);
+ QTRY_COMPARE(listView->model(), modelVariant);
+ QTRY_COMPARE(modelSpy.count(),1);
+
+ listView->setModel(modelVariant);
+ QTRY_COMPARE(modelSpy.count(),1);
+
+ listView->setModel(QVariant());
+ QTRY_COMPARE(modelSpy.count(),2);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::QTBUG_9791()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("strictlyenforcerange.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(listview->delegate() != 0);
+ QTRY_VERIFY(listview->model() != 0);
+
+ QMetaObject::invokeMethod(listview, "fillModel");
+ qApp->processEvents();
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ QCOMPARE(itemCount, 3);
+
+ for (int i = 0; i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), i*300.0);
+ }
+
+ // check that view is positioned correctly
+ QTRY_COMPARE(listview->contentX(), 590.0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::manualHighlight()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ QString filename(TESTDATA("manual-highlight.qml"));
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
+ QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
+
+ listview->setCurrentIndex(2);
+
+ QTRY_COMPARE(listview->currentIndex(), 2);
+ QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
+ QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
+
+ // QTBUG-15972
+ listview->positionViewAtIndex(3, QQuickListView::Contain);
+
+ QTRY_COMPARE(listview->currentIndex(), 2);
+ QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
+ QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
+
+ delete canvas;
+}
+
+void tst_QQuickListView::QTBUG_11105()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_VERIFY(item->y() == i*20);
+ }
+
+ listview->positionViewAtIndex(20, QQuickListView::Beginning);
+ QCOMPARE(listview->contentY(), 280.);
+
+ TestModel model2;
+ for (int i = 0; i < 5; i++)
+ model2.addItem("Item" + QString::number(i), "");
+
+ ctxt->setContextProperty("testModel", &model2);
+
+ itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ QCOMPARE(itemCount, 5);
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::header()
+{
+ QFETCH(QQuickListView::Orientation, orientation);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(QPointF, initialHeaderPos);
+ QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, initialContentPos);
+ QFETCH(QPointF, changedHeaderPos);
+ QFETCH(QPointF, changedContentPos);
+ QFETCH(QPointF, resizeContentPos);
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QQuickView *canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *header = findItem<QQuickText>(contentItem, "header");
+ QVERIFY(header);
+
+ QVERIFY(header == listview->headerItem());
+
+ QCOMPARE(header->width(), 100.);
+ QCOMPARE(header->height(), 30.);
+ QCOMPARE(header->pos(), initialHeaderPos);
+ QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ model.clear();
+ QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
+
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QSignalSpy headerItemSpy(listview, SIGNAL(headerItemChanged()));
+ QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
+
+ QCOMPARE(headerItemSpy.count(), 1);
+
+ header = findItem<QQuickText>(contentItem, "header");
+ QVERIFY(!header);
+ header = findItem<QQuickText>(contentItem, "header2");
+ QVERIFY(header);
+
+ QVERIFY(header == listview->headerItem());
+
+ QCOMPARE(header->pos(), changedHeaderPos);
+ QCOMPARE(header->width(), 50.);
+ QCOMPARE(header->height(), 20.);
+ QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ delete canvas;
+
+
+ // QTBUG-21207 header should become visible if view resizes from initial empty size
+
+ canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 0.0);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 0.0);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
+
+ listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+
+ listview->setWidth(240);
+ listview->setHeight(320);
+ QTRY_COMPARE(listview->headerItem()->pos(), initialHeaderPos);
+ QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
+
+
+ delete canvas;
+}
+
+void tst_QQuickListView::header_data()
+{
+ QTest::addColumn<QQuickListView::Orientation>("orientation");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QPointF>("initialHeaderPos");
+ QTest::addColumn<QPointF>("changedHeaderPos");
+ QTest::addColumn<QPointF>("initialContentPos");
+ QTest::addColumn<QPointF>("changedContentPos");
+ QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
+
+ // header1 = 100 x 30
+ // header2 = 50 x 20
+ // delegates = 240 x 20
+ // view width = 240
+
+ // header above items, top left
+ QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, 0)
+ << QPointF(0, -10);
+
+ // header above items, top right
+ QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, -30)
+ << QPointF(0, -20)
+ << QPointF(0, 0)
+ << QPointF(0, -10);
+
+ // header to left of items
+ QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
+ << QPointF(-100, 0)
+ << QPointF(-50, 0)
+ << QPointF(-100, 0)
+ << QPointF(-50, 0)
+ << QPointF(0, 0)
+ << QPointF(-40, 0);
+
+ // header to right of items
+ QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(-240 + 100, 0)
+ << QPointF(-240 + 50, 0)
+ << QPointF(-240, 0)
+ << QPointF(-240 + 40, 0);
+}
+
+void tst_QQuickListView::header_delayItemCreation()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+
+ canvas->rootContext()->setContextProperty("setCurrentToZero", QVariant(false));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("fillModelOnComponentCompleted.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *header = findItem<QQuickText>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->y(), -header->height());
+
+ QCOMPARE(listview->contentY(), -header->height());
+
+ model.clear();
+ QTRY_COMPARE(header->y(), -header->height());
+
+ delete canvas;
+}
+
+void tst_QQuickListView::footer()
+{
+ QFETCH(QQuickListView::Orientation, orientation);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(QPointF, initialFooterPos);
+ QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, initialContentPos);
+ QFETCH(QPointF, changedFooterPos);
+ QFETCH(QPointF, changedContentPos);
+ QFETCH(QPointF, resizeContentPos);
+
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 3; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("footer.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
+ QVERIFY(footer);
+
+ QVERIFY(footer == listview->footerItem());
+
+ QCOMPARE(footer->pos(), initialFooterPos);
+ QCOMPARE(footer->width(), 100.);
+ QCOMPARE(footer->height(), 30.);
+ QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ // remove one item
+ model.removeItem(1);
+
+ if (orientation == QQuickListView::Vertical) {
+ QTRY_COMPARE(footer->y(), initialFooterPos.y() - 20); // delegate height = 20
+ } else {
+ QTRY_COMPARE(footer->x(), layoutDirection == Qt::LeftToRight ?
+ initialFooterPos.x() - 40 : initialFooterPos.x() + 40); // delegate width = 40
+ }
+
+ // remove all items
+ model.clear();
+
+ QPointF posWhenNoItems(0, 0);
+ if (orientation == QQuickListView::Horizontal && layoutDirection == Qt::RightToLeft)
+ posWhenNoItems.setX(-100);
+ QTRY_COMPARE(footer->pos(), posWhenNoItems);
+
+ // if header is present, it's at a negative pos, so the footer should not move
+ canvas->rootObject()->setProperty("showHeader", true);
+ QTRY_COMPARE(footer->pos(), posWhenNoItems);
+ canvas->rootObject()->setProperty("showHeader", false);
+
+ // add 30 items
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QSignalSpy footerItemSpy(listview, SIGNAL(footerItemChanged()));
+ QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
+
+ QCOMPARE(footerItemSpy.count(), 1);
+
+ footer = findItem<QQuickText>(contentItem, "footer");
+ QVERIFY(!footer);
+ footer = findItem<QQuickText>(contentItem, "footer2");
+ QVERIFY(footer);
+
+ QVERIFY(footer == listview->footerItem());
+
+ QCOMPARE(footer->pos(), changedFooterPos);
+ QCOMPARE(footer->width(), 50.);
+ QCOMPARE(footer->height(), 20.);
+ QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->pos(), firstDelegatePos);
+
+ listview->positionViewAtEnd();
+ footer->setHeight(10);
+ footer->setWidth(40);
+ QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::footer_data()
+{
+ QTest::addColumn<QQuickListView::Orientation>("orientation");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QPointF>("initialFooterPos");
+ QTest::addColumn<QPointF>("changedFooterPos");
+ QTest::addColumn<QPointF>("initialContentPos");
+ QTest::addColumn<QPointF>("changedContentPos");
+ QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
+
+ // footer1 = 100 x 30
+ // footer2 = 50 x 20
+ // delegates = 40 x 20
+ // view width = 240
+ // view height = 320
+
+ // footer below items, bottom left
+ QTest::newRow("vertical, layout left to right") << QQuickListView::Vertical << Qt::LeftToRight
+ << QPointF(0, 3 * 20)
+ << QPointF(0, 30 * 20) // added 30 items
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 30 * 20 - 320 + 10);
+
+ // footer below items, bottom right
+ QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
+ << QPointF(0, 3 * 20)
+ << QPointF(0, 30 * 20)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 30 * 20 - 320 + 10);
+
+ // footer to right of items
+ QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
+ << QPointF(40 * 3, 0)
+ << QPointF(40 * 30, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(0, 0)
+ << QPointF(40 * 30 - 240 + 40, 0);
+
+ // footer to left of items
+ QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
+ << QPointF(-(40 * 3) - 100, 0)
+ << QPointF(-(40 * 30) - 50, 0) // 50 = new footer width
+ << QPointF(-240, 0)
+ << QPointF(-240, 0)
+ << QPointF(-40, 0)
+ << QPointF(-(40 * 30) - 40, 0);
+}
+
+class LVAccessor : public QQuickListView
+{
+public:
+ qreal minY() const { return minYExtent(); }
+ qreal maxY() const { return maxYExtent(); }
+ qreal minX() const { return minXExtent(); }
+ qreal maxX() const { return maxXExtent(); }
+};
+
+void tst_QQuickListView::headerFooter()
+{
+ {
+ // Vertical
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->y(), -header->height());
+
+ QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->y(), 0.);
+
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minY(), header->height());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxY(), header->height());
+
+ delete canvas;
+ }
+ {
+ // Horizontal
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
+ canvas->rootObject()->setProperty("horizontal", true);
+ qApp->processEvents();
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), -header->width());
+
+ QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), 0.);
+
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), header->width());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), header->width());
+
+ delete canvas;
+ }
+ {
+ // Horizontal RTL
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("headerfooter.qml")));
+ canvas->rootObject()->setProperty("horizontal", true);
+ canvas->rootObject()->setProperty("rtl", true);
+ qApp->processEvents();
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), 0.);
+
+ QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), -footer->width());
+
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240. - header->width());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240. - header->width());
+
+ delete canvas;
+ }
+}
+
+void tst_QQuickListView::resizeView()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*20.);
+ }
+
+ QVariant heightRatio;
+ QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
+ QCOMPARE(heightRatio.toReal(), 0.4);
+
+ listview->setHeight(200);
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
+ QCOMPARE(heightRatio.toReal(), 0.25);
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::resizeViewAndRepaint()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < 40; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("initialHeight", 100);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizeview.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // item at index 10 should not be currently visible
+ QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ listview->setHeight(320);
+ QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ listview->setHeight(100);
+ QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
+
+ delete canvas;
+}
+
+void tst_QQuickListView::sizeLessThan1()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("sizelessthan1.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // Confirm items positioned correctly
+ int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
+ for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ if (!item) qWarning() << "Item" << i << "not found";
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->y(), i*0.5);
+ }
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::QTBUG_14821()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug14821.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ listview->decrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 99);
+
+ listview->incrementCurrentIndex();
+ QCOMPARE(listview->currentIndex(), 0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::resizeDelegate()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ QStringList strings;
+ for (int i = 0; i < 30; ++i)
+ strings << QString::number(i);
+ QStringListModel model(strings);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QCOMPARE(listview->count(), model.rowCount());
+
+ listview->setCurrentIndex(25);
+ listview->setContentY(0);
+ QTest::qWait(300);
+
+ for (int i = 0; i < 16; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QCOMPARE(item->y(), i*20.0);
+ }
+
+ QCOMPARE(listview->currentItem()->y(), 500.0);
+ QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
+
+ canvas->rootObject()->setProperty("delegateHeight", 30);
+ QTest::qWait(300);
+
+ for (int i = 0; i < 11; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QTRY_COMPARE(item->y(), i*30.0);
+ }
+
+ QTRY_COMPARE(listview->currentItem()->y(), 750.0);
+ QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
+
+ listview->setCurrentIndex(1);
+ listview->positionViewAtIndex(25, QQuickListView::Beginning);
+ listview->positionViewAtIndex(5, QQuickListView::Beginning);
+
+ for (int i = 5; i < 16; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QCOMPARE(item->y(), i*30.0);
+ }
+
+ QTRY_COMPARE(listview->currentItem()->y(), 30.0);
+ QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
+
+ canvas->rootObject()->setProperty("delegateHeight", 20);
+ QTest::qWait(300);
+
+ for (int i = 5; i < 11; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
+ }
+
+ QTRY_COMPARE(listview->currentItem()->y(), 70.0);
+ QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::resizeFirstDelegate()
+{
+ // QTBUG-20712: Content Y jumps constantly if first delegate height == 0
+ // and other delegates have height > 0
+
+ QSKIP("Test unstable - QTBUG-22872");
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ // bug only occurs when all items in the model are visible
+ TestModel model;
+ for (int i = 0; i < 10; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickItem *item = 0;
+ for (int i = 0; i < model.count(); ++i) {
+ item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QCOMPARE(item->y(), i*20.0);
+ }
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 0);
+ item->setHeight(0);
+
+ // check the content y has not jumped up and down
+ QCOMPARE(listview->contentY(), 0.0);
+ QSignalSpy spy(listview, SIGNAL(contentYChanged()));
+ QTest::qWait(100);
+ QCOMPARE(spy.count(), 0);
+
+ for (int i = 1; i < model.count(); ++i) {
+ item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QVERIFY(item != 0);
+ QTRY_COMPARE(item->y(), (i-1)*20.0);
+ }
+
+
+ // QTBUG-22014: refill doesn't clear items scrolling off the top of the
+ // list if they follow a zero-sized delegate
+
+ for (int i = 0; i < 10; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ item = findItem<QQuickItem>(contentItem, "wrapper", 1);
+ QVERIFY(item);
+ item->setHeight(0);
+
+ listview->setCurrentIndex(19);
+ qApp->processEvents();
+
+ // items 0-2 should have been deleted
+ for (int i=0; i<3; i++) {
+ QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", i));
+ }
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickListView::QTBUG_16037()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug16037.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "listview");
+ QTRY_VERIFY(listview != 0);
+
+ QVERIFY(listview->contentHeight() <= 0.0);
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "setModel");
+
+ QTRY_COMPARE(listview->contentHeight(), 80.0);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::indexAt()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("listviewtest.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QCOMPARE(listview->indexAt(0,0), 0);
+ QCOMPARE(listview->indexAt(0,19), 0);
+ QCOMPARE(listview->indexAt(239,19), 0);
+ QCOMPARE(listview->indexAt(0,20), 1);
+ QCOMPARE(listview->indexAt(240,20), -1);
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickListView::incrementalModel()
+{
+ QQuickView *canvas = createView();
+
+ IncrementalModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaylist.qml")));
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(listview->count(), 20);
+
+ listview->positionViewAtIndex(10, QQuickListView::Beginning);
+
+ QTRY_COMPARE(listview->count(), 25);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::onAdd()
+{
+ QFETCH(int, initialItemCount);
+ QFETCH(int, itemsToAdd);
+
+ const int delegateHeight = 10;
+ TestModel2 model;
+
+ // these initial items should not trigger ListView.onAdd
+ for (int i=0; i<initialItemCount; i++)
+ model.addItem("dummy value", "dummy value");
+
+ QQuickView *canvas = createView();
+ canvas->setGeometry(0,0,200, delegateHeight * (initialItemCount + itemsToAdd));
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("delegateHeight", delegateHeight);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
+
+ QObject *object = canvas->rootObject();
+ object->setProperty("width", canvas->width());
+ object->setProperty("height", canvas->height());
+ qApp->processEvents();
+
+ QList<QPair<QString, QString> > items;
+ for (int i=0; i<itemsToAdd; i++)
+ items << qMakePair(QString("value %1").arg(i), QString::number(i));
+ model.addItems(items);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QVariantList result = object->property("addedDelegates").toList();
+ QCOMPARE(result.count(), items.count());
+ for (int i=0; i<items.count(); i++)
+ QCOMPARE(result[i].toString(), items[i].first);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::onAdd_data()
+{
+ QTest::addColumn<int>("initialItemCount");
+ QTest::addColumn<int>("itemsToAdd");
+
+ QTest::newRow("0, add 1") << 0 << 1;
+ QTest::newRow("0, add 2") << 0 << 2;
+ QTest::newRow("0, add 10") << 0 << 10;
+
+ QTest::newRow("1, add 1") << 1 << 1;
+ QTest::newRow("1, add 2") << 1 << 2;
+ QTest::newRow("1, add 10") << 1 << 10;
+
+ QTest::newRow("5, add 1") << 5 << 1;
+ QTest::newRow("5, add 2") << 5 << 2;
+ QTest::newRow("5, add 10") << 5 << 10;
+}
+
+void tst_QQuickListView::onRemove()
+{
+ QFETCH(int, initialItemCount);
+ QFETCH(int, indexToRemove);
+ QFETCH(int, removeCount);
+
+ const int delegateHeight = 10;
+ TestModel2 model;
+ for (int i=0; i<initialItemCount; i++)
+ model.addItem(QString("value %1").arg(i), "dummy value");
+
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("delegateHeight", delegateHeight);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
+ QObject *object = canvas->rootObject();
+
+ model.removeItems(indexToRemove, removeCount);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
+ QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
+
+ delete canvas;
+}
+
+void tst_QQuickListView::onRemove_data()
+{
+ QTest::addColumn<int>("initialItemCount");
+ QTest::addColumn<int>("indexToRemove");
+ QTest::addColumn<int>("removeCount");
+
+ QTest::newRow("remove first") << 1 << 0 << 1;
+ QTest::newRow("two items, remove first") << 2 << 0 << 1;
+ QTest::newRow("two items, remove last") << 2 << 1 << 1;
+ QTest::newRow("two items, remove all") << 2 << 0 << 2;
+
+ QTest::newRow("four items, remove first") << 4 << 0 << 1;
+ QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
+ QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
+ QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
+ QTest::newRow("four items, remove last") << 4 << 3 << 1;
+ QTest::newRow("four items, remove all") << 4 << 0 << 4;
+
+ QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
+ QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
+ QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
+}
+
+void tst_QQuickListView::rightToLeft()
+{
+ QQuickView *canvas = createView();
+ canvas->setGeometry(0,0,640,320);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
+ qApp->processEvents();
+
+ QVERIFY(canvas->rootObject() != 0);
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
+ QTRY_VERIFY(model != 0);
+
+ QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+
+ // initial position at first item, right edge aligned
+ QCOMPARE(listview->contentX(), -640.);
+
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), -100.0);
+ QCOMPARE(item->height(), listview->height());
+
+ QQuickText *text = findItem<QQuickText>(contentItem, "text1");
+ QTRY_VERIFY(text);
+ QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
+
+ listview->setCurrentIndex(2);
+
+ item = findItem<QQuickItem>(contentItem, "item3");
+ QTRY_VERIFY(item);
+ QTRY_COMPARE(item->x(), -540.0);
+
+ text = findItem<QQuickText>(contentItem, "text3");
+ QTRY_VERIFY(text);
+ QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
+
+ QCOMPARE(listview->contentX(), -640.);
+
+ // Ensure resizing maintains position relative to right edge
+ qobject_cast<QQuickItem*>(canvas->rootObject())->setWidth(600);
+ QTRY_COMPARE(listview->contentX(), -600.);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::test_mirroring()
+{
+ QQuickView *canvasA = createView();
+ canvasA->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
+ QQuickListView *listviewA = findItem<QQuickListView>(canvasA->rootObject(), "view");
+ QTRY_VERIFY(listviewA != 0);
+
+ QQuickView *canvasB = createView();
+ canvasB->setSource(QUrl::fromLocalFile(TESTDATA("rightToLeft.qml")));
+ QQuickListView *listviewB = findItem<QQuickListView>(canvasB->rootObject(), "view");
+ QTRY_VERIFY(listviewA != 0);
+ qApp->processEvents();
+
+ QList<QString> objectNames;
+ objectNames << "item1" << "item2"; // << "item3"
+
+ listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+ listviewB->setProperty("layoutDirection", Qt::RightToLeft);
+ QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
+
+ // LTR != RTL
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
+
+ listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+ listviewB->setProperty("layoutDirection", Qt::LeftToRight);
+
+ // LTR == LTR
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
+
+ QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
+ QQuickItemPrivate::get(listviewB)->setLayoutMirror(true);
+ QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
+
+ // LTR != LTR+mirror
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
+
+ listviewA->setProperty("layoutDirection", Qt::RightToLeft);
+
+ // RTL == LTR+mirror
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
+
+ listviewB->setProperty("layoutDirection", Qt::RightToLeft);
+
+ // RTL != RTL+mirror
+ foreach (const QString objectName, objectNames)
+ QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
+
+ listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+
+ // LTR == RTL+mirror
+ foreach (const QString objectName, objectNames)
+ QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
+
+ delete canvasA;
+ delete canvasB;
+}
+
+void tst_QQuickListView::margins()
+{
+ QQuickView *canvas = createView();
+
+ TestModel2 model;
+ for (int i = 0; i < 50; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QCOMPARE(listview->contentY(), -30.);
+ QCOMPARE(listview->yOrigin(), 0.);
+
+ // check end bound
+ listview->positionViewAtEnd();
+ qreal pos = listview->contentY();
+ listview->setContentY(pos + 80);
+ listview->returnToBounds();
+ QTRY_COMPARE(listview->contentY(), pos + 50);
+
+ // remove item before visible and check that top margin is maintained
+ // and yOrigin is updated
+ listview->setContentY(100);
+ model.removeItem(1);
+ QTest::qWait(100);
+ listview->setContentY(-50);
+ listview->returnToBounds();
+ QCOMPARE(listview->yOrigin(), 20.);
+ QTRY_COMPARE(listview->contentY(), -10.);
+
+ // reduce top margin
+ listview->setTopMargin(20);
+ QCOMPARE(listview->yOrigin(), 20.);
+ QTRY_COMPARE(listview->contentY(), 0.);
+
+ // check end bound
+ listview->positionViewAtEnd();
+ pos = listview->contentY();
+ listview->setContentY(pos + 80);
+ listview->returnToBounds();
+ QTRY_COMPARE(listview->contentY(), pos + 50);
+
+ // reduce bottom margin
+ pos = listview->contentY();
+ listview->setBottomMargin(40);
+ QCOMPARE(listview->yOrigin(), 20.);
+ QTRY_COMPARE(listview->contentY(), pos-10);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::snapToItem_data()
+{
+ QTest::addColumn<QQuickListView::Orientation>("orientation");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<int>("highlightRangeMode");
+ QTest::addColumn<QPoint>("flickStart");
+ QTest::addColumn<QPoint>("flickEnd");
+ QTest::addColumn<qreal>("snapAlignment");
+ QTest::addColumn<qreal>("endExtent");
+ QTest::addColumn<qreal>("startExtent");
+
+ QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, left to right") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
+
+ QTest::newRow("horizontal, right to left") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
+
+ QTest::newRow("vertical, left to right, enforce range") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, left to right, enforce range") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
+
+ QTest::newRow("horizontal, right to left, enforce range") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
+}
+
+void tst_QQuickListView::snapToItem()
+{
+ QFETCH(QQuickListView::Orientation, orientation);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(int, highlightRangeMode);
+ QFETCH(QPoint, flickStart);
+ QFETCH(QPoint, flickEnd);
+ QFETCH(qreal, snapAlignment);
+ QFETCH(qreal, endExtent);
+ QFETCH(qreal, startExtent);
+
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToItem.qml")));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+ listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // confirm that a flick hits an item boundary
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ if (orientation == QQuickListView::Vertical)
+ QCOMPARE(qreal(fmod(listview->contentY(),80.0)), snapAlignment);
+ else
+ QCOMPARE(qreal(fmod(listview->contentX(),80.0)), snapAlignment);
+
+ // flick to end
+ do {
+ flick(canvas, flickStart, flickEnd, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ } while (orientation == QQuickListView::Vertical
+ ? !listview->isAtYEnd()
+ : layoutDirection == Qt::LeftToRight ? !listview->isAtXEnd() : !listview->isAtXBeginning());
+
+ if (orientation == QQuickListView::Vertical)
+ QCOMPARE(listview->contentY(), endExtent);
+ else
+ QCOMPARE(listview->contentX(), endExtent);
+
+ // flick to start
+ do {
+ flick(canvas, flickEnd, flickStart, 180);
+ QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
+ } while (orientation == QQuickListView::Vertical
+ ? !listview->isAtYBeginning()
+ : layoutDirection == Qt::LeftToRight ? !listview->isAtXBeginning() : !listview->isAtXEnd());
+
+ if (orientation == QQuickListView::Vertical)
+ QCOMPARE(listview->contentY(), startExtent);
+ else
+ QCOMPARE(listview->contentX(), startExtent);
+
+ delete canvas;
+}
+
+void tst_QQuickListView::qListModelInterface_items()
+{
+ items<TestModel>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_items()
+{
+ items<TestModel2>();
+}
+
+void tst_QQuickListView::qListModelInterface_changed()
+{
+ changed<TestModel>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_changed()
+{
+ changed<TestModel2>();
+}
+
+void tst_QQuickListView::qListModelInterface_inserted()
+{
+ inserted<TestModel>();
+}
+
+void tst_QQuickListView::qListModelInterface_inserted_more()
+{
+ inserted_more<TestModel>();
+}
+
+void tst_QQuickListView::qListModelInterface_inserted_more_data()
+{
+ inserted_more_data();
+}
+
+void tst_QQuickListView::qAbstractItemModel_inserted()
+{
+ inserted<TestModel2>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_inserted_more()
+{
+ inserted_more<TestModel2>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_inserted_more_data()
+{
+ inserted_more_data();
+}
+
+void tst_QQuickListView::qListModelInterface_removed()
+{
+ removed<TestModel>(false);
+ removed<TestModel>(true);
+}
+
+void tst_QQuickListView::qAbstractItemModel_removed()
+{
+ removed<TestModel2>(false);
+ removed<TestModel2>(true);
+}
+
+void tst_QQuickListView::qListModelInterface_moved()
+{
+ moved<TestModel>();
+}
+
+void tst_QQuickListView::qListModelInterface_moved_data()
+{
+ moved_data();
+}
+
+void tst_QQuickListView::qAbstractItemModel_moved()
+{
+ moved<TestModel2>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_moved_data()
+{
+ moved_data();
+}
+
+void tst_QQuickListView::qListModelInterface_clear()
+{
+ clear<TestModel>();
+}
+
+void tst_QQuickListView::qAbstractItemModel_clear()
+{
+ clear<TestModel2>();
+}
+
+void tst_QQuickListView::creationContext()
+{
+ QQuickView canvas;
+ canvas.setGeometry(0,0,240,320);
+ canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
+ qApp->processEvents();
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
+ QVERIFY(rootItem);
+ QVERIFY(rootItem->property("count").toInt() > 0);
+
+ QQuickItem *item;
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+ QVERIFY(item = rootItem->findChild<QQuickItem *>("section"));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+}
+
+void tst_QQuickListView::QTBUG_21742()
+{
+ QQuickView canvas;
+ canvas.setGeometry(0,0,200,200);
+ canvas.setSource(QUrl::fromLocalFile(TESTDATA("qtbug-21742.qml")));
+ qApp->processEvents();
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
+ QVERIFY(rootItem);
+ QCOMPARE(rootItem->property("count").toInt(), 1);
+}
+
+QQuickView *tst_QQuickListView::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ return canvas;
+}
+
+void tst_QQuickListView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
+{
+ const int pointCount = 5;
+ QPoint diff = to - from;
+
+ // send press, five equally spaced moves, and release.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, from);
+
+ for (int i = 0; i < pointCount; ++i) {
+ QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ QTest::qWait(duration/pointCount);
+ QCoreApplication::processEvents();
+ }
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
+}
+
+void tst_QQuickListView::asynchronous()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ canvas->setSource(TESTDATA("asyncloader.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootObject);
+
+ QQuickListView *listview = 0;
+ while (!listview) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ listview = rootObject->findChild<QQuickListView*>("view");
+ }
+
+ // items will be created one at a time
+ for (int i = 0; i < 8; ++i) {
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(listview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ // verify positioning
+ QQuickItem *contentItem = listview->contentItem();
+ for (int i = 0; i < 8; ++i) {
+ QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
+ QTRY_COMPARE(item->y(), i*50.0);
+ }
+
+ delete canvas;
+}
+
+QQuickItem *tst_QQuickListView::findVisibleChild(QQuickItem *parent, const QString &objectName)
+{
+ QQuickItem *item = 0;
+ QList<QQuickItem*> items = parent->findChildren<QQuickItem*>(objectName);
+ for (int i = 0; i < items.count(); ++i) {
+ if (items.at(i)->isVisible()) {
+ item = items.at(i);
+ break;
+ }
+ }
+ return item;
+}
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QQuickListView::findItem(QQuickItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeExpression e(qmlContext(item), item, "index");
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QQuickListView::findItems(QQuickItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item || !item->isVisible())
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ items.append(static_cast<T*>(item));
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+void tst_QQuickListView::dumpTree(QQuickItem *parent, int depth)
+{
+ static QString padding(" ");
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ qDebug() << padding.left(depth*2) << item;
+ dumpTree(item, depth+1);
+ }
+}
+
+QTEST_MAIN(tst_QQuickListView)
+
+#include "tst_qquicklistview.moc"
+
diff --git a/tests/auto/declarative/qquickloader/data/ActiveComponent.qml b/tests/auto/qtquick2/qquickloader/data/ActiveComponent.qml
index 24c6f7ad91..24c6f7ad91 100644
--- a/tests/auto/declarative/qquickloader/data/ActiveComponent.qml
+++ b/tests/auto/qtquick2/qquickloader/data/ActiveComponent.qml
diff --git a/tests/auto/declarative/qquickloader/data/AnchoredLoader.qml b/tests/auto/qtquick2/qquickloader/data/AnchoredLoader.qml
index 1a2a620d7f..1a2a620d7f 100644
--- a/tests/auto/declarative/qquickloader/data/AnchoredLoader.qml
+++ b/tests/auto/qtquick2/qquickloader/data/AnchoredLoader.qml
diff --git a/tests/auto/declarative/qquickloader/data/BigComponent.qml b/tests/auto/qtquick2/qquickloader/data/BigComponent.qml
index df92532c43..df92532c43 100644
--- a/tests/auto/declarative/qquickloader/data/BigComponent.qml
+++ b/tests/auto/qtquick2/qquickloader/data/BigComponent.qml
diff --git a/tests/auto/declarative/qquickloader/data/BlueRect.qml b/tests/auto/qtquick2/qquickloader/data/BlueRect.qml
index e96ac00f21..e96ac00f21 100644
--- a/tests/auto/declarative/qquickloader/data/BlueRect.qml
+++ b/tests/auto/qtquick2/qquickloader/data/BlueRect.qml
diff --git a/tests/auto/declarative/qquickloader/data/CreationContextLoader.qml b/tests/auto/qtquick2/qquickloader/data/CreationContextLoader.qml
index 4dd73e797c..4dd73e797c 100644
--- a/tests/auto/declarative/qquickloader/data/CreationContextLoader.qml
+++ b/tests/auto/qtquick2/qquickloader/data/CreationContextLoader.qml
diff --git a/tests/auto/declarative/qquickloader/data/GraphicsWidget250x250.qml b/tests/auto/qtquick2/qquickloader/data/GraphicsWidget250x250.qml
index dae8e3fbbb..dae8e3fbbb 100644
--- a/tests/auto/declarative/qquickloader/data/GraphicsWidget250x250.qml
+++ b/tests/auto/qtquick2/qquickloader/data/GraphicsWidget250x250.qml
diff --git a/tests/auto/declarative/qquickloader/data/GreenRect.qml b/tests/auto/qtquick2/qquickloader/data/GreenRect.qml
index 99cefaf176..99cefaf176 100644
--- a/tests/auto/declarative/qquickloader/data/GreenRect.qml
+++ b/tests/auto/qtquick2/qquickloader/data/GreenRect.qml
diff --git a/tests/auto/declarative/qquickloader/data/InitialPropertyValuesComponent.qml b/tests/auto/qtquick2/qquickloader/data/InitialPropertyValuesComponent.qml
index 24c6f7ad91..24c6f7ad91 100644
--- a/tests/auto/declarative/qquickloader/data/InitialPropertyValuesComponent.qml
+++ b/tests/auto/qtquick2/qquickloader/data/InitialPropertyValuesComponent.qml
diff --git a/tests/auto/declarative/qquickloader/data/InvalidSourceComponent.qml b/tests/auto/qtquick2/qquickloader/data/InvalidSourceComponent.qml
index 7efa4a5f61..7efa4a5f61 100644
--- a/tests/auto/declarative/qquickloader/data/InvalidSourceComponent.qml
+++ b/tests/auto/qtquick2/qquickloader/data/InvalidSourceComponent.qml
diff --git a/tests/auto/declarative/qquickloader/data/NoResize.qml b/tests/auto/qtquick2/qquickloader/data/NoResize.qml
index 9b3ea6410b..9b3ea6410b 100644
--- a/tests/auto/declarative/qquickloader/data/NoResize.qml
+++ b/tests/auto/qtquick2/qquickloader/data/NoResize.qml
diff --git a/tests/auto/declarative/qquickloader/data/NoResizeGraphicsWidget.qml b/tests/auto/qtquick2/qquickloader/data/NoResizeGraphicsWidget.qml
index c0f51d8c35..c0f51d8c35 100644
--- a/tests/auto/declarative/qquickloader/data/NoResizeGraphicsWidget.qml
+++ b/tests/auto/qtquick2/qquickloader/data/NoResizeGraphicsWidget.qml
diff --git a/tests/auto/declarative/qquickloader/data/QTBUG_16928.qml b/tests/auto/qtquick2/qquickloader/data/QTBUG_16928.qml
index 903d7f0812..903d7f0812 100644
--- a/tests/auto/declarative/qquickloader/data/QTBUG_16928.qml
+++ b/tests/auto/qtquick2/qquickloader/data/QTBUG_16928.qml
diff --git a/tests/auto/declarative/qquickloader/data/QTBUG_17114.qml b/tests/auto/qtquick2/qquickloader/data/QTBUG_17114.qml
index 7402037553..7402037553 100644
--- a/tests/auto/declarative/qquickloader/data/QTBUG_17114.qml
+++ b/tests/auto/qtquick2/qquickloader/data/QTBUG_17114.qml
diff --git a/tests/auto/declarative/qquickloader/data/Rect120x60.qml b/tests/auto/qtquick2/qquickloader/data/Rect120x60.qml
index fc9e447e69..fc9e447e69 100644
--- a/tests/auto/declarative/qquickloader/data/Rect120x60.qml
+++ b/tests/auto/qtquick2/qquickloader/data/Rect120x60.qml
diff --git a/tests/auto/declarative/qquickloader/data/SetSourceComponent.qml b/tests/auto/qtquick2/qquickloader/data/SetSourceComponent.qml
index 83cc358f7d..83cc358f7d 100644
--- a/tests/auto/declarative/qquickloader/data/SetSourceComponent.qml
+++ b/tests/auto/qtquick2/qquickloader/data/SetSourceComponent.qml
diff --git a/tests/auto/declarative/qquickloader/data/SizeGraphicsWidgetToLoader.qml b/tests/auto/qtquick2/qquickloader/data/SizeGraphicsWidgetToLoader.qml
index 2a63b4d34f..2a63b4d34f 100644
--- a/tests/auto/declarative/qquickloader/data/SizeGraphicsWidgetToLoader.qml
+++ b/tests/auto/qtquick2/qquickloader/data/SizeGraphicsWidgetToLoader.qml
diff --git a/tests/auto/declarative/qquickloader/data/SizeLoaderToGraphicsWidget.qml b/tests/auto/qtquick2/qquickloader/data/SizeLoaderToGraphicsWidget.qml
index a9875d8e21..a9875d8e21 100644
--- a/tests/auto/declarative/qquickloader/data/SizeLoaderToGraphicsWidget.qml
+++ b/tests/auto/qtquick2/qquickloader/data/SizeLoaderToGraphicsWidget.qml
diff --git a/tests/auto/declarative/qquickloader/data/SizeToItem.qml b/tests/auto/qtquick2/qquickloader/data/SizeToItem.qml
index 866365754f..866365754f 100644
--- a/tests/auto/declarative/qquickloader/data/SizeToItem.qml
+++ b/tests/auto/qtquick2/qquickloader/data/SizeToItem.qml
diff --git a/tests/auto/declarative/qquickloader/data/SizeToLoader.qml b/tests/auto/qtquick2/qquickloader/data/SizeToLoader.qml
index dad18c6939..dad18c6939 100644
--- a/tests/auto/declarative/qquickloader/data/SizeToLoader.qml
+++ b/tests/auto/qtquick2/qquickloader/data/SizeToLoader.qml
diff --git a/tests/auto/declarative/qquickloader/data/VmeError.qml b/tests/auto/qtquick2/qquickloader/data/VmeError.qml
index 0443aa9054..0443aa9054 100644
--- a/tests/auto/declarative/qquickloader/data/VmeError.qml
+++ b/tests/auto/qtquick2/qquickloader/data/VmeError.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.1.qml b/tests/auto/qtquick2/qquickloader/data/active.1.qml
index 2dbd1a0887..2dbd1a0887 100644
--- a/tests/auto/declarative/qquickloader/data/active.1.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.1.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.2.qml b/tests/auto/qtquick2/qquickloader/data/active.2.qml
index e561744c63..e561744c63 100644
--- a/tests/auto/declarative/qquickloader/data/active.2.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.2.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.3.qml b/tests/auto/qtquick2/qquickloader/data/active.3.qml
index 0fbba959bb..0fbba959bb 100644
--- a/tests/auto/declarative/qquickloader/data/active.3.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.3.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.4.qml b/tests/auto/qtquick2/qquickloader/data/active.4.qml
index 63fd46e2da..63fd46e2da 100644
--- a/tests/auto/declarative/qquickloader/data/active.4.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.4.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.5.qml b/tests/auto/qtquick2/qquickloader/data/active.5.qml
index 903f458a41..903f458a41 100644
--- a/tests/auto/declarative/qquickloader/data/active.5.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.5.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.6.qml b/tests/auto/qtquick2/qquickloader/data/active.6.qml
index f769a4e184..f769a4e184 100644
--- a/tests/auto/declarative/qquickloader/data/active.6.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.6.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.7.qml b/tests/auto/qtquick2/qquickloader/data/active.7.qml
index a29e932f5e..a29e932f5e 100644
--- a/tests/auto/declarative/qquickloader/data/active.7.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.7.qml
diff --git a/tests/auto/declarative/qquickloader/data/active.8.qml b/tests/auto/qtquick2/qquickloader/data/active.8.qml
index 3a66d3e99a..3a66d3e99a 100644
--- a/tests/auto/declarative/qquickloader/data/active.8.qml
+++ b/tests/auto/qtquick2/qquickloader/data/active.8.qml
diff --git a/tests/auto/declarative/qquickloader/data/asynchronous.qml b/tests/auto/qtquick2/qquickloader/data/asynchronous.qml
index 29570525ad..29570525ad 100644
--- a/tests/auto/declarative/qquickloader/data/asynchronous.qml
+++ b/tests/auto/qtquick2/qquickloader/data/asynchronous.qml
diff --git a/tests/auto/declarative/qquickloader/data/crash.qml b/tests/auto/qtquick2/qquickloader/data/crash.qml
index e6ddc33a10..e6ddc33a10 100644
--- a/tests/auto/declarative/qquickloader/data/crash.qml
+++ b/tests/auto/qtquick2/qquickloader/data/crash.qml
diff --git a/tests/auto/declarative/qquickloader/data/creationContext.qml b/tests/auto/qtquick2/qquickloader/data/creationContext.qml
index 17a596cc74..17a596cc74 100644
--- a/tests/auto/declarative/qquickloader/data/creationContext.qml
+++ b/tests/auto/qtquick2/qquickloader/data/creationContext.qml
diff --git a/tests/auto/declarative/qquickloader/data/differentorigin.qml b/tests/auto/qtquick2/qquickloader/data/differentorigin.qml
index 56a3034fe0..56a3034fe0 100644
--- a/tests/auto/declarative/qquickloader/data/differentorigin.qml
+++ b/tests/auto/qtquick2/qquickloader/data/differentorigin.qml
diff --git a/tests/auto/declarative/qquickloader/data/implicitSize.qml b/tests/auto/qtquick2/qquickloader/data/implicitSize.qml
index 5c8c8348ed..5c8c8348ed 100644
--- a/tests/auto/declarative/qquickloader/data/implicitSize.qml
+++ b/tests/auto/qtquick2/qquickloader/data/implicitSize.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.1.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.1.qml
index ae371797ce..ae371797ce 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.1.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.1.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.2.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.2.qml
index 76c7bc2fd6..76c7bc2fd6 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.2.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.2.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.3.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.3.qml
index 3b08e6ee42..3b08e6ee42 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.3.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.3.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.4.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.4.qml
index e8310044e8..e8310044e8 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.4.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.4.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.5.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.5.qml
index 03ee599aba..03ee599aba 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.5.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.5.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.6.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.6.qml
index 66452b512b..66452b512b 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.6.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.6.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.7.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.7.qml
index 02349f7ddf..02349f7ddf 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.7.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.7.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.8.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.8.qml
index 79e9264d4a..79e9264d4a 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.8.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.8.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.binding.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.binding.qml
index e0df50a74a..e0df50a74a 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.binding.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.binding.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.1.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.1.qml
index f324dbddac..f324dbddac 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.1.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.1.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.2.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.2.qml
index 89aba313c7..89aba313c7 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.2.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.2.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.3.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.3.qml
index c862007402..c862007402 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.3.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.3.qml
diff --git a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.4.qml b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.4.qml
index 9a80b2156d..9a80b2156d 100644
--- a/tests/auto/declarative/qquickloader/data/initialPropertyValues.error.4.qml
+++ b/tests/auto/qtquick2/qquickloader/data/initialPropertyValues.error.4.qml
diff --git a/tests/auto/declarative/qquickloader/data/nonItem.qml b/tests/auto/qtquick2/qquickloader/data/nonItem.qml
index 8cfa0d8efb..8cfa0d8efb 100644
--- a/tests/auto/declarative/qquickloader/data/nonItem.qml
+++ b/tests/auto/qtquick2/qquickloader/data/nonItem.qml
diff --git a/tests/auto/declarative/qquickloader/data/parented.qml b/tests/auto/qtquick2/qquickloader/data/parented.qml
index 1c19d4d1a5..1c19d4d1a5 100644
--- a/tests/auto/declarative/qquickloader/data/parented.qml
+++ b/tests/auto/qtquick2/qquickloader/data/parented.qml
diff --git a/tests/auto/declarative/qquickloader/data/qmldir b/tests/auto/qtquick2/qquickloader/data/qmldir
index bf42b507c0..bf42b507c0 100644
--- a/tests/auto/declarative/qquickloader/data/qmldir
+++ b/tests/auto/qtquick2/qquickloader/data/qmldir
diff --git a/tests/auto/declarative/qquickloader/data/sameorigin-load.qml b/tests/auto/qtquick2/qquickloader/data/sameorigin-load.qml
index 3332500be6..3332500be6 100644
--- a/tests/auto/declarative/qquickloader/data/sameorigin-load.qml
+++ b/tests/auto/qtquick2/qquickloader/data/sameorigin-load.qml
diff --git a/tests/auto/declarative/qquickloader/data/sameorigin.qml b/tests/auto/qtquick2/qquickloader/data/sameorigin.qml
index 84846b6aba..84846b6aba 100644
--- a/tests/auto/declarative/qquickloader/data/sameorigin.qml
+++ b/tests/auto/qtquick2/qquickloader/data/sameorigin.qml
diff --git a/tests/auto/declarative/qquickloader/data/vmeErrors.qml b/tests/auto/qtquick2/qquickloader/data/vmeErrors.qml
index 8e6c89dc8e..8e6c89dc8e 100644
--- a/tests/auto/declarative/qquickloader/data/vmeErrors.qml
+++ b/tests/auto/qtquick2/qquickloader/data/vmeErrors.qml
diff --git a/tests/auto/qtquick2/qquickloader/qquickloader.pro b/tests/auto/qtquick2/qquickloader/qquickloader.pro
new file mode 100644
index 0000000000..6e372692c2
--- /dev/null
+++ b/tests/auto/qtquick2/qquickloader/qquickloader.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qquickloader
+macx:CONFIG -= app_bundle
+
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qquickloader.cpp \
+ ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickloader/tst_qquickloader.cpp b/tests/auto/qtquick2/qquickloader/tst_qquickloader.cpp
new file mode 100644
index 0000000000..3df692a6a6
--- /dev/null
+++ b/tests/auto/qtquick2/qquickloader/tst_qquickloader.cpp
@@ -0,0 +1,969 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+
+#include <QSignalSpy>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+#include <private/qquickloader_p.h>
+#include "testhttpserver.h"
+#include "../../shared/util.h"
+
+#define SERVER_PORT 14450
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(TESTDATA(filename));
+}
+
+class PeriodicIncubationController : public QObject,
+ public QDeclarativeIncubationController
+{
+public:
+ PeriodicIncubationController() {
+ startTimer(16);
+ }
+
+protected:
+ virtual void timerEvent(QTimerEvent *) {
+ incubateFor(15);
+ }
+};
+
+class tst_QQuickLoader : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_QQuickLoader();
+
+private slots:
+ void sourceOrComponent();
+ void sourceOrComponent_data();
+ void clear();
+ void urlToComponent();
+ void componentToUrl();
+ void anchoredLoader();
+ void sizeLoaderToItem();
+ void sizeItemToLoader();
+ void noResize();
+ void networkRequestUrl();
+ void failNetworkRequest();
+// void networkComponent();
+ void active();
+ void initialPropertyValues_data();
+ void initialPropertyValues();
+ void initialPropertyValuesBinding();
+ void initialPropertyValuesError_data();
+ void initialPropertyValuesError();
+
+ void deleteComponentCrash();
+ void nonItem();
+ void vmeErrors();
+ void creationContext();
+ void QTBUG_16928();
+ void implicitSize();
+ void QTBUG_17114();
+ void asynchronous_data();
+ void asynchronous();
+ void asynchronous_clear();
+
+ void parented();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+
+tst_QQuickLoader::tst_QQuickLoader()
+{
+}
+
+void tst_QQuickLoader::sourceOrComponent()
+{
+ QFETCH(QString, sourceOrComponent);
+ QFETCH(QString, sourceDefinition);
+ QFETCH(QUrl, sourceUrl);
+ QFETCH(QString, errorString);
+
+ bool error = !errorString.isEmpty();
+ if (error)
+ QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData());
+
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray(
+ "import QtQuick 2.0\n"
+ "Loader {\n"
+ " property int onItemChangedCount: 0\n"
+ " property int onSourceChangedCount: 0\n"
+ " property int onSourceComponentChangedCount: 0\n"
+ " property int onStatusChangedCount: 0\n"
+ " property int onProgressChangedCount: 0\n"
+ " property int onLoadedCount: 0\n")
+ + sourceDefinition.toUtf8()
+ + QByteArray(
+ " onItemChanged: onItemChangedCount += 1\n"
+ " onSourceChanged: onSourceChangedCount += 1\n"
+ " onSourceComponentChanged: onSourceComponentChangedCount += 1\n"
+ " onStatusChanged: onStatusChangedCount += 1\n"
+ " onProgressChanged: onProgressChangedCount += 1\n"
+ " onLoaded: onLoadedCount += 1\n"
+ "}")
+ , TEST_FILE(""));
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QCOMPARE(loader->item() == 0, error);
+ QCOMPARE(loader->source(), sourceUrl);
+ QCOMPARE(loader->progress(), 1.0);
+
+ QCOMPARE(loader->status(), error ? QQuickLoader::Error : QQuickLoader::Ready);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), error ? 0: 1);
+
+ if (!error) {
+ bool sourceComponentIsChildOfLoader = false;
+ for (int ii = 0; ii < loader->children().size(); ++ii) {
+ QDeclarativeComponent *c = qobject_cast<QDeclarativeComponent*>(loader->children().at(ii));
+ if (c && c == loader->sourceComponent()) {
+ sourceComponentIsChildOfLoader = true;
+ }
+ }
+ QVERIFY(sourceComponentIsChildOfLoader);
+ }
+
+ if (sourceOrComponent == "component") {
+ QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 1);
+ QCOMPARE(loader->property("onSourceChangedCount").toInt(), 0);
+ } else {
+ QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 0);
+ QCOMPARE(loader->property("onSourceChangedCount").toInt(), 1);
+ }
+ QCOMPARE(loader->property("onStatusChangedCount").toInt(), 1);
+ QCOMPARE(loader->property("onProgressChangedCount").toInt(), 1);
+
+ QCOMPARE(loader->property("onItemChangedCount").toInt(), error ? 0 : 1);
+ QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::sourceOrComponent_data()
+{
+ QTest::addColumn<QString>("sourceOrComponent");
+ QTest::addColumn<QString>("sourceDefinition");
+ QTest::addColumn<QUrl>("sourceUrl");
+ QTest::addColumn<QString>("errorString");
+
+ QTest::newRow("source") << "source" << "source: 'Rect120x60.qml'\n" << QUrl::fromLocalFile(TESTDATA("Rect120x60.qml")) << "";
+ QTest::newRow("sourceComponent") << "component" << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << "";
+ QTest::newRow("invalid source") << "source" << "source: 'IDontExist.qml'\n" << QUrl::fromLocalFile(TESTDATA("IDontExist.qml"))
+ << QString(QUrl::fromLocalFile(TESTDATA("IDontExist.qml")).toString() + ": File not found");
+}
+
+void tst_QQuickLoader::clear()
+{
+ {
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray(
+ "import QtQuick 2.0\n"
+ " Loader { id: loader\n"
+ " source: 'Rect120x60.qml'\n"
+ " Timer { interval: 200; running: true; onTriggered: loader.source = '' }\n"
+ " }")
+ , TEST_FILE(""));
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ QTRY_VERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QQuickLoader::Null);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
+
+ delete loader;
+ }
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ loader->setSourceComponent(0);
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QQuickLoader::Null);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
+
+ delete item;
+ }
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ QMetaObject::invokeMethod(item, "clear");
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QQuickLoader::Null);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
+
+ delete item;
+ }
+}
+
+void tst_QQuickLoader::urlToComponent()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\n"
+ "Loader {\n"
+ " id: loader\n"
+ " Component { id: myComp; Rectangle { width: 10; height: 10 } }\n"
+ " source: \"Rect120x60.qml\"\n"
+ " Timer { interval: 100; running: true; onTriggered: loader.sourceComponent = myComp }\n"
+ "}" )
+ , TEST_FILE(""));
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QTest::qWait(200);
+ QTRY_VERIFY(loader != 0);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+ QCOMPARE(loader->width(), 10.0);
+ QCOMPARE(loader->height(), 10.0);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::componentToUrl()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ loader->setSource(TEST_FILE("/Rect120x60.qml"));
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+ QCOMPARE(loader->width(), 120.0);
+ QCOMPARE(loader->height(), 60.0);
+
+ delete item;
+}
+
+void tst_QQuickLoader::anchoredLoader()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("/AnchoredLoader.qml"));
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootItem != 0);
+ QQuickItem *loader = rootItem->findChild<QQuickItem*>("loader");
+ QQuickItem *sourceElement = rootItem->findChild<QQuickItem*>("sourceElement");
+
+ QVERIFY(loader != 0);
+ QVERIFY(sourceElement != 0);
+
+ QCOMPARE(rootItem->width(), 300.0);
+ QCOMPARE(rootItem->height(), 200.0);
+
+ QCOMPARE(loader->width(), 300.0);
+ QCOMPARE(loader->height(), 200.0);
+
+ QCOMPARE(sourceElement->width(), 300.0);
+ QCOMPARE(sourceElement->height(), 200.0);
+}
+
+void tst_QQuickLoader::sizeLoaderToItem()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("/SizeToItem.qml"));
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QCOMPARE(loader->width(), 120.0);
+ QCOMPARE(loader->height(), 60.0);
+
+ // Check resize
+ QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
+ QVERIFY(rect);
+ rect->setWidth(150);
+ rect->setHeight(45);
+ QCOMPARE(loader->width(), 150.0);
+ QCOMPARE(loader->height(), 45.0);
+
+ // Check explicit width
+ loader->setWidth(200.0);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(rect->width(), 200.0);
+ rect->setWidth(100.0); // when rect changes ...
+ QCOMPARE(rect->width(), 100.0); // ... it changes
+ QCOMPARE(loader->width(), 200.0); // ... but loader stays the same
+
+ // Check explicit height
+ loader->setHeight(200.0);
+ QCOMPARE(loader->height(), 200.0);
+ QCOMPARE(rect->height(), 200.0);
+ rect->setHeight(100.0); // when rect changes ...
+ QCOMPARE(rect->height(), 100.0); // ... it changes
+ QCOMPARE(loader->height(), 200.0); // ... but loader stays the same
+
+ // Switch mode
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(rect->width(), 180.0);
+ QCOMPARE(rect->height(), 30.0);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::sizeItemToLoader()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("/SizeToLoader.qml"));
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+ QCOMPARE(loader->width(), 200.0);
+ QCOMPARE(loader->height(), 80.0);
+
+ QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
+ QVERIFY(rect);
+ QCOMPARE(rect->width(), 200.0);
+ QCOMPARE(rect->height(), 80.0);
+
+ // Check resize
+ loader->setWidth(180);
+ loader->setHeight(30);
+ QCOMPARE(rect->width(), 180.0);
+ QCOMPARE(rect->height(), 30.0);
+
+ // Switch mode
+ loader->resetWidth(); // reset explicit size
+ loader->resetHeight();
+ rect->setWidth(160);
+ rect->setHeight(45);
+ QCOMPARE(loader->width(), 160.0);
+ QCOMPARE(loader->height(), 45.0);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::noResize()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("/NoResize.qml"));
+ QQuickItem* item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item != 0);
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 80.0);
+
+ delete item;
+}
+
+void tst_QQuickLoader::networkRequestUrl()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nLoader { property int signalCount : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: signalCount += 1 }"), QUrl::fromLocalFile(TESTDATA("../dummy.qml")));
+ if (component.isError())
+ qDebug() << component.errors();
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+
+ QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
+
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->property("signalCount").toInt(), 1);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+ delete loader;
+}
+
+/* XXX Component waits until all dependencies are loaded. Is this actually possible?
+void tst_QQuickLoader::networkComponent()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory("slowdata", TestHTTPServer::Delay);
+
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray(
+ "import QtQuick 2.0\n"
+ "import \"http://127.0.0.1:14450/\" as NW\n"
+ "Item {\n"
+ " Component { id: comp; NW.SlowRect {} }\n"
+ " Loader { sourceComponent: comp } }")
+ , TEST_FILE(""));
+
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::children().at(1));
+ QVERIFY(loader);
+ QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
+
+ QVERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->children().count(), 1);
+
+ delete loader;
+}
+*/
+
+void tst_QQuickLoader::failNetworkRequest()
+{
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ QTest::ignoreMessage(QtWarningMsg, "http://127.0.0.1:14450/IDontExist.qml: File not found");
+
+ QDeclarativeComponent component(&engine);
+ component.setData(QByteArray("import QtQuick 2.0\nLoader { property int did_load: 123; source: \"http://127.0.0.1:14450/IDontExist.qml\"; onLoaded: did_load=456 }"), QUrl::fromLocalFile("http://127.0.0.1:14450/dummy.qml"));
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader != 0);
+
+ QTRY_VERIFY(loader->status() == QQuickLoader::Error);
+
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->property("did_load").toInt(), 123);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::active()
+{
+ // check that the item isn't instantiated until active is set to true
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == false); // set manually to false
+ QVERIFY(loader->item() == 0);
+ QMetaObject::invokeMethod(object, "doSetSourceComponent");
+ QVERIFY(loader->item() == 0);
+ QMetaObject::invokeMethod(object, "doSetSource");
+ QVERIFY(loader->item() == 0);
+ QMetaObject::invokeMethod(object, "doSetActive");
+ QVERIFY(loader->item() != 0);
+
+ delete object;
+ }
+
+ // check that the status is Null if active is set to false
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == true); // active is true by default
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+ int currStatusChangedCount = loader->property("statusChangedCount").toInt();
+ QMetaObject::invokeMethod(object, "doSetInactive");
+ QCOMPARE(loader->status(), QQuickLoader::Null);
+ QCOMPARE(loader->property("statusChangedCount").toInt(), (currStatusChangedCount+1));
+
+ delete object;
+ }
+
+ // check that the source is not cleared if active is set to false
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.3.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == true); // active is true by default
+ QVERIFY(!loader->source().isEmpty());
+ int currSourceChangedCount = loader->property("sourceChangedCount").toInt();
+ QMetaObject::invokeMethod(object, "doSetInactive");
+ QVERIFY(!loader->source().isEmpty());
+ QCOMPARE(loader->property("sourceChangedCount").toInt(), currSourceChangedCount);
+
+ delete object;
+ }
+
+ // check that the sourceComponent is not cleared if active is set to false
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.4.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == true); // active is true by default
+ QVERIFY(loader->sourceComponent() != 0);
+ int currSourceComponentChangedCount = loader->property("sourceComponentChangedCount").toInt();
+ QMetaObject::invokeMethod(object, "doSetInactive");
+ QVERIFY(loader->sourceComponent() != 0);
+ QCOMPARE(loader->property("sourceComponentChangedCount").toInt(), currSourceComponentChangedCount);
+
+ delete object;
+ }
+
+ // check that the item is released if active is set to false
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.5.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == true); // active is true by default
+ QVERIFY(loader->item() != 0);
+ int currItemChangedCount = loader->property("itemChangedCount").toInt();
+ QMetaObject::invokeMethod(object, "doSetInactive");
+ QVERIFY(loader->item() == 0);
+ QCOMPARE(loader->property("itemChangedCount").toInt(), (currItemChangedCount+1));
+
+ delete object;
+ }
+
+ // check that the activeChanged signal is emitted correctly
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.6.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+
+ QVERIFY(loader->active() == true); // active is true by default
+ loader->setActive(true); // no effect
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 0);
+ loader->setActive(false); // change signal should be emitted
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
+ loader->setActive(false); // no effect
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
+ loader->setActive(true); // change signal should be emitted
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 2);
+ loader->setActive(false); // change signal should be emitted
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 3);
+ QMetaObject::invokeMethod(object, "doSetActive");
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
+ QMetaObject::invokeMethod(object, "doSetActive");
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
+ QMetaObject::invokeMethod(object, "doSetInactive");
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 5);
+ loader->setActive(true); // change signal should be emitted
+ QCOMPARE(loader->property("activeChangedCount").toInt(), 6);
+
+ delete object;
+ }
+
+ // check that the component isn't loaded until active is set to true
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.7.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("success").toBool(), true);
+ delete object;
+ }
+
+ // check that the component is loaded if active is not set (true by default)
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("active.8.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("success").toBool(), true);
+ delete object;
+ }
+}
+
+void tst_QQuickLoader::initialPropertyValues_data()
+{
+ QTest::addColumn<QUrl>("qmlFile");
+ QTest::addColumn<QStringList>("expectedWarnings");
+ QTest::addColumn<QStringList>("propertyNames");
+ QTest::addColumn<QVariantList>("propertyValues");
+
+ QTest::newRow("source url with value set in onLoaded, initially active = true") << TEST_FILE("initialPropertyValues.1.qml")
+ << QStringList()
+ << (QStringList() << "initialValue" << "behaviorCount")
+ << (QVariantList() << 1 << 1);
+
+ QTest::newRow("set source with initial property values specified, active = true") << TEST_FILE("initialPropertyValues.2.qml")
+ << QStringList()
+ << (QStringList() << "initialValue" << "behaviorCount")
+ << (QVariantList() << 2 << 0);
+
+ QTest::newRow("set source with initial property values specified, active = false") << TEST_FILE("initialPropertyValues.3.qml")
+ << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("initialPropertyValues.3.qml").toLocalFile() + QLatin1String(":16: TypeError: Cannot read property 'canary' of null")))
+ << (QStringList())
+ << (QVariantList());
+
+ QTest::newRow("set source with initial property values specified, active = false, with active set true later") << TEST_FILE("initialPropertyValues.4.qml")
+ << QStringList()
+ << (QStringList() << "initialValue" << "behaviorCount")
+ << (QVariantList() << 4 << 0);
+
+ QTest::newRow("set source without initial property values specified, active = true") << TEST_FILE("initialPropertyValues.5.qml")
+ << QStringList()
+ << (QStringList() << "initialValue" << "behaviorCount")
+ << (QVariantList() << 0 << 0);
+
+ QTest::newRow("set source with initial property values specified with binding, active = true") << TEST_FILE("initialPropertyValues.6.qml")
+ << QStringList()
+ << (QStringList() << "initialValue" << "behaviorCount")
+ << (QVariantList() << 6 << 0);
+
+ QTest::newRow("ensure initial property value semantics mimic createObject") << TEST_FILE("initialPropertyValues.7.qml")
+ << QStringList()
+ << (QStringList() << "loaderValue" << "createObjectValue")
+ << (QVariantList() << 1 << 1);
+
+ QTest::newRow("ensure initial property values aren't disposed prior to component completion") << TEST_FILE("initialPropertyValues.8.qml")
+ << QStringList()
+ << (QStringList() << "initialValue")
+ << (QVariantList() << 6);
+}
+
+void tst_QQuickLoader::initialPropertyValues()
+{
+ QFETCH(QUrl, qmlFile);
+ QFETCH(QStringList, expectedWarnings);
+ QFETCH(QStringList, propertyNames);
+ QFETCH(QVariantList, propertyValues);
+
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ server.serveDirectory(TESTDATA(""));
+
+ foreach (const QString &warning, expectedWarnings)
+ QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
+
+ QDeclarativeComponent component(&engine, qmlFile);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ qApp->processEvents();
+ QTest::qWait(50);
+
+ for (int i = 0; i < propertyNames.size(); ++i)
+ QCOMPARE(object->property(propertyNames.at(i).toAscii().constData()), propertyValues.at(i));
+
+ delete object;
+}
+
+void tst_QQuickLoader::initialPropertyValuesBinding()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("initialPropertyValues.binding.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->setProperty("bindable", QVariant(8)));
+ QCOMPARE(object->property("canaryValue").toInt(), 8);
+
+ delete object;
+}
+
+void tst_QQuickLoader::initialPropertyValuesError_data()
+{
+ QTest::addColumn<QUrl>("qmlFile");
+ QTest::addColumn<QStringList>("expectedWarnings");
+
+ QTest::newRow("invalid initial property values object") << TEST_FILE("initialPropertyValues.error.1.qml")
+ << (QStringList() << QString(TEST_FILE("initialPropertyValues.error.1.qml").toString() + ":6:5: QML Loader: setSource: value is not an object"));
+
+ QTest::newRow("nonexistent source url") << TEST_FILE("initialPropertyValues.error.2.qml")
+ << (QStringList() << QString(TEST_FILE("NonexistentSourceComponent.qml").toString() + ": File not found"));
+
+ QTest::newRow("invalid source url") << TEST_FILE("initialPropertyValues.error.3.qml")
+ << (QStringList() << QString(TEST_FILE("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+
+ QTest::newRow("invalid initial property values object with invalid property access") << TEST_FILE("initialPropertyValues.error.4.qml")
+ << (QStringList() << QString(TEST_FILE("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
+ << QString(TEST_FILE("initialPropertyValues.error.4.qml").toString() + ":5: TypeError: Cannot read property 'canary' of null"));
+}
+
+void tst_QQuickLoader::initialPropertyValuesError()
+{
+ QFETCH(QUrl, qmlFile);
+ QFETCH(QStringList, expectedWarnings);
+
+ foreach (const QString &warning, expectedWarnings)
+ QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
+
+ QDeclarativeComponent component(&engine, qmlFile);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
+ QVERIFY(loader != 0);
+ QVERIFY(loader->item() == 0);
+ delete object;
+}
+
+// QTBUG-9241
+void tst_QQuickLoader::deleteComponentCrash()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("crash.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ item->metaObject()->invokeMethod(item, "setLoaderSource");
+
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QCOMPARE(loader->item()->objectName(), QLatin1String("blue"));
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+ qApp->processEvents(QEventLoop::DeferredDeletion);
+ QTRY_COMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+ QVERIFY(loader->source() == QUrl::fromLocalFile(TESTDATA("BlueRect.qml")));
+
+ delete item;
+}
+
+void tst_QQuickLoader::nonItem()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("nonItem.qml"));
+ QString err = QUrl::fromLocalFile(TESTDATA("nonItem.qml")).toString() + ":3:1: QML Loader: Loader does not support loading non-visual elements.";
+
+ QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader);
+ QVERIFY(loader->item() == 0);
+
+ delete loader;
+}
+
+void tst_QQuickLoader::vmeErrors()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("vmeErrors.qml"));
+ QString err = QUrl::fromLocalFile(TESTDATA("VmeError.qml")).toString() + ":6: Cannot assign object type QObject with no default method";
+ QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
+ QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QVERIFY(loader);
+ QVERIFY(loader->item() == 0);
+
+ delete loader;
+}
+
+// QTBUG-13481
+void tst_QQuickLoader::creationContext()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("creationContext.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->property("test").toBool(), true);
+
+ delete o;
+}
+
+void tst_QQuickLoader::QTBUG_16928()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_16928.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QCOMPARE(item->width(), 250.);
+ QCOMPARE(item->height(), 250.);
+
+ delete item;
+}
+
+void tst_QQuickLoader::implicitSize()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("implicitSize.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QCOMPARE(item->width(), 150.);
+ QCOMPARE(item->height(), 150.);
+
+ QCOMPARE(item->property("implHeight").toReal(), 100.);
+ QCOMPARE(item->property("implWidth").toReal(), 100.);
+
+ delete item;
+}
+
+void tst_QQuickLoader::QTBUG_17114()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_17114.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+
+ QCOMPARE(item->property("loaderWidth").toReal(), 32.);
+ QCOMPARE(item->property("loaderHeight").toReal(), 32.);
+
+ delete item;
+}
+
+void tst_QQuickLoader::asynchronous_data()
+{
+ QTest::addColumn<QUrl>("qmlFile");
+ QTest::addColumn<QStringList>("expectedWarnings");
+
+ QTest::newRow("Valid component") << TEST_FILE("BigComponent.qml")
+ << QStringList();
+
+ QTest::newRow("Non-existant component") << TEST_FILE("IDoNotExist.qml")
+ << (QStringList() << QString(TEST_FILE("IDoNotExist.qml").toString() + ": File not found"));
+
+ QTest::newRow("Invalid component") << TEST_FILE("InvalidSourceComponent.qml")
+ << (QStringList() << QString(TEST_FILE("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+}
+
+void tst_QQuickLoader::asynchronous()
+{
+ QFETCH(QUrl, qmlFile);
+ QFETCH(QStringList, expectedWarnings);
+
+ if (!engine.incubationController())
+ engine.setIncubationController(new PeriodicIncubationController);
+ QDeclarativeComponent component(&engine, TEST_FILE("asynchronous.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(root);
+
+ QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
+ QVERIFY(loader);
+
+ foreach (const QString &warning, expectedWarnings)
+ QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
+
+ QVERIFY(!loader->item());
+ root->setProperty("comp", qmlFile.toString());
+ QMetaObject::invokeMethod(root, "loadComponent");
+ QVERIFY(!loader->item());
+
+ if (expectedWarnings.isEmpty()) {
+ QCOMPARE(loader->status(), QQuickLoader::Loading);
+ QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
+
+ QTRY_VERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+ } else {
+ QCOMPARE(loader->progress(), 1.0);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Error);
+ }
+
+ delete root;
+}
+
+void tst_QQuickLoader::asynchronous_clear()
+{
+ if (!engine.incubationController())
+ engine.setIncubationController(new PeriodicIncubationController);
+ QDeclarativeComponent component(&engine, TEST_FILE("asynchronous.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(root);
+
+ QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
+ QVERIFY(loader);
+
+ QVERIFY(!loader->item());
+ root->setProperty("comp", "BigComponent.qml");
+ QMetaObject::invokeMethod(root, "loadComponent");
+ QVERIFY(!loader->item());
+
+ QCOMPARE(loader->status(), QQuickLoader::Loading);
+ QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
+
+ // clear before component created
+ root->setProperty("comp", "");
+ QMetaObject::invokeMethod(root, "loadComponent");
+ QVERIFY(!loader->item());
+ QCOMPARE(engine.incubationController()->incubatingObjectCount(), 0);
+
+ QCOMPARE(loader->progress(), 0.0);
+ QCOMPARE(loader->status(), QQuickLoader::Null);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
+
+ // check loading component
+ root->setProperty("comp", "Rect120x60.qml");
+ QMetaObject::invokeMethod(root, "loadComponent");
+ QVERIFY(!loader->item());
+
+ QCOMPARE(loader->status(), QQuickLoader::Loading);
+ QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
+
+ QTRY_VERIFY(loader->item());
+ QCOMPARE(loader->progress(), 1.0);
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+ QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+}
+
+void tst_QQuickLoader::parented()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("parented.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(root);
+
+ QQuickItem *item = root->findChild<QQuickItem*>("comp");
+ QVERIFY(item);
+
+ QVERIFY(item->parentItem() == root);
+
+ QCOMPARE(item->width(), 300.);
+ QCOMPARE(item->height(), 300.);
+
+ delete root;
+}
+
+
+QTEST_MAIN(tst_QQuickLoader)
+
+#include "tst_qquickloader.moc"
diff --git a/tests/auto/declarative/qquickmousearea/data/clickThrough.qml b/tests/auto/qtquick2/qquickmousearea/data/clickThrough.qml
index 3c03161faa..3c03161faa 100644
--- a/tests/auto/declarative/qquickmousearea/data/clickThrough.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/clickThrough.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/clickThrough2.qml b/tests/auto/qtquick2/qquickmousearea/data/clickThrough2.qml
index 2624108225..2624108225 100644
--- a/tests/auto/declarative/qquickmousearea/data/clickThrough2.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/clickThrough2.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/clickandhold.qml b/tests/auto/qtquick2/qquickmousearea/data/clickandhold.qml
index 5e4e48f6db..5e4e48f6db 100644
--- a/tests/auto/declarative/qquickmousearea/data/clickandhold.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/clickandhold.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/clicktwice.qml b/tests/auto/qtquick2/qquickmousearea/data/clicktwice.qml
index 002d1b9047..002d1b9047 100644
--- a/tests/auto/declarative/qquickmousearea/data/clicktwice.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/clicktwice.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/doubleclick.qml b/tests/auto/qtquick2/qquickmousearea/data/doubleclick.qml
index 1030d0c33e..1030d0c33e 100644
--- a/tests/auto/declarative/qquickmousearea/data/doubleclick.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/doubleclick.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/dragging.qml b/tests/auto/qtquick2/qquickmousearea/data/dragging.qml
index d9b6ac4083..d9b6ac4083 100644
--- a/tests/auto/declarative/qquickmousearea/data/dragging.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/dragging.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/dragproperties.qml b/tests/auto/qtquick2/qquickmousearea/data/dragproperties.qml
index 421dfe26b7..421dfe26b7 100644
--- a/tests/auto/declarative/qquickmousearea/data/dragproperties.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/dragproperties.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/dragreset.qml b/tests/auto/qtquick2/qquickmousearea/data/dragreset.qml
index d7949f9139..d7949f9139 100644
--- a/tests/auto/declarative/qquickmousearea/data/dragreset.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/dragreset.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/hoverPosition.qml b/tests/auto/qtquick2/qquickmousearea/data/hoverPosition.qml
index 834f91ff29..834f91ff29 100644
--- a/tests/auto/declarative/qquickmousearea/data/hoverPosition.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/hoverPosition.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/hoverPropagation.qml b/tests/auto/qtquick2/qquickmousearea/data/hoverPropagation.qml
index c47c794132..c47c794132 100644
--- a/tests/auto/declarative/qquickmousearea/data/hoverPropagation.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/hoverPropagation.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/noclickandhold.qml b/tests/auto/qtquick2/qquickmousearea/data/noclickandhold.qml
index 6647de001d..6647de001d 100644
--- a/tests/auto/declarative/qquickmousearea/data/noclickandhold.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/noclickandhold.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/pressedCanceled.qml b/tests/auto/qtquick2/qquickmousearea/data/pressedCanceled.qml
index 231436d0f2..231436d0f2 100644
--- a/tests/auto/declarative/qquickmousearea/data/pressedCanceled.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/pressedCanceled.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/pressedOrdering.qml b/tests/auto/qtquick2/qquickmousearea/data/pressedOrdering.qml
index 7aa3098100..7aa3098100 100644
--- a/tests/auto/declarative/qquickmousearea/data/pressedOrdering.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/pressedOrdering.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/preventstealing.qml b/tests/auto/qtquick2/qquickmousearea/data/preventstealing.qml
index fb0d6955c1..fb0d6955c1 100644
--- a/tests/auto/declarative/qquickmousearea/data/preventstealing.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/preventstealing.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/rejectEvent.qml b/tests/auto/qtquick2/qquickmousearea/data/rejectEvent.qml
index 816fc76fac..816fc76fac 100644
--- a/tests/auto/declarative/qquickmousearea/data/rejectEvent.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/rejectEvent.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/updateMousePosOnClick.qml b/tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnClick.qml
index 7377a2e86c..7377a2e86c 100644
--- a/tests/auto/declarative/qquickmousearea/data/updateMousePosOnClick.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnClick.qml
diff --git a/tests/auto/declarative/qquickmousearea/data/updateMousePosOnResize.qml b/tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnResize.qml
index 55af864060..55af864060 100644
--- a/tests/auto/declarative/qquickmousearea/data/updateMousePosOnResize.qml
+++ b/tests/auto/qtquick2/qquickmousearea/data/updateMousePosOnResize.qml
diff --git a/tests/auto/qtquick2/qquickmousearea/qquickmousearea.pro b/tests/auto/qtquick2/qquickmousearea/qquickmousearea.pro
new file mode 100644
index 0000000000..fcf166b0ed
--- /dev/null
+++ b/tests/auto/qtquick2/qquickmousearea/qquickmousearea.pro
@@ -0,0 +1,14 @@
+CONFIG += testcase
+TARGET = tst_qquickmousearea
+macx:CONFIG -= app_bundle
+
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += tst_qquickmousearea.cpp ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/qtquick2/qquickmousearea/tst_qquickmousearea.cpp
new file mode 100644
index 0000000000..7c9af4ba64
--- /dev/null
+++ b/tests/auto/qtquick2/qquickmousearea/tst_qquickmousearea.cpp
@@ -0,0 +1,824 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtQuick/private/qquickmousearea_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <private/qquickflickable_p.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtOpenGL/QGLShaderProgram>
+#include "../../shared/util.h"
+
+//#define OLDWAY
+
+class tst_QQuickMouseArea: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void dragProperties();
+ void resetDrag();
+ void dragging();
+ void updateMouseAreaPosOnClick();
+ void updateMouseAreaPosOnResize();
+ void noOnClickedWithPressAndHold();
+ void onMousePressRejected();
+ void pressedCanceledOnWindowDeactivate();
+ void doubleClick();
+ void clickTwice();
+ void pressedOrdering();
+ void preventStealing();
+ void clickThrough();
+ void testQtQuick11Attributes();
+ void testQtQuick11Attributes_data();
+ void hoverPosition();
+ void hoverPropagation();
+
+private:
+ QQuickView *createView();
+};
+
+void tst_QQuickMouseArea::initTestCase()
+{
+
+}
+
+void tst_QQuickMouseArea::cleanupTestCase()
+{
+
+}
+
+void tst_QQuickMouseArea::dragProperties()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragproperties.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QQuickDrag *drag = mouseRegion->drag();
+ QVERIFY(mouseRegion != 0);
+ QVERIFY(drag != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == drag->target());
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootItem != 0);
+ QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
+ drag->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+ drag->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+
+ // axis
+ QCOMPARE(drag->axis(), QQuickDrag::XandYAxis);
+ QSignalSpy axisSpy(drag, SIGNAL(axisChanged()));
+ drag->setAxis(QQuickDrag::XAxis);
+ QCOMPARE(drag->axis(), QQuickDrag::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+ drag->setAxis(QQuickDrag::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+
+ // minimum and maximum properties
+ QSignalSpy xminSpy(drag, SIGNAL(minimumXChanged()));
+ QSignalSpy xmaxSpy(drag, SIGNAL(maximumXChanged()));
+ QSignalSpy yminSpy(drag, SIGNAL(minimumYChanged()));
+ QSignalSpy ymaxSpy(drag, SIGNAL(maximumYChanged()));
+
+ QCOMPARE(drag->xmin(), 0.0);
+ QCOMPARE(drag->xmax(), rootItem->width()-blackRect->width());
+ QCOMPARE(drag->ymin(), 0.0);
+ QCOMPARE(drag->ymax(), rootItem->height()-blackRect->height());
+
+ drag->setXmin(10);
+ drag->setXmax(10);
+ drag->setYmin(10);
+ drag->setYmax(10);
+
+ QCOMPARE(drag->xmin(), 10.0);
+ QCOMPARE(drag->xmax(), 10.0);
+ QCOMPARE(drag->ymin(), 10.0);
+ QCOMPARE(drag->ymax(), 10.0);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+
+ drag->setXmin(10);
+ drag->setXmax(10);
+ drag->setYmin(10);
+ drag->setYmax(10);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+
+ // filterChildren
+ QSignalSpy filterChildrenSpy(drag, SIGNAL(filterChildrenChanged()));
+
+ drag->setFilterChildren(true);
+
+ QVERIFY(drag->filterChildren());
+ QCOMPARE(filterChildrenSpy.count(), 1);
+
+ drag->setFilterChildren(true);
+ QCOMPARE(filterChildrenSpy.count(), 1);
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::resetDrag()
+{
+ QQuickView *canvas = createView();
+
+ canvas->rootContext()->setContextProperty("haveTarget", QVariant(true));
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragreset.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QQuickDrag *drag = mouseRegion->drag();
+ QVERIFY(mouseRegion != 0);
+ QVERIFY(drag != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == drag->target());
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootItem != 0);
+ QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
+ QVERIFY(drag->target() != 0);
+ canvas->rootContext()->setContextProperty("haveTarget", QVariant(false));
+ QCOMPARE(targetSpy.count(),1);
+ QVERIFY(drag->target() == 0);
+
+ delete canvas;
+}
+
+
+void tst_QQuickMouseArea::dragging()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragging.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWait(20);
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QQuickDrag *drag = mouseRegion->drag();
+ QVERIFY(mouseRegion != 0);
+ QVERIFY(drag != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == drag->target());
+
+ QVERIFY(!drag->active());
+
+#ifdef OLDWAY
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+#else
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+#endif
+
+ QVERIFY(!drag->active());
+ QCOMPARE(blackRect->x(), 50.0);
+ QCOMPARE(blackRect->y(), 50.0);
+
+ // First move event triggers drag, second is acted upon.
+ // This is due to possibility of higher stacked area taking precedence.
+
+ QTest::mouseMove(canvas, QPoint(111,111));
+ QTest::qWait(50);
+ QTest::mouseMove(canvas, QPoint(122,122));
+ QTest::qWait(50);
+
+ QVERIFY(drag->active());
+ QCOMPARE(blackRect->x(), 72.0);
+ QCOMPARE(blackRect->y(), 72.0);
+
+#ifdef OLDWAY
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+#else
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
+ QTest::qWait(50);
+#endif
+
+ QVERIFY(!drag->active());
+ QCOMPARE(blackRect->x(), 72.0);
+ QCOMPARE(blackRect->y(), 72.0);
+
+ delete canvas;
+}
+
+QQuickView *tst_QQuickMouseArea::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setBaseSize(QSize(240,320));
+
+ return canvas;
+}
+
+void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("updateMousePosOnClick.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QVERIFY(mouseRegion != 0);
+
+ QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("ball");
+ QVERIFY(rect != 0);
+
+ QCOMPARE(mouseRegion->mouseX(), rect->x());
+ QCOMPARE(mouseRegion->mouseY(), rect->y());
+
+ QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &event);
+
+ QCOMPARE(mouseRegion->mouseX(), 100.0);
+ QCOMPARE(mouseRegion->mouseY(), 100.0);
+
+ QCOMPARE(mouseRegion->mouseX(), rect->x());
+ QCOMPARE(mouseRegion->mouseY(), rect->y());
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("updateMousePosOnResize.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QVERIFY(mouseRegion != 0);
+
+ QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("brother");
+ QVERIFY(rect != 0);
+
+ QCOMPARE(mouseRegion->mouseX(), 0.0);
+ QCOMPARE(mouseRegion->mouseY(), 0.0);
+
+ QMouseEvent event(QEvent::MouseButtonPress, rect->pos().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &event);
+
+ QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
+ QVERIFY(mouseRegion->property("mouseMatchesPos").toBool());
+
+ QCOMPARE(mouseRegion->property("x1").toReal(), 0.0);
+ QCOMPARE(mouseRegion->property("y1").toReal(), 0.0);
+
+ QCOMPARE(mouseRegion->property("x2").toReal(), rect->x());
+ QCOMPARE(mouseRegion->property("y2").toReal(), rect->y());
+
+ QCOMPARE(mouseRegion->mouseX(), rect->x());
+ QCOMPARE(mouseRegion->mouseY(), rect->y());
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
+{
+ {
+ // We handle onPressAndHold, therefore no onClicked
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickandhold.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QVERIFY(!canvas->rootObject()->property("clicked").toBool());
+ QVERIFY(!canvas->rootObject()->property("held").toBool());
+
+ QTest::qWait(1000);
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QVERIFY(!canvas->rootObject()->property("clicked").toBool());
+ QVERIFY(canvas->rootObject()->property("held").toBool());
+
+ delete canvas;
+ }
+
+ {
+ // We do not handle onPressAndHold, therefore we get onClicked
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("noclickandhold.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QVERIFY(!canvas->rootObject()->property("clicked").toBool());
+
+ QTest::qWait(1000);
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QVERIFY(canvas->rootObject()->property("clicked").toBool());
+
+ delete canvas;
+ }
+}
+
+void tst_QQuickMouseArea::onMousePressRejected()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("rejectEvent.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+ QVERIFY(canvas->rootObject()->property("enabled").toBool());
+
+ QVERIFY(!canvas->rootObject()->property("mr1_pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr2_pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr2_canceled").toBool());
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QVERIFY(canvas->rootObject()->property("mr1_pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
+ QVERIFY(canvas->rootObject()->property("mr2_pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
+ QVERIFY(canvas->rootObject()->property("mr2_canceled").toBool());
+
+ QTest::qWait(200);
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QVERIFY(canvas->rootObject()->property("mr1_released").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
+
+ delete canvas;
+}
+void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pressedCanceled.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+ QVERIFY(!canvas->rootObject()->property("pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("released").toBool());
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QVERIFY(canvas->rootObject()->property("pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("released").toBool());
+
+ QTest::qWait(200);
+
+ QEvent windowDeactivateEvent(QEvent::WindowDeactivate);
+ QApplication::sendEvent(canvas, &windowDeactivateEvent);
+ QVERIFY(!canvas->rootObject()->property("pressed").toBool());
+ QVERIFY(canvas->rootObject()->property("canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("released").toBool());
+
+ QTest::qWait(200);
+
+ //press again
+ QApplication::sendEvent(canvas, &pressEvent);
+ QVERIFY(canvas->rootObject()->property("pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("canceled").toBool());
+ QVERIFY(!canvas->rootObject()->property("released").toBool());
+
+ QTest::qWait(200);
+
+ //release
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+ QVERIFY(!canvas->rootObject()->property("pressed").toBool());
+ QVERIFY(!canvas->rootObject()->property("canceled").toBool());
+ QVERIFY(canvas->rootObject()->property("released").toBool());
+
+ delete canvas;
+}
+void tst_QQuickMouseArea::doubleClick()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("doubleclick.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
+
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
+
+ delete canvas;
+}
+
+// QTBUG-14832
+void tst_QQuickMouseArea::clickTwice()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("clicktwice.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
+
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QApplication::sendEvent(canvas, &pressEvent);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2);
+ QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
+ QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2);
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::pressedOrdering()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pressedOrdering.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base"));
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
+
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &releaseEvent);
+
+ QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled"));
+
+ QApplication::sendEvent(canvas, &pressEvent);
+
+ QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::preventStealing()
+{
+ QQuickView *canvas = createView();
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("preventstealing.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mousearea");
+ QVERIFY(mouseArea != 0);
+
+ QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
+
+ // Without preventStealing, mouse movement over MouseArea would
+ // cause the Flickable to steal mouse and trigger content movement.
+
+ QTest::mouseMove(canvas,QPoint(69,69));
+ QTest::mouseMove(canvas,QPoint(58,58));
+ QTest::mouseMove(canvas,QPoint(47,47));
+
+ // We should have received all three move events
+ QCOMPARE(mousePositionSpy.count(), 3);
+ QVERIFY(mouseArea->pressed());
+
+ // Flickable content should not have moved.
+ QCOMPARE(flickable->contentX(), 0.);
+ QCOMPARE(flickable->contentY(), 0.);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(47, 47));
+
+ // Now allow stealing and confirm Flickable does its thing.
+ canvas->rootObject()->setProperty("stealing", false);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
+
+ // Without preventStealing, mouse movement over MouseArea would
+ // cause the Flickable to steal mouse and trigger content movement.
+
+ QTest::mouseMove(canvas,QPoint(69,69));
+ QTest::mouseMove(canvas,QPoint(58,58));
+ QTest::mouseMove(canvas,QPoint(47,47));
+
+ // We should only have received the first move event
+ QCOMPARE(mousePositionSpy.count(), 4);
+ // Our press should be taken away
+ QVERIFY(!mouseArea->pressed());
+
+ // Flickable content should have moved.
+
+ QCOMPARE(flickable->contentX(), 11.);
+ QCOMPARE(flickable->contentY(), 11.);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 50));
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::clickThrough()
+{
+ //With no handlers defined click, doubleClick and PressAndHold should propagate to those with handlers
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickThrough.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+ QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
+
+ QTest::qWait(800); // to avoid generating a double click.
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(1000);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+ QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
+ QTRY_COMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
+
+ QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
+ QTRY_COMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
+
+ delete canvas;
+
+ //With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
+ canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("clickThrough2.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
+
+ QTest::qWait(800); // to avoid generating a double click.
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(1000);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
+
+ QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
+
+ canvas->rootObject()->setProperty("letThrough", QVariant(true));
+
+ QTest::qWait(800); // to avoid generating a double click.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
+
+ QTest::qWait(800); // to avoid generating a double click.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(1000);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
+
+ QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
+ QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
+
+ canvas->rootObject()->setProperty("noPropagation", QVariant(true));
+
+ QTest::qWait(800); // to avoid generating a double click.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+ QTest::qWait(800); // to avoid generating a double click.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(1000);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
+ QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
+ QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
+ QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::testQtQuick11Attributes()
+{
+ QFETCH(QString, code);
+ QFETCH(QString, warning);
+ QFETCH(QString, error);
+
+ QDeclarativeEngine engine;
+ QObject *obj;
+
+ QDeclarativeComponent valid(&engine);
+ valid.setData("import QtQuick 1.1; MouseArea { " + code.toUtf8() + " }", QUrl(""));
+ obj = valid.create();
+ QVERIFY(obj);
+ QVERIFY(valid.errorString().isEmpty());
+ delete obj;
+
+ QDeclarativeComponent invalid(&engine);
+ invalid.setData("import QtQuick 1.0; MouseArea { " + code.toUtf8() + " }", QUrl(""));
+ QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
+ obj = invalid.create();
+ QCOMPARE(invalid.errorString(), error);
+ delete obj;
+}
+
+void tst_QQuickMouseArea::testQtQuick11Attributes_data()
+{
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("warning");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("preventStealing") << "preventStealing: true"
+ << "QDeclarativeComponent: Component is not ready"
+ << ":1 \"MouseArea.preventStealing\" is not available in QtQuick 1.0.\n";
+}
+
+void tst_QQuickMouseArea::hoverPosition()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("hoverPosition.qml")));
+
+ QQuickItem *root = canvas->rootObject();
+ QVERIFY(root != 0);
+
+ QCOMPARE(root->property("mouseX").toReal(), qreal(0));
+ QCOMPARE(root->property("mouseY").toReal(), qreal(0));
+
+ QTest::mouseMove(canvas,QPoint(10,32));
+
+
+ QCOMPARE(root->property("mouseX").toReal(), qreal(10));
+ QCOMPARE(root->property("mouseY").toReal(), qreal(32));
+
+ delete canvas;
+}
+
+void tst_QQuickMouseArea::hoverPropagation()
+{
+ //QTBUG-18175, to behave like GV did.
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("hoverPropagation.qml")));
+
+ QQuickItem *root = canvas->rootObject();
+ QVERIFY(root != 0);
+
+ QCOMPARE(root->property("point1").toBool(), false);
+ QCOMPARE(root->property("point2").toBool(), false);
+
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ QCOMPARE(root->property("point1").toBool(), true);
+ QCOMPARE(root->property("point2").toBool(), false);
+
+ QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent2);
+ QCOMPARE(root->property("point1").toBool(), false);
+ QCOMPARE(root->property("point2").toBool(), true);
+
+ delete canvas;
+}
+
+QTEST_MAIN(tst_QQuickMouseArea)
+
+#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/data/inFlickable.qml b/tests/auto/qtquick2/qquickmultipointtoucharea/data/inFlickable.qml
index 53a2bf87f9..53a2bf87f9 100644
--- a/tests/auto/declarative/qquickmultipointtoucharea/data/inFlickable.qml
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/data/inFlickable.qml
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/data/nested.qml b/tests/auto/qtquick2/qquickmultipointtoucharea/data/nested.qml
index 37b8820aa0..37b8820aa0 100644
--- a/tests/auto/declarative/qquickmultipointtoucharea/data/nested.qml
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/data/nested.qml
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/data/nonOverlapping.qml b/tests/auto/qtquick2/qquickmultipointtoucharea/data/nonOverlapping.qml
index 039607e26c..039607e26c 100644
--- a/tests/auto/declarative/qquickmultipointtoucharea/data/nonOverlapping.qml
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/data/nonOverlapping.qml
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/data/properties.qml b/tests/auto/qtquick2/qquickmultipointtoucharea/data/properties.qml
index 98ef1a9cbe..98ef1a9cbe 100644
--- a/tests/auto/declarative/qquickmultipointtoucharea/data/properties.qml
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/data/properties.qml
diff --git a/tests/auto/declarative/qquickmultipointtoucharea/data/signalTest.qml b/tests/auto/qtquick2/qquickmultipointtoucharea/data/signalTest.qml
index 3a6aa86a1c..3a6aa86a1c 100644
--- a/tests/auto/declarative/qquickmultipointtoucharea/data/signalTest.qml
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/data/signalTest.qml
diff --git a/tests/auto/qtquick2/qquickmultipointtoucharea/qquickmultipointtoucharea.pro b/tests/auto/qtquick2/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
new file mode 100644
index 0000000000..38c32099b0
--- /dev/null
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
@@ -0,0 +1,11 @@
+TARGET = tst_qquickmultipointtoucharea
+CONFIG += testcase
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickmultipointtoucharea.cpp
+
+importFiles.files = data
+importFiles.path = .
+DEPLOYMENT += importFiles
+
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/qtquick2/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
new file mode 100644
index 0000000000..b4fca9bb9e
--- /dev/null
+++ b/tests/auto/qtquick2/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -0,0 +1,586 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <private/qquickmultipointtoucharea_p.h>
+#include <private/qquickflickable_p.h>
+#include <QtQuick/qquickview.h>
+
+class tst_QQuickMultiPointTouchArea: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase() {}
+ void cleanupTestCase() {}
+
+ void properties();
+ void signalTest();
+ void nonOverlapping();
+ void nested();
+ void inFlickable();
+
+private:
+ QQuickView *createAndShowView(const QString &file);
+};
+
+void tst_QQuickMultiPointTouchArea::properties()
+{
+ QQuickView *canvas = createAndShowView("properties.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(canvas->rootObject());
+ QVERIFY(area != 0);
+
+ QCOMPARE(area->minimumTouchPoints(), 2);
+ QCOMPARE(area->maximumTouchPoints(), 4);
+
+ QDeclarativeListReference ref(area, "touchPoints");
+ QCOMPARE(ref.count(), 4);
+
+ delete canvas;
+}
+
+void tst_QQuickMultiPointTouchArea::signalTest()
+{
+ QQuickView *canvas = createAndShowView("signalTest.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(canvas->rootObject());
+ QVERIFY(area != 0);
+
+ QPoint p1(20,100);
+ QPoint p2(40,100);
+ QPoint p3(60,100);
+ QPoint p4(80,100);
+ QPoint p5(100,100);
+
+ QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
+
+ sequence.press(0, p1).press(1, p2).commit();
+
+ QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
+ QCOMPARE(area->property("touchCount").toInt(), 2);
+ QMetaObject::invokeMethod(area, "clearCounts");
+
+ sequence.stationary(0).stationary(1).press(2, p3).commit();
+
+ QCOMPARE(area->property("touchPointPressCount").toInt(), 1);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
+ QCOMPARE(area->property("touchCount").toInt(), 3);
+ QMetaObject::invokeMethod(area, "clearCounts");
+
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ sequence.move(0, p1).move(1, p2).stationary(2).commit();
+
+ QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
+ QCOMPARE(area->property("touchPointReleaseCount").toInt(), 0);
+ QCOMPARE(area->property("touchCount").toInt(), 3);
+ QMetaObject::invokeMethod(area, "clearCounts");
+
+ p3 += QPoint(10,10);
+ sequence.release(0, p1).release(1, p2)
+ .move(2, p3).press(3, p4).press(4, p5).commit();
+
+ QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 1);
+ QCOMPARE(area->property("touchPointReleaseCount").toInt(), 2);
+ QCOMPARE(area->property("touchCount").toInt(), 3);
+ QMetaObject::invokeMethod(area, "clearCounts");
+
+ sequence.release(2, p3).release(3, p4).release(4, p5).commit();
+
+ QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
+ QCOMPARE(area->property("touchPointReleaseCount").toInt(), 3);
+ QCOMPARE(area->property("touchCount").toInt(), 0);
+ QMetaObject::invokeMethod(area, "clearCounts");
+
+ delete canvas;
+}
+
+void tst_QQuickMultiPointTouchArea::nonOverlapping()
+{
+ QQuickView *canvas = createAndShowView("nonOverlapping.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point11");
+ QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point12");
+ QQuickTouchPoint *point21 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point21");
+ QQuickTouchPoint *point22 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point22");
+ QQuickTouchPoint *point23 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point23");
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QPoint p1(20,100);
+ QPoint p2(40,100);
+ QPoint p3(60,180);
+ QPoint p4(80,180);
+ QPoint p5(100,180);
+
+ QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
+
+ sequence.press(0, p1).commit();
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ sequence.stationary(0).press(1, p2).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(100));
+ QCOMPARE(point12->x(), qreal(40)); QCOMPARE(point12->y(), qreal(100));
+
+ p1 += QPoint(0,10);
+ p2 += QPoint(5,0);
+ sequence.move(0, p1).move(1, p2).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+
+ sequence.stationary(0).stationary(1).press(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ sequence.stationary(0).stationary(1).stationary(2).press(3, p4).press(4, p5).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+ QCOMPARE(point21->x(), qreal(60)); QCOMPARE(point21->y(), qreal(20));
+ QCOMPARE(point22->x(), qreal(80)); QCOMPARE(point22->y(), qreal(20));
+ QCOMPARE(point23->x(), qreal(100)); QCOMPARE(point23->y(), qreal(20));
+
+ p1 += QPoint(4,10);
+ p2 += QPoint(17,17);
+ p3 += QPoint(3,0);
+ p4 += QPoint(1,-1);
+ p5 += QPoint(-7,10);
+ sequence.move(0, p1).move(1, p2).move(2, p3).move(3, p4).move(4, p5).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ QCOMPARE(point11->x(), qreal(24)); QCOMPARE(point11->y(), qreal(120));
+ QCOMPARE(point12->x(), qreal(62)); QCOMPARE(point12->y(), qreal(117));
+ QCOMPARE(point21->x(), qreal(63)); QCOMPARE(point21->y(), qreal(20));
+ QCOMPARE(point22->x(), qreal(81)); QCOMPARE(point22->y(), qreal(19));
+ QCOMPARE(point23->x(), qreal(93)); QCOMPARE(point23->y(), qreal(30));
+
+ sequence.release(0, p1).release(1, p2).release(2, p3).release(3, p4).release(4, p5).commit();
+
+ //points remain valid immediately after release
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ delete canvas;
+}
+
+void tst_QQuickMultiPointTouchArea::nested()
+{
+ QQuickView *canvas = createAndShowView("nested.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point11");
+ QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point12");
+ QQuickTouchPoint *point21 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point21");
+ QQuickTouchPoint *point22 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point22");
+ QQuickTouchPoint *point23 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point23");
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QPoint p1(20,100);
+ QPoint p2(40,100);
+ QPoint p3(60,180);
+
+ QTest::QTouchEventSequence sequence = QTest::touchEvent(canvas);
+
+ sequence.press(0, p1).commit();
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ sequence.stationary(0).press(1, p2).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(100));
+ QCOMPARE(point12->x(), qreal(40)); QCOMPARE(point12->y(), qreal(100));
+
+ p1 += QPoint(0,10);
+ p2 += QPoint(5,0);
+ sequence.move(0, p1).move(1, p2).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+
+ sequence.stationary(0).stationary(1).press(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ //point11 should be same as point21, point12 same as point22
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+ QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
+ QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
+ QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
+
+ sequence.stationary(0).stationary(1).stationary(2).press(3, QPoint(80,180)).press(4, QPoint(100,180)).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ //new touch points should be ignored (have no impact on our existing touch points)
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+ QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
+ QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
+ QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
+
+ sequence.stationary(0).stationary(1).stationary(2).release(3, QPoint(80,180)).release(4, QPoint(100,180)).commit();
+
+ p1 += QPoint(4,10);
+ p2 += QPoint(17,17);
+ p3 += QPoint(3,0);
+ sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
+ QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
+ QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
+ QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
+ QCOMPARE(point23->x(), qreal(63)); QCOMPARE(point23->y(), qreal(180));
+
+ p1 += QPoint(4,10);
+ p2 += QPoint(17,17);
+ p3 += QPoint(3,0);
+ sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ //first two remain the same (touches now grabbed by inner touch area)
+ QCOMPARE(point11->x(), qreal(24)); QCOMPARE(point11->y(), qreal(120));
+ QCOMPARE(point12->x(), qreal(62)); QCOMPARE(point12->y(), qreal(117));
+ QCOMPARE(point21->x(), qreal(28)); QCOMPARE(point21->y(), qreal(130));
+ QCOMPARE(point22->x(), qreal(79)); QCOMPARE(point22->y(), qreal(134));
+ QCOMPARE(point23->x(), qreal(66)); QCOMPARE(point23->y(), qreal(180));
+
+ sequence.release(0, p1).release(1, p2).release(2, p3).commit();
+
+ sequence.press(0, p1).commit();
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+ QCOMPARE(point21->isValid(), false);
+ QCOMPARE(point22->isValid(), false);
+ QCOMPARE(point23->isValid(), false);
+
+ sequence.release(0, p1).commit();
+
+ //test with grabbing turned off
+ canvas->rootObject()->setProperty("grabInnerArea", false);
+
+ sequence.press(0, p1).press(1, p2).press(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ p1 -= QPoint(4,10);
+ p2 -= QPoint(17,17);
+ p3 -= QPoint(3,0);
+ sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
+ QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
+ QCOMPARE(point21->x(), qreal(24)); QCOMPARE(point21->y(), qreal(120));
+ QCOMPARE(point22->x(), qreal(62)); QCOMPARE(point22->y(), qreal(117));
+ QCOMPARE(point23->x(), qreal(63)); QCOMPARE(point23->y(), qreal(180));
+
+ p1 -= QPoint(4,10);
+ p2 -= QPoint(17,17);
+ p3 -= QPoint(3,0);
+ sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+ QCOMPARE(point21->isValid(), true);
+ QCOMPARE(point22->isValid(), true);
+ QCOMPARE(point23->isValid(), true);
+
+ //all change (touches not grabbed by inner touch area)
+ QCOMPARE(point11->x(), qreal(20)); QCOMPARE(point11->y(), qreal(110));
+ QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
+ QCOMPARE(point21->x(), qreal(20)); QCOMPARE(point21->y(), qreal(110));
+ QCOMPARE(point22->x(), qreal(45)); QCOMPARE(point22->y(), qreal(100));
+ QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
+
+ sequence.release(0, p1).release(1, p2).release(2, p3).commit();
+
+ delete canvas;
+}
+
+void tst_QQuickMultiPointTouchArea::inFlickable()
+{
+ QQuickView *canvas = createAndShowView("inFlickable.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ QQuickTouchPoint *point11 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point1");
+ QQuickTouchPoint *point12 = canvas->rootObject()->findChild<QQuickTouchPoint*>("point2");
+
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+
+ QPoint p1(20,100);
+ QPoint p2(40,100);
+
+ //moving one point vertically
+ QTest::touchEvent(canvas).press(0, p1);
+ QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
+
+ p1 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1);
+ QTest::mouseMove(canvas, p1);
+
+ QVERIFY(flickable->contentY() < 0);
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+
+ QTest::touchEvent(canvas).release(0, p1);
+ QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
+ QTest::qWait(50);
+
+ QTRY_VERIFY(!flickable->isMoving());
+
+ //moving two points vertically
+ p1 = QPoint(20,100);
+ QTest::touchEvent(canvas).press(0, p1).press(1, p2);
+ QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ QVERIFY(flickable->contentY() < 0);
+ QCOMPARE(point11->isValid(), false);
+ QCOMPARE(point12->isValid(), false);
+
+ QTest::touchEvent(canvas).release(0, p1).release(1, p2);
+ QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
+ QTest::qWait(50);
+
+ QTRY_VERIFY(!flickable->isMoving());
+
+ //moving two points horizontally, then one point vertically
+ p1 = QPoint(20,100);
+ p2 = QPoint(40,100);
+ QTest::touchEvent(canvas).press(0, p1).press(1, p2);
+ QTest::mousePress(canvas, Qt::LeftButton, 0, p1);
+
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+
+ p1 += QPoint(15,0); p2 += QPoint(15,0);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(15,0); p2 += QPoint(15,0);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(15,0); p2 += QPoint(15,0);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(15,0); p2 += QPoint(15,0);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ p1 += QPoint(0,15); p2 += QPoint(0,15);
+ QTest::touchEvent(canvas).move(0, p1).move(1, p2);
+ QTest::mouseMove(canvas, p1);
+
+ QVERIFY(flickable->contentY() == 0);
+ QCOMPARE(point11->isValid(), true);
+ QCOMPARE(point12->isValid(), true);
+
+ QTest::touchEvent(canvas).release(0, p1).release(1, p2);
+ QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1);
+ QTest::qWait(50);
+
+ delete canvas;
+}
+
+QQuickView *tst_QQuickMultiPointTouchArea::createAndShowView(const QString &file)
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QLatin1String("/data/") + file));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+
+ return canvas;
+}
+
+QTEST_MAIN(tst_QQuickMultiPointTouchArea)
+
+#include "tst_qquickmultipointtoucharea.moc"
diff --git a/tests/auto/declarative/qquickpathview/data/ComponentView.qml b/tests/auto/qtquick2/qquickpathview/data/ComponentView.qml
index b61033d375..b61033d375 100644
--- a/tests/auto/declarative/qquickpathview/data/ComponentView.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/ComponentView.qml
diff --git a/tests/auto/declarative/qquickpathview/data/asyncloader.qml b/tests/auto/qtquick2/qquickpathview/data/asyncloader.qml
index 94f560f3e7..94f560f3e7 100644
--- a/tests/auto/declarative/qquickpathview/data/asyncloader.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/asyncloader.qml
diff --git a/tests/auto/declarative/qquickpathview/data/closedPath.qml b/tests/auto/qtquick2/qquickpathview/data/closedPath.qml
index 3ca34056c8..3ca34056c8 100644
--- a/tests/auto/declarative/qquickpathview/data/closedPath.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/closedPath.qml
diff --git a/tests/auto/declarative/qquickpathview/data/creationContext.qml b/tests/auto/qtquick2/qquickpathview/data/creationContext.qml
index 79a682788b..79a682788b 100644
--- a/tests/auto/declarative/qquickpathview/data/creationContext.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/creationContext.qml
diff --git a/tests/auto/declarative/qquickpathview/data/datamodel.qml b/tests/auto/qtquick2/qquickpathview/data/datamodel.qml
index 44f2aecc0a..44f2aecc0a 100644
--- a/tests/auto/declarative/qquickpathview/data/datamodel.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/datamodel.qml
diff --git a/tests/auto/declarative/qquickpathview/data/displaypath.qml b/tests/auto/qtquick2/qquickpathview/data/displaypath.qml
index af0f381fc4..af0f381fc4 100644
--- a/tests/auto/declarative/qquickpathview/data/displaypath.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/displaypath.qml
diff --git a/tests/auto/declarative/qquickpathview/data/dragpath.qml b/tests/auto/qtquick2/qquickpathview/data/dragpath.qml
index f9c6615b04..f9c6615b04 100644
--- a/tests/auto/declarative/qquickpathview/data/dragpath.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/dragpath.qml
diff --git a/tests/auto/declarative/qquickpathview/data/emptymodel.qml b/tests/auto/qtquick2/qquickpathview/data/emptymodel.qml
index eb4d3006f4..eb4d3006f4 100644
--- a/tests/auto/declarative/qquickpathview/data/emptymodel.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/emptymodel.qml
diff --git a/tests/auto/declarative/qquickpathview/data/missingPercent.qml b/tests/auto/qtquick2/qquickpathview/data/missingPercent.qml
index 97af8e8982..97af8e8982 100644
--- a/tests/auto/declarative/qquickpathview/data/missingPercent.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/missingPercent.qml
diff --git a/tests/auto/declarative/qquickpathview/data/openPath.qml b/tests/auto/qtquick2/qquickpathview/data/openPath.qml
index 1bd8375d9e..1bd8375d9e 100644
--- a/tests/auto/declarative/qquickpathview/data/openPath.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/openPath.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathUpdate.qml b/tests/auto/qtquick2/qquickpathview/data/pathUpdate.qml
index e729291025..e729291025 100644
--- a/tests/auto/declarative/qquickpathview/data/pathUpdate.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathUpdate.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathUpdateOnStartChanged.qml b/tests/auto/qtquick2/qquickpathview/data/pathUpdateOnStartChanged.qml
index 89084b2a37..89084b2a37 100644
--- a/tests/auto/declarative/qquickpathview/data/pathUpdateOnStartChanged.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathUpdateOnStartChanged.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathline.qml b/tests/auto/qtquick2/qquickpathview/data/pathline.qml
index 4c1c785bce..4c1c785bce 100644
--- a/tests/auto/declarative/qquickpathview/data/pathline.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathline.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathtest.qml b/tests/auto/qtquick2/qquickpathview/data/pathtest.qml
index 736d58d2a9..736d58d2a9 100644
--- a/tests/auto/declarative/qquickpathview/data/pathtest.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathtest.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathview0.qml b/tests/auto/qtquick2/qquickpathview/data/pathview0.qml
index 8b9378163f..8b9378163f 100644
--- a/tests/auto/declarative/qquickpathview/data/pathview0.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathview0.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathview1.qml b/tests/auto/qtquick2/qquickpathview/data/pathview1.qml
index 53d375e596..53d375e596 100644
--- a/tests/auto/declarative/qquickpathview/data/pathview1.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathview1.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathview2.qml b/tests/auto/qtquick2/qquickpathview/data/pathview2.qml
index 1d279c42a0..1d279c42a0 100644
--- a/tests/auto/declarative/qquickpathview/data/pathview2.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathview2.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathview3.qml b/tests/auto/qtquick2/qquickpathview/data/pathview3.qml
index ded5a3911c..ded5a3911c 100644
--- a/tests/auto/declarative/qquickpathview/data/pathview3.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathview3.qml
diff --git a/tests/auto/declarative/qquickpathview/data/pathview_package.qml b/tests/auto/qtquick2/qquickpathview/data/pathview_package.qml
index 2af57e6bb1..2af57e6bb1 100644
--- a/tests/auto/declarative/qquickpathview/data/pathview_package.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/pathview_package.qml
diff --git a/tests/auto/declarative/qquickpathview/data/propertychanges.qml b/tests/auto/qtquick2/qquickpathview/data/propertychanges.qml
index 09b309f86f..09b309f86f 100644
--- a/tests/auto/declarative/qquickpathview/data/propertychanges.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/propertychanges.qml
diff --git a/tests/auto/declarative/qquickpathview/data/treemodel.qml b/tests/auto/qtquick2/qquickpathview/data/treemodel.qml
index fcf6922d00..fcf6922d00 100644
--- a/tests/auto/declarative/qquickpathview/data/treemodel.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/treemodel.qml
diff --git a/tests/auto/declarative/qquickpathview/data/undefinedpath.qml b/tests/auto/qtquick2/qquickpathview/data/undefinedpath.qml
index 674e7cca8d..674e7cca8d 100644
--- a/tests/auto/declarative/qquickpathview/data/undefinedpath.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/undefinedpath.qml
diff --git a/tests/auto/declarative/qquickpathview/data/vdm.qml b/tests/auto/qtquick2/qquickpathview/data/vdm.qml
index 839393d9bd..839393d9bd 100644
--- a/tests/auto/declarative/qquickpathview/data/vdm.qml
+++ b/tests/auto/qtquick2/qquickpathview/data/vdm.qml
diff --git a/tests/auto/qtquick2/qquickpathview/qquickpathview.pro b/tests/auto/qtquick2/qquickpathview/qquickpathview.pro
new file mode 100644
index 0000000000..6e16dd4879
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpathview/qquickpathview.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickpathview
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickpathview.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private v8-private declarative-private quick-private widgets testlib
diff --git a/tests/auto/qtquick2/qquickpathview/tst_qquickpathview.cpp b/tests/auto/qtquick2/qquickpathview/tst_qquickpathview.cpp
new file mode 100644
index 0000000000..2f1d836c72
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpathview/tst_qquickpathview.cpp
@@ -0,0 +1,1629 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+#include <QtQuick/private/qquickpathview_p.h>
+#include <QtQuick/private/qdeclarativepath_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
+#include <QtDeclarative/private/qdeclarativevaluetype_p.h>
+#include <QAbstractListModel>
+#include <QStringListModel>
+#include <QStandardItemModel>
+#include <QFile>
+
+#include "../../shared/util.h"
+
+static void initStandardTreeModel(QStandardItemModel *model)
+{
+ QStandardItem *item;
+ item = new QStandardItem(QLatin1String("Row 1 Item"));
+ model->insertRow(0, item);
+
+ item = new QStandardItem(QLatin1String("Row 2 Item"));
+ item->setCheckable(true);
+ model->insertRow(1, item);
+
+ QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
+ item->setChild(0, childItem);
+
+ item = new QStandardItem(QLatin1String("Row 3 Item"));
+ item->setIcon(QIcon());
+ model->insertRow(2, item);
+}
+
+
+class tst_QQuickPathView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickPathView();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void initValues();
+ void items();
+ void dataModel();
+ void pathview2();
+ void pathview3();
+ void insertModel_data();
+ void insertModel();
+ void removeModel_data();
+ void removeModel();
+ void moveModel_data();
+ void moveModel();
+ void path();
+ void pathMoved();
+ void setCurrentIndex();
+ void resetModel();
+ void propertyChanges();
+ void pathChanges();
+ void componentChanges();
+ void modelChanges();
+ void pathUpdateOnStartChanged();
+ void package();
+ void emptyModel();
+ void closed();
+ void pathUpdate();
+ void visualDataModel();
+ void undefinedPath();
+ void mouseDrag();
+ void treeModel();
+ void changePreferredHighlight();
+ void missingPercent();
+ void creationContext();
+ void currentOffsetOnInsertion();
+ void asynchronous();
+
+private:
+ QQuickView *createView();
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &objectName, int index=-1);
+ template<typename T>
+ QList<T*> findItems(QQuickItem *parent, const QString &objectName);
+};
+
+void tst_QQuickPathView::initTestCase()
+{
+}
+
+void tst_QQuickPathView::cleanupTestCase()
+{
+
+}
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError)
+ Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
+ Q_PROPERTY(int pathItemCount READ pathItemCount NOTIFY pathItemCountChanged)
+
+public:
+ TestObject() : QObject(), mError(true), mUseModel(true), mPathItemCount(-1) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; }
+
+ bool useModel() const { return mUseModel; }
+ void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
+
+ int pathItemCount() const { return mPathItemCount; }
+ void setPathItemCount(int count) { mPathItemCount = count; emit pathItemCountChanged(); }
+
+signals:
+ void useModelChanged();
+ void pathItemCountChanged();
+
+private:
+ bool mError;
+ bool mUseModel;
+ int mPathItemCount;
+};
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ endInsertRows();
+ }
+
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ beginInsertRows(QModelIndex(), index, index+items.count()-1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ endInsertRows();
+ }
+
+ void removeItem(int index) {
+ beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ endRemoveRows();
+ }
+
+ void removeItems(int index, int count) {
+ emit beginRemoveRows(QModelIndex(), index, index+count-1);
+ while (count--)
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ endMoveRows();
+ }
+
+ void moveItems(int from, int to, int count) {
+ beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
+ move(from, to, count);
+ endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+ void move(int from, int to, int n)
+ {
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+ if (n == 1) {
+ list.move(from, to);
+ } else {
+ QList<QPair<QString,QString> > replaced;
+ int i=0;
+ QList<QPair<QString,QString> >::ConstIterator it=list.begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=list.begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ QList<QPair<QString,QString> >::ConstIterator f=replaced.begin();
+ QList<QPair<QString,QString> >::Iterator t=list.begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+tst_QQuickPathView::tst_QQuickPathView()
+{
+}
+
+void tst_QQuickPathView::initValues()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview1.qml")));
+ QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() == 0);
+ QVERIFY(obj->delegate() == 0);
+ QCOMPARE(obj->model(), QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 0.);
+ QCOMPARE(obj->preferredHighlightBegin(), 0.);
+ QCOMPARE(obj->dragMargin(), 0.);
+ QCOMPARE(obj->count(), 0);
+ QCOMPARE(obj->pathItemCount(), -1);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::items()
+{
+ QQuickView *canvas = createView();
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->count(), model.count());
+ QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QCOMPARE(pathview->childItems().count(), model.count()+1); // assumes all are visible, including highlight
+
+ for (int i = 0; i < model.count(); ++i) {
+ QQuickText *name = findItem<QQuickText>(pathview, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QQuickText *number = findItem<QQuickText>(pathview, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+
+ QVERIFY(pathview->highlightItem());
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;
+ offset.setX(pathview->highlightItem()->width()/2);
+ offset.setY(pathview->highlightItem()->height()/2);
+ QCOMPARE(pathview->highlightItem()->pos() + offset, start);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::pathview2()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview2.qml")));
+ QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() != 0);
+ QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj->model() != QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 0.);
+ QCOMPARE(obj->preferredHighlightBegin(), 0.);
+ QCOMPARE(obj->dragMargin(), 0.);
+ QCOMPARE(obj->count(), 8);
+ QCOMPARE(obj->pathItemCount(), 10);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::pathview3()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathview3.qml")));
+ QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
+
+ QVERIFY(obj != 0);
+ QVERIFY(obj->path() != 0);
+ QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj->model() != QVariant());
+ QCOMPARE(obj->currentIndex(), 0);
+ QCOMPARE(obj->offset(), 1.0);
+ QCOMPARE(obj->preferredHighlightBegin(), 0.5);
+ QCOMPARE(obj->dragMargin(), 24.);
+ QCOMPARE(obj->count(), 8);
+ QCOMPARE(obj->pathItemCount(), 4);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::insertModel_data()
+{
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("idx");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("offset");
+
+ // We have 8 items, with currentIndex == 4
+ QTest::newRow("insert after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 5.;
+ QTest::newRow("insert before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4.;
+ QTest::newRow("insert multiple after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 6.;
+ QTest::newRow("insert multiple before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4.;
+ QTest::newRow("insert at end")
+ << int(QQuickPathView::StrictlyEnforceRange) << 8 << 1 << 5.;
+ QTest::newRow("insert at beginning")
+ << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4.;
+ QTest::newRow("insert at current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 4.;
+
+ QTest::newRow("no range - insert after current")
+ << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 5.;
+ QTest::newRow("no range - insert before current")
+ << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4.;
+ QTest::newRow("no range - insert multiple after current")
+ << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 6.;
+ QTest::newRow("no range - insert multiple before current")
+ << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4.;
+ QTest::newRow("no range - insert at end")
+ << int(QQuickPathView::NoHighlightRange) << 8 << 1 << 5.;
+ QTest::newRow("no range - insert at beginning")
+ << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4.;
+ QTest::newRow("no range - insert at current")
+ << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4.;
+}
+
+void tst_QQuickPathView::insertModel()
+{
+ QFETCH(int, mode);
+ QFETCH(int, idx);
+ QFETCH(int, count);
+ QFETCH(qreal, offset);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+ model.addItem("Jinny", "679");
+ model.addItem("Milly", "73378");
+ model.addItem("Jimmy", "3535");
+ model.addItem("Barb", "9039");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
+
+ pathview->setCurrentIndex(4);
+ if (mode == QQuickPathView::StrictlyEnforceRange)
+ QTRY_COMPARE(pathview->offset(), 4.0);
+ else
+ pathview->setOffset(4);
+
+ QList<QPair<QString, QString> > items;
+ for (int i = 0; i < count; ++i)
+ items.append(qMakePair(QString("New"), QString::number(i)));
+
+ model.insertItems(idx, items);
+ QTRY_COMPARE(pathview->offset(), offset);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::removeModel_data()
+{
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("idx");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("offset");
+
+ // We have 8 items, with currentIndex == 4
+ QTest::newRow("remove after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 3.;
+ QTest::newRow("remove before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4.;
+ QTest::newRow("remove multiple after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 2.;
+ QTest::newRow("remove multiple before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4.;
+ QTest::newRow("remove last")
+ << int(QQuickPathView::StrictlyEnforceRange) << 7 << 1 << 3.;
+ QTest::newRow("remove first")
+ << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4.;
+ QTest::newRow("remove current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 3.;
+
+ QTest::newRow("no range - remove after current")
+ << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 3.;
+ QTest::newRow("no range - remove before current")
+ << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4.;
+ QTest::newRow("no range - remove multiple after current")
+ << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 2.;
+ QTest::newRow("no range - remove multiple before current")
+ << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4.;
+ QTest::newRow("no range - remove last")
+ << int(QQuickPathView::NoHighlightRange) << 7 << 1 << 3.;
+ QTest::newRow("no range - remove first")
+ << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4.;
+ QTest::newRow("no range - remove current offset")
+ << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4.;
+}
+
+void tst_QQuickPathView::removeModel()
+{
+ QFETCH(int, mode);
+ QFETCH(int, idx);
+ QFETCH(int, count);
+ QFETCH(qreal, offset);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+ model.addItem("Jinny", "679");
+ model.addItem("Milly", "73378");
+ model.addItem("Jimmy", "3535");
+ model.addItem("Barb", "9039");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
+
+ pathview->setCurrentIndex(4);
+ if (mode == QQuickPathView::StrictlyEnforceRange)
+ QTRY_COMPARE(pathview->offset(), 4.0);
+ else
+ pathview->setOffset(4);
+
+ model.removeItems(idx, count);
+ QTRY_COMPARE(pathview->offset(), offset);
+
+ delete canvas;
+}
+
+
+void tst_QQuickPathView::moveModel_data()
+{
+ QTest::addColumn<int>("mode");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("offset");
+
+ // We have 8 items, with currentIndex == 4
+ QTest::newRow("move after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 1 << 4.;
+ QTest::newRow("move before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 2 << 3 << 1 << 4.;
+ QTest::newRow("move before current to after")
+ << int(QQuickPathView::StrictlyEnforceRange) << 2 << 6 << 1 << 5.;
+ QTest::newRow("move multiple after current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 2 << 4.;
+ QTest::newRow("move multiple before current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 2 << 4.;
+ QTest::newRow("move before current to end")
+ << int(QQuickPathView::StrictlyEnforceRange) << 2 << 7 << 1 << 5.;
+ QTest::newRow("move last to beginning")
+ << int(QQuickPathView::StrictlyEnforceRange) << 7 << 0 << 1 << 3.;
+ QTest::newRow("move current")
+ << int(QQuickPathView::StrictlyEnforceRange) << 4 << 6 << 1 << 2.;
+
+ QTest::newRow("no range - move after current")
+ << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 1 << 4.;
+ QTest::newRow("no range - move before current")
+ << int(QQuickPathView::NoHighlightRange) << 2 << 3 << 1 << 4.;
+ QTest::newRow("no range - move before current to after")
+ << int(QQuickPathView::NoHighlightRange) << 2 << 6 << 1 << 5.;
+ QTest::newRow("no range - move multiple after current")
+ << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 2 << 4.;
+ QTest::newRow("no range - move multiple before current")
+ << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 2 << 4.;
+ QTest::newRow("no range - move before current to end")
+ << int(QQuickPathView::NoHighlightRange) << 2 << 7 << 1 << 5.;
+ QTest::newRow("no range - move last to beginning")
+ << int(QQuickPathView::NoHighlightRange) << 7 << 0 << 1 << 3.;
+ QTest::newRow("no range - move current")
+ << int(QQuickPathView::NoHighlightRange) << 4 << 6 << 1 << 4.;
+ QTest::newRow("no range - move multiple incl. current")
+ << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 5 << 4.;
+}
+
+void tst_QQuickPathView::moveModel()
+{
+ QFETCH(int, mode);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, count);
+ QFETCH(qreal, offset);
+
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+ model.addItem("Jinny", "679");
+ model.addItem("Milly", "73378");
+ model.addItem("Jimmy", "3535");
+ model.addItem("Barb", "9039");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
+
+ pathview->setCurrentIndex(4);
+ if (mode == QQuickPathView::StrictlyEnforceRange)
+ QTRY_COMPARE(pathview->offset(), 4.0);
+ else
+ pathview->setOffset(4);
+
+ model.moveItems(from, to, count);
+ QTRY_COMPARE(pathview->offset(), offset);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::path()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("pathtest.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->startX(), 120.);
+ QCOMPARE(obj->startY(), 100.);
+ QVERIFY(obj->path() != QPainterPath());
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 5);
+
+ QDeclarativePathAttribute* attr = qobject_cast<QDeclarativePathAttribute*>(list.at(0));
+ QVERIFY(attr != 0);
+ QCOMPARE(attr->name(), QString("scale"));
+ QCOMPARE(attr->value(), 1.0);
+
+ QDeclarativePathQuad* quad = qobject_cast<QDeclarativePathQuad*>(list.at(1));
+ QVERIFY(quad != 0);
+ QCOMPARE(quad->x(), 120.);
+ QCOMPARE(quad->y(), 25.);
+ QCOMPARE(quad->controlX(), 260.);
+ QCOMPARE(quad->controlY(), 75.);
+
+ QDeclarativePathPercent* perc = qobject_cast<QDeclarativePathPercent*>(list.at(2));
+ QVERIFY(perc != 0);
+ QCOMPARE(perc->value(), 0.3);
+
+ QDeclarativePathLine* line = qobject_cast<QDeclarativePathLine*>(list.at(3));
+ QVERIFY(line != 0);
+ QCOMPARE(line->x(), 120.);
+ QCOMPARE(line->y(), 100.);
+
+ QDeclarativePathCubic* cubic = qobject_cast<QDeclarativePathCubic*>(list.at(4));
+ QVERIFY(cubic != 0);
+ QCOMPARE(cubic->x(), 180.);
+ QCOMPARE(cubic->y(), 0.);
+ QCOMPARE(cubic->control1X(), -10.);
+ QCOMPARE(cubic->control1Y(), 90.);
+ QCOMPARE(cubic->control2X(), 210.);
+ QCOMPARE(cubic->control2Y(), 90.);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::dataModel()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel model;
+ model.addItem("red", "1");
+ model.addItem("green", "2");
+ model.addItem("blue", "3");
+ model.addItem("purple", "4");
+ model.addItem("gray", "5");
+ model.addItem("brown", "6");
+ model.addItem("yellow", "7");
+ model.addItem("thistle", "8");
+ model.addItem("cyan", "9");
+ model.addItem("peachpuff", "10");
+ model.addItem("powderblue", "11");
+ model.addItem("gold", "12");
+ model.addItem("sandybrown", "13");
+
+ ctxt->setContextProperty("testData", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("datamodel.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QQuickItem *item = findItem<QQuickItem>(pathview, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->x(), 110.0);
+ QCOMPARE(item->y(), 10.0);
+
+ model.insertItem(4, "orange", "10");
+ QTest::qWait(100);
+
+ QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
+ QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 14);
+
+ QVERIFY(pathview->currentIndex() == 0);
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
+
+ QQuickText *text = findItem<QQuickText>(pathview, "myText", 4);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(4));
+
+ model.removeItem(2);
+ QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
+ text = findItem<QQuickText>(pathview, "myText", 2);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(2));
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
+
+ testObject->setPathItemCount(5);
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
+
+ QQuickRectangle *testItem = findItem<QQuickRectangle>(pathview, "wrapper", 4);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QQuickRectangle>(pathview, "wrapper", 5);
+ QVERIFY(testItem == 0);
+
+ pathview->setCurrentIndex(1);
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
+ QTest::qWait(100);
+
+ model.insertItem(2, "pink", "2");
+ QTest::qWait(100);
+
+ QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
+ QVERIFY(pathview->currentIndex() == 1);
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
+
+ text = findItem<QQuickText>(pathview, "myText", 2);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(2));
+
+ model.removeItem(3);
+ QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
+ text = findItem<QQuickText>(pathview, "myText", 3);
+ QVERIFY(text);
+ QCOMPARE(text->text(), model.name(3));
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
+
+ model.moveItem(3, 5);
+ QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
+ QList<QQuickItem*> items = findItems<QQuickItem>(pathview, "wrapper");
+ foreach (QQuickItem *item, items) {
+ QVERIFY(item->property("onPath").toBool());
+ }
+ QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
+
+ // QTBUG-14199
+ pathview->setOffset(7);
+ pathview->setOffset(0);
+ QCOMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
+
+ pathview->setCurrentIndex(model.count()-1);
+ model.removeItem(model.count()-1);
+ QCOMPARE(pathview->currentIndex(), model.count()-1);
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QQuickPathView::pathMoved()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ pathview->setOffset(1.0);
+
+ for (int i=0; i<model.count(); i++) {
+ QQuickRectangle *curItem = findItem<QQuickRectangle>(pathview, "wrapper", i);
+ QPointF itemPos(path->pointAt(0.25 + i*0.25));
+ QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
+ }
+
+ pathview->setOffset(0.0);
+ QCOMPARE(firstItem->pos() + offset, start);
+
+ // Change delegate size
+ pathview->setOffset(0.1);
+ pathview->setOffset(0.0);
+ canvas->rootObject()->setProperty("delegateWidth", 30);
+ QCOMPARE(firstItem->width(), 30.0);
+ offset.setX(firstItem->width()/2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+
+ // Change delegate scale
+ pathview->setOffset(0.1);
+ pathview->setOffset(0.0);
+ canvas->rootObject()->setProperty("delegateScale", 1.2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::setCurrentIndex()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview0.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QCOMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 0);
+ QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 0);
+
+ pathview->setCurrentIndex(2);
+
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 2);
+ QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 2);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 1);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
+ QVERIFY(firstItem);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 0);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 3);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
+ QVERIFY(firstItem);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->incrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 0);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ // move an item, set move duration to 0, and change currentIndex to moved item. QTBUG-22786
+ model.moveItem(0, 3);
+ pathview->setHighlightMoveDuration(0);
+ pathview->setCurrentIndex(3);
+ QCOMPARE(pathview->currentIndex(), 3);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
+ QVERIFY(firstItem);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ model.moveItem(3, 0);
+ pathview->setCurrentIndex(0);
+ pathview->setHighlightMoveDuration(300);
+
+ // Check the current item is still created when outside the bounds of pathItemCount.
+ pathview->setPathItemCount(2);
+ pathview->setHighlightRangeMode(QQuickPathView::NoHighlightRange);
+ QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 0));
+ QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 1));
+ QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 2));
+ QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 3));
+
+ pathview->setCurrentIndex(2);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(false));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 1);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
+ QVERIFY(firstItem);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 0);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ pathview->decrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 3);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
+ QVERIFY(firstItem);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(false));
+
+ pathview->incrementCurrentIndex();
+ QTRY_COMPARE(pathview->currentIndex(), 0);
+ firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QCOMPARE(pathview->currentItem(), firstItem);
+ QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::resetModel()
+{
+ QQuickView *canvas = createView();
+
+ QStringList strings;
+ strings << "one" << "two" << "three";
+ QStringListModel model(strings);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaypath.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
+ QVERIFY(display != 0);
+ QCOMPARE(display->text(), strings.at(i));
+ }
+
+ strings.clear();
+ strings << "four" << "five" << "six" << "seven";
+ model.setStringList(strings);
+
+ QCOMPARE(pathview->count(), model.rowCount());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
+ QVERIFY(display != 0);
+ QCOMPARE(display->text(), strings.at(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::propertyChanges()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QSignalSpy snapPositionSpy(pathView, SIGNAL(preferredHighlightBeginChanged()));
+ QSignalSpy dragMarginSpy(pathView, SIGNAL(dragMarginChanged()));
+
+ QCOMPARE(pathView->preferredHighlightBegin(), 0.1);
+ QCOMPARE(pathView->dragMargin(), 5.0);
+
+ pathView->setPreferredHighlightBegin(0.4);
+ pathView->setPreferredHighlightEnd(0.4);
+ pathView->setDragMargin(20.0);
+
+ QCOMPARE(pathView->preferredHighlightBegin(), 0.4);
+ QCOMPARE(pathView->preferredHighlightEnd(), 0.4);
+ QCOMPARE(pathView->dragMargin(), 20.0);
+
+ QCOMPARE(snapPositionSpy.count(), 1);
+ QCOMPARE(dragMarginSpy.count(), 1);
+
+ pathView->setPreferredHighlightBegin(0.4);
+ pathView->setPreferredHighlightEnd(0.4);
+ pathView->setDragMargin(20.0);
+
+ QCOMPARE(snapPositionSpy.count(), 1);
+ QCOMPARE(dragMarginSpy.count(), 1);
+ delete canvas;
+}
+
+void tst_QQuickPathView::pathChanges()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
+ QVERIFY(path);
+
+ QSignalSpy startXSpy(path, SIGNAL(startXChanged()));
+ QSignalSpy startYSpy(path, SIGNAL(startYChanged()));
+
+ QCOMPARE(path->startX(), 220.0);
+ QCOMPARE(path->startY(), 200.0);
+
+ path->setStartX(240.0);
+ path->setStartY(220.0);
+
+ QCOMPARE(path->startX(), 240.0);
+ QCOMPARE(path->startY(), 220.0);
+
+ QCOMPARE(startXSpy.count(),1);
+ QCOMPARE(startYSpy.count(),1);
+
+ path->setStartX(240);
+ path->setStartY(220);
+
+ QCOMPARE(startXSpy.count(),1);
+ QCOMPARE(startYSpy.count(),1);
+
+ QDeclarativePath *alternatePath = canvas->rootObject()->findChild<QDeclarativePath*>("alternatePath");
+ QVERIFY(alternatePath);
+
+ QSignalSpy pathSpy(pathView, SIGNAL(pathChanged()));
+
+ QCOMPARE(pathView->path(), path);
+
+ pathView->setPath(alternatePath);
+ QCOMPARE(pathView->path(), alternatePath);
+ QCOMPARE(pathSpy.count(),1);
+
+ pathView->setPath(alternatePath);
+ QCOMPARE(pathSpy.count(),1);
+
+ QDeclarativePathAttribute *pathAttribute = canvas->rootObject()->findChild<QDeclarativePathAttribute*>("pathAttribute");
+ QVERIFY(pathAttribute);
+
+ QSignalSpy nameSpy(pathAttribute, SIGNAL(nameChanged()));
+ QCOMPARE(pathAttribute->name(), QString("opacity"));
+
+ pathAttribute->setName("scale");
+ QCOMPARE(pathAttribute->name(), QString("scale"));
+ QCOMPARE(nameSpy.count(),1);
+
+ pathAttribute->setName("scale");
+ QCOMPARE(nameSpy.count(),1);
+ delete canvas;
+}
+
+void tst_QQuickPathView::componentChanges()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QDeclarativeComponent delegateComponent(canvas->engine());
+ delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
+
+ QSignalSpy delegateSpy(pathView, SIGNAL(delegateChanged()));
+
+ pathView->setDelegate(&delegateComponent);
+ QCOMPARE(pathView->delegate(), &delegateComponent);
+ QCOMPARE(delegateSpy.count(),1);
+
+ pathView->setDelegate(&delegateComponent);
+ QCOMPARE(delegateSpy.count(),1);
+ delete canvas;
+}
+
+void tst_QQuickPathView::modelChanges()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychanges.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
+ QVERIFY(alternateModel);
+ QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
+ QSignalSpy modelSpy(pathView, SIGNAL(modelChanged()));
+
+ pathView->setModel(modelVariant);
+ QCOMPARE(pathView->model(), modelVariant);
+ QCOMPARE(modelSpy.count(),1);
+
+ pathView->setModel(modelVariant);
+ QCOMPARE(modelSpy.count(),1);
+
+ pathView->setModel(QVariant());
+ QCOMPARE(modelSpy.count(),2);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::pathUpdateOnStartChanged()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathUpdateOnStartChanged.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
+ QVERIFY(path);
+ QCOMPARE(path->startX(), 400.0);
+ QCOMPARE(path->startY(), 300.0);
+
+ QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->x(), path->startX() - item->width() / 2.0);
+ QCOMPARE(item->y(), path->startY() - item->height() / 2.0);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::package()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathview_package.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("photoPathView");
+ QVERIFY(pathView);
+
+ QQuickItem *item = findItem<QQuickItem>(pathView, "pathItem");
+ QVERIFY(item);
+ QVERIFY(item->scale() != 1.0);
+
+ delete canvas;
+}
+
+//QTBUG-13017
+void tst_QQuickPathView::emptyModel()
+{
+ QQuickView *canvas = createView();
+
+ QStringListModel model;
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("emptyModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("emptymodel.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->offset(), qreal(0.0));
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::closed()
+{
+ QDeclarativeEngine engine;
+
+ {
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("openPath.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj);
+ QCOMPARE(obj->isClosed(), false);
+ delete obj;
+ }
+
+ {
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("closedPath.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj);
+ QCOMPARE(obj->isClosed(), true);
+ delete obj;
+ }
+}
+
+// QTBUG-14239
+void tst_QQuickPathView::pathUpdate()
+{
+ QQuickView *canvas = createView();
+ QVERIFY(canvas);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathUpdate.qml")));
+
+ QQuickPathView *pathView = canvas->rootObject()->findChild<QQuickPathView*>("pathView");
+ QVERIFY(pathView);
+
+ QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->x(), 150.0);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::visualDataModel()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("vdm.qml")));
+
+ QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->count(), 3);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::undefinedPath()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("undefinedpath.qml")));
+
+ QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->count(), 3);
+
+ delete obj;
+}
+
+void tst_QQuickPathView::mouseDrag()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragpath.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(canvas, qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+
+ int current = pathview->currentIndex();
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10,100));
+ QTest::qWait(100);
+
+ {
+ QMouseEvent mv(QEvent::MouseMove, QPoint(30,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ }
+ {
+ QMouseEvent mv(QEvent::MouseMove, QPoint(90,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(canvas, &mv);
+ }
+
+ QVERIFY(pathview->currentIndex() != current);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(40,100));
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::treeModel()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+ canvas->engine()->rootContext()->setContextProperty("myModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("treemodel.qml")));
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+ QCOMPARE(pathview->count(), 3);
+
+ QQuickText *item = findItem<QQuickText>(pathview, "wrapper", 0);
+ QVERIFY(item);
+ QCOMPARE(item->text(), QLatin1String("Row 1 Item"));
+
+ QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1)));
+ QCOMPARE(pathview->count(), 1);
+
+ QTRY_VERIFY(item = findItem<QQuickText>(pathview, "wrapper", 0));
+ QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item"));
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::changePreferredHighlight()
+{
+ QQuickView *canvas = createView();
+ canvas->setGeometry(0,0,400,200);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("dragpath.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(canvas, qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject());
+ QVERIFY(pathview != 0);
+
+ int current = pathview->currentIndex();
+ QCOMPARE(current, 0);
+
+ QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.5);
+ start.setX(qRound(start.x()));
+ start.setY(qRound(start.y()));
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+
+ pathview->setPreferredHighlightBegin(0.8);
+ pathview->setPreferredHighlightEnd(0.8);
+ start = path->pointAt(0.8);
+ start.setX(qRound(start.x()));
+ start.setY(qRound(start.y()));
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ QCOMPARE(pathview->currentIndex(), 0);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::creationContext()
+{
+ QQuickView canvas;
+ canvas.setGeometry(0,0,240,320);
+ canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
+ QVERIFY(rootItem);
+ QVERIFY(rootItem->property("count").toInt() > 0);
+
+ QQuickItem *item;
+ QVERIFY(item = findItem<QQuickItem>(rootItem, "listItem", 0));
+ QCOMPARE(item->property("text").toString(), QString("Hello!"));
+}
+
+// QTBUG-21320
+void tst_QQuickPathView::currentOffsetOnInsertion()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathline.qml")));
+ qApp->processEvents();
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setPreferredHighlightBegin(0.5);
+ pathview->setPreferredHighlightEnd(0.5);
+
+ QCOMPARE(pathview->count(), model.count());
+
+ model.addItem("item0", "0");
+
+ QCOMPARE(pathview->count(), model.count());
+
+ QQuickRectangle *item = 0;
+ QTRY_VERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 0));
+
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+
+ QPointF start = path->pointAt(0.5);
+ start = QPointF(qRound(start.x()), qRound(start.y()));
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(item->width()/2);
+ offset.setY(item->height()/2);
+ QCOMPARE(item->pos() + offset, start);
+
+ QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged()));
+
+ // insert an item at the beginning
+ model.insertItem(0, "item1", "1");
+ qApp->processEvents();
+
+ QCOMPARE(currentIndexSpy.count(), 1);
+
+ // currentIndex is now 1
+ QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
+
+ // verify that current item (item 1) is still at offset 0.5
+ QCOMPARE(item->pos() + offset, start);
+
+ // insert another item at the beginning
+ model.insertItem(0, "item2", "2");
+ qApp->processEvents();
+
+ QCOMPARE(currentIndexSpy.count(), 2);
+
+ // currentIndex is now 2
+ QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 2));
+
+ // verify that current item (item 2) is still at offset 0.5
+ QCOMPARE(item->pos() + offset, start);
+
+ // verify that remove before current maintains current item
+ model.removeItem(0);
+ qApp->processEvents();
+
+ QCOMPARE(currentIndexSpy.count(), 3);
+
+ // currentIndex is now 1
+ QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
+
+ // verify that current item (item 1) is still at offset 0.5
+ QCOMPARE(item->pos() + offset, start);
+
+ delete canvas;
+}
+
+void tst_QQuickPathView::asynchronous()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ canvas->setSource(TESTDATA("asyncloader.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootObject);
+
+ QQuickPathView *pathview = 0;
+ while (!pathview) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ pathview = rootObject->findChild<QQuickPathView*>("view");
+ }
+
+ // items will be created one at a time
+ for (int i = 0; i < 5; ++i) {
+ QVERIFY(findItem<QQuickItem>(pathview, "wrapper", i) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(pathview, "wrapper", i);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ // verify positioning
+ QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QTRY_COMPARE(firstItem->pos() + offset, start);
+ pathview->setOffset(1.0);
+
+ for (int i=0; i<5; i++) {
+ QQuickItem *curItem = findItem<QQuickItem>(pathview, "wrapper", i);
+ QPointF itemPos(path->pointAt(0.2 + i*0.2));
+ QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
+ }
+
+ delete canvas;
+}
+
+QQuickView *tst_QQuickPathView::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+ */
+template<typename T>
+T *tst_QQuickPathView::findItem(QQuickItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeExpression e(qmlContext(item), item, "index");
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+QList<T*> tst_QQuickPathView::findItems(QQuickItem *parent, const QString &objectName)
+{
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QQuickItem::children().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ items.append(static_cast<T*>(item));
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+}
+
+void tst_QQuickPathView::missingPercent()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("missingPercent.qml")));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj);
+ QCOMPARE(obj->attributeAt("_qfx_percent", 1.0), qreal(1.0));
+ delete obj;
+}
+
+
+QTEST_MAIN(tst_QQuickPathView)
+
+#include "tst_qquickpathview.moc"
diff --git a/tests/auto/declarative/qquickpincharea/data/pinchproperties.qml b/tests/auto/qtquick2/qquickpincharea/data/pinchproperties.qml
index 44d116184e..44d116184e 100644
--- a/tests/auto/declarative/qquickpincharea/data/pinchproperties.qml
+++ b/tests/auto/qtquick2/qquickpincharea/data/pinchproperties.qml
diff --git a/tests/auto/qtquick2/qquickpincharea/qquickpincharea.pro b/tests/auto/qtquick2/qquickpincharea/qquickpincharea.pro
new file mode 100644
index 0000000000..6e2ff59512
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpincharea/qquickpincharea.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickpincharea
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickpincharea.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/qtquick2/qquickpincharea/tst_qquickpincharea.cpp
new file mode 100644
index 0000000000..c4912c46f1
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpincharea/tst_qquickpincharea.cpp
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <private/qquickpincharea_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include "../../shared/util.h"
+
+class tst_QQuickPinchArea: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void pinchProperties();
+ void scale();
+ void pan();
+ void retouch();
+
+private:
+ QQuickView *createView();
+};
+void tst_QQuickPinchArea::initTestCase()
+{
+}
+
+void tst_QQuickPinchArea::cleanupTestCase()
+{
+
+}
+void tst_QQuickPinchArea::pinchProperties()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
+ QQuickPinch *pinch = pinchArea->pinch();
+ QVERIFY(pinchArea != 0);
+ QVERIFY(pinch != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == pinch->target());
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootItem != 0);
+ QSignalSpy targetSpy(pinch, SIGNAL(targetChanged()));
+ pinch->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+ pinch->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+
+ // axis
+ QCOMPARE(pinch->axis(), QQuickPinch::XandYAxis);
+ QSignalSpy axisSpy(pinch, SIGNAL(dragAxisChanged()));
+ pinch->setAxis(QQuickPinch::XAxis);
+ QCOMPARE(pinch->axis(), QQuickPinch::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+ pinch->setAxis(QQuickPinch::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+
+ // minimum and maximum drag properties
+ QSignalSpy xminSpy(pinch, SIGNAL(minimumXChanged()));
+ QSignalSpy xmaxSpy(pinch, SIGNAL(maximumXChanged()));
+ QSignalSpy yminSpy(pinch, SIGNAL(minimumYChanged()));
+ QSignalSpy ymaxSpy(pinch, SIGNAL(maximumYChanged()));
+
+ QCOMPARE(pinch->xmin(), 0.0);
+ QCOMPARE(pinch->xmax(), rootItem->width()-blackRect->width());
+ QCOMPARE(pinch->ymin(), 0.0);
+ QCOMPARE(pinch->ymax(), rootItem->height()-blackRect->height());
+
+ pinch->setXmin(10);
+ pinch->setXmax(10);
+ pinch->setYmin(10);
+ pinch->setYmax(10);
+
+ QCOMPARE(pinch->xmin(), 10.0);
+ QCOMPARE(pinch->xmax(), 10.0);
+ QCOMPARE(pinch->ymin(), 10.0);
+ QCOMPARE(pinch->ymax(), 10.0);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+
+ pinch->setXmin(10);
+ pinch->setXmax(10);
+ pinch->setYmin(10);
+ pinch->setYmax(10);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+
+ // minimum and maximum scale properties
+ QSignalSpy scaleMinSpy(pinch, SIGNAL(minimumScaleChanged()));
+ QSignalSpy scaleMaxSpy(pinch, SIGNAL(maximumScaleChanged()));
+
+ QCOMPARE(pinch->minimumScale(), 1.0);
+ QCOMPARE(pinch->maximumScale(), 2.0);
+
+ pinch->setMinimumScale(0.5);
+ pinch->setMaximumScale(1.5);
+
+ QCOMPARE(pinch->minimumScale(), 0.5);
+ QCOMPARE(pinch->maximumScale(), 1.5);
+
+ QCOMPARE(scaleMinSpy.count(),1);
+ QCOMPARE(scaleMaxSpy.count(),1);
+
+ pinch->setMinimumScale(0.5);
+ pinch->setMaximumScale(1.5);
+
+ QCOMPARE(scaleMinSpy.count(),1);
+ QCOMPARE(scaleMaxSpy.count(),1);
+
+ // minimum and maximum rotation properties
+ QSignalSpy rotMinSpy(pinch, SIGNAL(minimumRotationChanged()));
+ QSignalSpy rotMaxSpy(pinch, SIGNAL(maximumRotationChanged()));
+
+ QCOMPARE(pinch->minimumRotation(), 0.0);
+ QCOMPARE(pinch->maximumRotation(), 90.0);
+
+ pinch->setMinimumRotation(-90.0);
+ pinch->setMaximumRotation(45.0);
+
+ QCOMPARE(pinch->minimumRotation(), -90.0);
+ QCOMPARE(pinch->maximumRotation(), 45.0);
+
+ QCOMPARE(rotMinSpy.count(),1);
+ QCOMPARE(rotMaxSpy.count(),1);
+
+ pinch->setMinimumRotation(-90.0);
+ pinch->setMaximumRotation(45.0);
+
+ QCOMPARE(rotMinSpy.count(),1);
+ QCOMPARE(rotMaxSpy.count(),1);
+
+ delete canvas;
+}
+
+QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
+{
+ QTouchEvent::TouchPoint touchPoint(id);
+ touchPoint.setPos(i->mapFromScene(p));
+ touchPoint.setScreenPos(v->mapToGlobal(p));
+ touchPoint.setScenePos(p);
+ return touchPoint;
+}
+
+void tst_QQuickPinchArea::scale()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QVERIFY(canvas->rootObject() != 0);
+ qApp->processEvents();
+
+ QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
+ QQuickPinch *pinch = pinchArea->pinch();
+ QVERIFY(pinchArea != 0);
+ QVERIFY(pinch != 0);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+
+ QPoint p1(80, 80);
+ QPoint p2(100, 100);
+
+ QTest::touchEvent(canvas).press(0, p1, canvas);
+ QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1,canvas).move(1, p2,canvas);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1,canvas).move(1, p2,canvas);
+
+ QCOMPARE(root->property("scale").toReal(), 1.5);
+ QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
+ QCOMPARE(blackRect->scale(), 1.5);
+
+ // scale beyond bound
+ p1 -= QPoint(50,50);
+ p2 += QPoint(50,50);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(blackRect->scale(), 2.0);
+
+ QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
+
+ delete canvas;
+}
+
+void tst_QQuickPinchArea::pan()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QVERIFY(canvas->rootObject() != 0);
+ qApp->processEvents();
+
+ QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
+ QQuickPinch *pinch = pinchArea->pinch();
+ QVERIFY(pinchArea != 0);
+ QVERIFY(pinch != 0);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root != 0);
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+
+ QPoint p1(80, 80);
+ QPoint p2(100, 100);
+
+ QTest::touchEvent(canvas).press(0, p1, canvas);
+ QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
+ p1 += QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+
+ p1 += QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50
+
+ QCOMPARE(blackRect->x(), 60.0);
+ QCOMPARE(blackRect->y(), 60.0);
+
+ // pan x beyond bound
+ p1 += QPoint(100,100);
+ p2 += QPoint(100,100);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(blackRect->x(), 140.0);
+ QCOMPARE(blackRect->y(), 160.0);
+
+ QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
+
+ delete canvas;
+}
+
+// test pinch, release one point, touch again to continue pinch
+void tst_QQuickPinchArea::retouch()
+{
+ QQuickView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("pinchproperties.qml")));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QVERIFY(canvas->rootObject() != 0);
+ qApp->processEvents();
+
+ QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea");
+ QQuickPinch *pinch = pinchArea->pinch();
+ QVERIFY(pinchArea != 0);
+ QVERIFY(pinch != 0);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root != 0);
+
+ QSignalSpy startedSpy(pinchArea, SIGNAL(pinchStarted(QQuickPinchEvent *)));
+ QSignalSpy finishedSpy(pinchArea, SIGNAL(pinchFinished(QQuickPinchEvent *)));
+
+ // target
+ QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+
+ QPoint p1(80, 80);
+ QPoint p2(100, 100);
+
+ QTest::touchEvent(canvas).press(0, p1, canvas);
+ QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ QCOMPARE(startedSpy.count(), 1);
+
+ QCOMPARE(root->property("scale").toReal(), 1.5);
+ QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
+ QCOMPARE(blackRect->scale(), 1.5);
+
+ QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2);
+
+ QCOMPARE(startedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ QTest::touchEvent(canvas).stationary(0).release(1, p2, canvas);
+
+ QCOMPARE(startedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 1);
+
+ QTest::touchEvent(canvas).stationary(0).press(1, p2, canvas);
+ p1 -= QPoint(10,10);
+ p2 += QPoint(10,10);
+ QTest::touchEvent(canvas).move(0, p1, canvas).move(1, p2, canvas);
+
+ // Lifting and retouching results in onPinchStarted being called again
+ QCOMPARE(startedSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2);
+
+ QTest::touchEvent(canvas).release(0, p1, canvas).release(1, p2, canvas);
+
+ QCOMPARE(startedSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 1);
+
+ delete canvas;
+}
+
+
+QQuickView *tst_QQuickPinchArea::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ return canvas;
+}
+
+QTEST_MAIN(tst_QQuickPinchArea)
+
+#include "tst_qquickpincharea.moc"
diff --git a/tests/auto/declarative/qquickpositioners/data/allInvisible.qml b/tests/auto/qtquick2/qquickpositioners/data/allInvisible.qml
index 5894171434..5894171434 100644
--- a/tests/auto/declarative/qquickpositioners/data/allInvisible.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/allInvisible.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/attachedproperties-column.qml b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-column.qml
index 4c667aa205..4c667aa205 100644
--- a/tests/auto/declarative/qquickpositioners/data/attachedproperties-column.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-column.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/attachedproperties-dynamic.qml b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-dynamic.qml
index 894749dc16..894749dc16 100644
--- a/tests/auto/declarative/qquickpositioners/data/attachedproperties-dynamic.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-dynamic.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/attachedproperties-flow.qml b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-flow.qml
index e7f9a63e2a..e7f9a63e2a 100644
--- a/tests/auto/declarative/qquickpositioners/data/attachedproperties-flow.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-flow.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/attachedproperties-grid.qml b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-grid.qml
index 2094309b9f..2094309b9f 100644
--- a/tests/auto/declarative/qquickpositioners/data/attachedproperties-grid.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-grid.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/attachedproperties-row.qml b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-row.qml
index 212a26b431..212a26b431 100644
--- a/tests/auto/declarative/qquickpositioners/data/attachedproperties-row.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/attachedproperties-row.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/flow-testimplicitsize.qml b/tests/auto/qtquick2/qquickpositioners/data/flow-testimplicitsize.qml
index c32b78676c..c32b78676c 100644
--- a/tests/auto/declarative/qquickpositioners/data/flow-testimplicitsize.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/flow-testimplicitsize.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/flowtest-toptobottom.qml b/tests/auto/qtquick2/qquickpositioners/data/flowtest-toptobottom.qml
index a7d3ee13c7..a7d3ee13c7 100644
--- a/tests/auto/declarative/qquickpositioners/data/flowtest-toptobottom.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/flowtest-toptobottom.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/flowtest.qml b/tests/auto/qtquick2/qquickpositioners/data/flowtest.qml
index 40b042dd79..40b042dd79 100644
--- a/tests/auto/declarative/qquickpositioners/data/flowtest.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/flowtest.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/grid-animated.qml b/tests/auto/qtquick2/qquickpositioners/data/grid-animated.qml
index b8ee8f9a52..b8ee8f9a52 100644
--- a/tests/auto/declarative/qquickpositioners/data/grid-animated.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/grid-animated.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/grid-row-column-spacing.qml b/tests/auto/qtquick2/qquickpositioners/data/grid-row-column-spacing.qml
index 49bbd337e7..49bbd337e7 100644
--- a/tests/auto/declarative/qquickpositioners/data/grid-row-column-spacing.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/grid-row-column-spacing.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/grid-spacing.qml b/tests/auto/qtquick2/qquickpositioners/data/grid-spacing.qml
index 535a39037f..535a39037f 100644
--- a/tests/auto/declarative/qquickpositioners/data/grid-spacing.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/grid-spacing.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/grid-toptobottom.qml b/tests/auto/qtquick2/qquickpositioners/data/grid-toptobottom.qml
index 45559aab5d..45559aab5d 100644
--- a/tests/auto/declarative/qquickpositioners/data/grid-toptobottom.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/grid-toptobottom.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/gridtest.qml b/tests/auto/qtquick2/qquickpositioners/data/gridtest.qml
index 50bec1377b..50bec1377b 100644
--- a/tests/auto/declarative/qquickpositioners/data/gridtest.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/gridtest.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/gridzerocolumns.qml b/tests/auto/qtquick2/qquickpositioners/data/gridzerocolumns.qml
index a252f279c3..a252f279c3 100644
--- a/tests/auto/declarative/qquickpositioners/data/gridzerocolumns.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/gridzerocolumns.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/horizontal-animated-disabled.qml b/tests/auto/qtquick2/qquickpositioners/data/horizontal-animated-disabled.qml
index 8723ffc78f..8723ffc78f 100644
--- a/tests/auto/declarative/qquickpositioners/data/horizontal-animated-disabled.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/horizontal-animated-disabled.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/horizontal-animated.qml b/tests/auto/qtquick2/qquickpositioners/data/horizontal-animated.qml
index a88c26b66c..a88c26b66c 100644
--- a/tests/auto/declarative/qquickpositioners/data/horizontal-animated.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/horizontal-animated.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/horizontal-spacing.qml b/tests/auto/qtquick2/qquickpositioners/data/horizontal-spacing.qml
index c6ff75ac6b..c6ff75ac6b 100644
--- a/tests/auto/declarative/qquickpositioners/data/horizontal-spacing.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/horizontal-spacing.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/horizontal.qml b/tests/auto/qtquick2/qquickpositioners/data/horizontal.qml
index 235ee78c9b..235ee78c9b 100644
--- a/tests/auto/declarative/qquickpositioners/data/horizontal.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/horizontal.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/propertychangestest.qml b/tests/auto/qtquick2/qquickpositioners/data/propertychangestest.qml
index c9fd62b012..c9fd62b012 100644
--- a/tests/auto/declarative/qquickpositioners/data/propertychangestest.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/propertychangestest.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/rectangleComponent.qml b/tests/auto/qtquick2/qquickpositioners/data/rectangleComponent.qml
index de1bb99593..de1bb99593 100644
--- a/tests/auto/declarative/qquickpositioners/data/rectangleComponent.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/rectangleComponent.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/repeatertest.qml b/tests/auto/qtquick2/qquickpositioners/data/repeatertest.qml
index d90e1cf160..d90e1cf160 100644
--- a/tests/auto/declarative/qquickpositioners/data/repeatertest.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/repeatertest.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/vertical-animated.qml b/tests/auto/qtquick2/qquickpositioners/data/vertical-animated.qml
index ecf593cd70..ecf593cd70 100644
--- a/tests/auto/declarative/qquickpositioners/data/vertical-animated.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/vertical-animated.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/vertical-spacing.qml b/tests/auto/qtquick2/qquickpositioners/data/vertical-spacing.qml
index 7087961651..7087961651 100644
--- a/tests/auto/declarative/qquickpositioners/data/vertical-spacing.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/vertical-spacing.qml
diff --git a/tests/auto/declarative/qquickpositioners/data/vertical.qml b/tests/auto/qtquick2/qquickpositioners/data/vertical.qml
index 0c3a81f008..0c3a81f008 100644
--- a/tests/auto/declarative/qquickpositioners/data/vertical.qml
+++ b/tests/auto/qtquick2/qquickpositioners/data/vertical.qml
diff --git a/tests/auto/qtquick2/qquickpositioners/qquickpositioners.pro b/tests/auto/qtquick2/qquickpositioners/qquickpositioners.pro
new file mode 100644
index 0000000000..5931b9ba3a
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpositioners/qquickpositioners.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+TARGET = tst_qquickpositioners
+SOURCES += tst_qquickpositioners.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/qtquick2/qquickpositioners/tst_qquickpositioners.cpp
new file mode 100644
index 0000000000..867de8cb9e
--- /dev/null
+++ b/tests/auto/qtquick2/qquickpositioners/tst_qquickpositioners.cpp
@@ -0,0 +1,1473 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <private/qlistmodelinterface_p.h>
+#include <QtQuick/qquickview.h>
+#include <qdeclarativeengine.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquickpositioners_p.h>
+#include <QtQuick/private/qdeclarativetransition_p.h>
+#include <private/qquickitem_p.h>
+#include <qdeclarativeexpression.h>
+#include "../../shared/util.h"
+
+class tst_qquickpositioners : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickpositioners();
+
+private slots:
+ void test_horizontal();
+ void test_horizontal_rtl();
+ void test_horizontal_spacing();
+ void test_horizontal_spacing_rightToLeft();
+ void test_horizontal_animated();
+ void test_horizontal_animated_rightToLeft();
+ void test_horizontal_animated_disabled();
+ void test_vertical();
+ void test_vertical_spacing();
+ void test_vertical_animated();
+ void test_grid();
+ void test_grid_topToBottom();
+ void test_grid_rightToLeft();
+ void test_grid_spacing();
+ void test_grid_row_column_spacing();
+ void test_grid_animated();
+ void test_grid_animated_rightToLeft();
+ void test_grid_zero_columns();
+ void test_propertychanges();
+ void test_repeater();
+ void test_flow();
+ void test_flow_rightToLeft();
+ void test_flow_topToBottom();
+ void test_flow_resize();
+ void test_flow_resize_rightToLeft();
+ void test_flow_implicit_resize();
+ void test_conflictinganchors();
+ void test_mirroring();
+ void test_allInvisible();
+ void test_attachedproperties();
+ void test_attachedproperties_data();
+ void test_attachedproperties_dynamic();
+
+private:
+ QQuickView *createView(const QString &filename, bool wait=true);
+};
+
+tst_qquickpositioners::tst_qquickpositioners()
+{
+}
+
+void tst_qquickpositioners::test_horizontal()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QCOMPARE(row->width(), 110.0);
+ QCOMPARE(row->height(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_rtl()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 60.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 40.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 0.0);
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QCOMPARE(row->width(), 110.0);
+ QCOMPARE(row->height(), 50.0);
+
+ // Change the width of the row and check that items stay to the right
+ row->setWidth(200);
+ QTRY_COMPARE(one->x(), 150.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 130.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 0.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_spacing()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal-spacing.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 0.0);
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QCOMPARE(row->width(), 130.0);
+ QCOMPARE(row->height(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal-spacing.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 80.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 00.0);
+ QCOMPARE(three->y(), 0.0);
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QCOMPARE(row->width(), 130.0);
+ QCOMPARE(row->height(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_animated()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal-animated.qml"), false);
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ //Note that they animate in
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->x(), -100.0);
+
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+ QCOMPARE(row->width(), 100.0);
+ QCOMPARE(row->height(), 50.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 50.0);
+ QTRY_COMPARE(three->y(), 0.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+ QTRY_COMPARE(row->width(), 150.0);
+ QTRY_COMPARE(row->height(), 50.0);
+
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
+ QVERIFY(three->x() >= 50.0 && three->x() < 100.0);
+
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(three->x(), 100.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal-animated.qml"), false);
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ //Note that they animate in
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(three->x(), -100.0);
+
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+ QCOMPARE(row->width(), 100.0);
+ QCOMPARE(row->height(), 50.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->x(), 50.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 0.0);
+ QTRY_COMPARE(three->y(), 0.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+
+ // New size should propagate after visible change
+ QTRY_COMPARE(row->width(), 150.0);
+ QTRY_COMPARE(row->height(), 50.0);
+
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(one->x() >= 50.0 && one->x() < 100);
+ QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
+
+ QTRY_COMPARE(one->x(), 100.0);
+ QTRY_COMPARE(two->x(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_horizontal_animated_disabled()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontal-animated-disabled.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
+ QVERIFY(row);
+
+ qApp->processEvents();
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->isVisible(), false);
+ QCOMPARE(two->x(), -100.0);//Not 'in' yet
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 0.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QTRY_COMPARE(row->width(), 150.0);
+ QTRY_COMPARE(row->height(), 50.0);
+
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(three->x(), 100.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_vertical()
+{
+ QQuickView *canvas = createView(TESTDATA("vertical.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
+
+ QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
+ QVERIFY(column);
+ QCOMPARE(column->height(), 80.0);
+ QCOMPARE(column->width(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_vertical_spacing()
+{
+ QQuickView *canvas = createView(TESTDATA("vertical-spacing.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 80.0);
+
+ QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
+ QCOMPARE(column->height(), 100.0);
+ QCOMPARE(column->width(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_vertical_animated()
+{
+ QQuickView *canvas = createView(TESTDATA("vertical-animated.qml"), false);
+
+ //Note that they animate in
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->y(), -100.0);
+
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
+ QVERIFY(column);
+ QCOMPARE(column->height(), 100.0);
+ QCOMPARE(column->width(), 50.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);//Not 'in' yet
+ QTRY_COMPARE(two->x(), 0.0);
+ QTRY_COMPARE(three->y(), 50.0);
+ QTRY_COMPARE(three->x(), 0.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QTRY_COMPARE(two->isVisible(), true);
+ QTRY_COMPARE(column->height(), 150.0);
+ QTRY_COMPARE(column->width(), 50.0);
+ QTest::qWait(0);//Let the animation start
+ QVERIFY(two->y() >= -100.0 && two->y() < 50.0);
+ QVERIFY(three->y() >= 50.0 && three->y() < 100.0);
+
+ QTRY_COMPARE(two->y(), 50.0);
+ QTRY_COMPARE(three->y(), 100.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid()
+{
+ QQuickView *canvas = createView(TESTDATA("gridtest.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
+ QCOMPARE(grid->flow(), QQuickGrid::LeftToRight);
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_topToBottom()
+{
+ QQuickView *canvas = createView(TESTDATA("grid-toptobottom.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 100.0);
+ QCOMPARE(four->x(), 50.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
+ QCOMPARE(grid->flow(), QQuickGrid::TopToBottom);
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 120.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("gridtest.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 50.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 30.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 50.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 40.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
+ QCOMPARE(grid->layoutDirection(), Qt::RightToLeft);
+ QCOMPARE(grid->width(), 100.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ // Change the width of the grid and check that items stay to the right
+ grid->setWidth(200);
+ QTRY_COMPARE(one->x(), 150.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 130.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 100.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 150.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 140.0);
+ QCOMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_spacing()
+{
+ QQuickView *canvas = createView(TESTDATA("grid-spacing.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 54.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 54.0);
+ QCOMPARE(five->x(), 54.0);
+ QCOMPARE(five->y(), 54.0);
+
+ QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
+ QCOMPARE(grid->width(), 128.0);
+ QCOMPARE(grid->height(), 104.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_row_column_spacing()
+{
+ QQuickView *canvas = createView(TESTDATA("grid-row-column-spacing.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 61.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 92.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 57.0);
+ QCOMPARE(five->x(), 61.0);
+ QCOMPARE(five->y(), 57.0);
+
+ QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
+ QCOMPARE(grid->width(), 142.0);
+ QCOMPARE(grid->height(), 107.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_animated()
+{
+ QQuickView *canvas = createView(TESTDATA("grid-animated.qml"), false);
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ //Note that all animate in
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+ QCOMPARE(three->y(), -100.0);
+
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QCOMPARE(four->x(), -100.0);
+ QCOMPARE(four->y(), -100.0);
+
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+ QCOMPARE(five->x(), -100.0);
+ QCOMPARE(five->y(), -100.0);
+
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
+ QVERIFY(grid);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);
+ QTRY_COMPARE(two->x(), -100.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(three->x(), 50.0);
+ QTRY_COMPARE(four->y(), 0.0);
+ QTRY_COMPARE(four->x(), 100.0);
+ QTRY_COMPARE(five->y(), 50.0);
+ QTRY_COMPARE(five->x(), 0.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 100.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 0.0);
+ QCOMPARE(five->y(), 50.0);
+ //Let the animation complete
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(three->x(), 100.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(four->x(), 0.0);
+ QTRY_COMPARE(four->y(), 50.0);
+ QTRY_COMPARE(five->x(), 50.0);
+ QTRY_COMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_animated_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("grid-animated.qml"), false);
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ //Note that all animate in
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QCOMPARE(one->x(), -100.0);
+ QCOMPARE(one->y(), -100.0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QCOMPARE(three->x(), -100.0);
+ QCOMPARE(three->y(), -100.0);
+
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QCOMPARE(four->x(), -100.0);
+ QCOMPARE(four->y(), -100.0);
+
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+ QCOMPARE(five->x(), -100.0);
+ QCOMPARE(five->y(), -100.0);
+
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
+ QVERIFY(grid);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+
+ //QTRY_COMPARE used instead of waiting for the expected time of animation completion
+ //Note that this means the duration of the animation is NOT tested
+
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(one->x(), 100.0);
+ QTRY_COMPARE(two->isVisible(), false);
+ QTRY_COMPARE(two->y(), -100.0);
+ QTRY_COMPARE(two->x(), -100.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(three->x(), 50.0);
+ QTRY_COMPARE(four->y(), 0.0);
+ QTRY_COMPARE(four->x(), 0.0);
+ QTRY_COMPARE(five->y(), 50.0);
+ QTRY_COMPARE(five->x(), 100.0);
+
+ //Add 'two'
+ two->setVisible(true);
+ QCOMPARE(two->isVisible(), true);
+ QCOMPARE(grid->width(), 150.0);
+ QCOMPARE(grid->height(), 100.0);
+ QTest::qWait(0);//Let the animation start
+ QCOMPARE(two->x(), -100.0);
+ QCOMPARE(two->y(), -100.0);
+ QCOMPARE(one->x(), 100.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 100.0);
+ QCOMPARE(five->y(), 50.0);
+ //Let the animation complete
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(one->x(), 100.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(three->x(), 0.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(four->x(), 100.0);
+ QTRY_COMPARE(four->y(), 50.0);
+ QTRY_COMPARE(five->x(), 50.0);
+ QTRY_COMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_grid_zero_columns()
+{
+ QQuickView *canvas = createView(TESTDATA("gridzerocolumns.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 120.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 0.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
+ QCOMPARE(grid->width(), 170.0);
+ QCOMPARE(grid->height(), 60.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_propertychanges()
+{
+ QQuickView *canvas = createView(TESTDATA("propertychangestest.qml"));
+
+ QQuickGrid *grid = qobject_cast<QQuickGrid*>(canvas->rootObject());
+ QVERIFY(grid != 0);
+ QDeclarativeTransition *rowTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("rowTransition");
+ QDeclarativeTransition *columnTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("columnTransition");
+
+ QSignalSpy addSpy(grid, SIGNAL(addChanged()));
+ QSignalSpy moveSpy(grid, SIGNAL(moveChanged()));
+ QSignalSpy columnsSpy(grid, SIGNAL(columnsChanged()));
+ QSignalSpy rowsSpy(grid, SIGNAL(rowsChanged()));
+
+ QVERIFY(grid);
+ QVERIFY(rowTransition);
+ QVERIFY(columnTransition);
+ QCOMPARE(grid->add(), columnTransition);
+ QCOMPARE(grid->move(), columnTransition);
+ QCOMPARE(grid->columns(), 4);
+ QCOMPARE(grid->rows(), -1);
+
+ grid->setAdd(rowTransition);
+ grid->setMove(rowTransition);
+ QCOMPARE(grid->add(), rowTransition);
+ QCOMPARE(grid->move(), rowTransition);
+ QCOMPARE(addSpy.count(),1);
+ QCOMPARE(moveSpy.count(),1);
+
+ grid->setAdd(rowTransition);
+ grid->setMove(rowTransition);
+ QCOMPARE(addSpy.count(),1);
+ QCOMPARE(moveSpy.count(),1);
+
+ grid->setAdd(0);
+ grid->setMove(0);
+ QCOMPARE(addSpy.count(),2);
+ QCOMPARE(moveSpy.count(),2);
+
+ grid->setColumns(-1);
+ grid->setRows(3);
+ QCOMPARE(grid->columns(), -1);
+ QCOMPARE(grid->rows(), 3);
+ QCOMPARE(columnsSpy.count(),1);
+ QCOMPARE(rowsSpy.count(),1);
+
+ grid->setColumns(-1);
+ grid->setRows(3);
+ QCOMPARE(columnsSpy.count(),1);
+ QCOMPARE(rowsSpy.count(),1);
+
+ grid->setColumns(2);
+ grid->setRows(2);
+ QCOMPARE(columnsSpy.count(),2);
+ QCOMPARE(rowsSpy.count(),2);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_repeater()
+{
+ QQuickView *canvas = createView(TESTDATA("repeatertest.qml"));
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 100.0);
+ QCOMPARE(three->y(), 0.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow()
+{
+ QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 70.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 70.0);
+
+ QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
+ QVERIFY(flow);
+ QCOMPARE(flow->width(), 90.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 40.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 20.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 40.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 40.0);
+ QCOMPARE(four->y(), 70.0);
+ QCOMPARE(five->x(), 30.0);
+ QCOMPARE(five->y(), 70.0);
+
+ QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
+ QVERIFY(flow);
+ QCOMPARE(flow->width(), 90.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow_topToBottom()
+{
+ QQuickView *canvas = createView(TESTDATA("flowtest-toptobottom.qml"));
+
+ canvas->rootObject()->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 100.0);
+ QCOMPARE(four->y(), 00.0);
+ QCOMPARE(five->x(), 100.0);
+ QCOMPARE(five->y(), 50.0);
+
+ QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
+ QVERIFY(flow);
+ QCOMPARE(flow->height(), 90.0);
+ QCOMPARE(flow->width(), 150.0);
+
+ canvas->rootObject()->setProperty("testRightToLeft", true);
+
+ QVERIFY(flow);
+ QCOMPARE(flow->height(), 90.0);
+ QCOMPARE(flow->width(), 150.0);
+
+ QCOMPARE(one->x(), 100.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 80.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 50.0);
+ QCOMPARE(three->y(), 50.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 0.0);
+ QCOMPARE(five->x(), 40.0);
+ QCOMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow_resize()
+{
+ QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root);
+ root->setWidth(125);
+ root->setProperty("testRightToLeft", false);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QVERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 70.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(four->x(), 0.0);
+ QTRY_COMPARE(four->y(), 50.0);
+ QTRY_COMPARE(five->x(), 50.0);
+ QTRY_COMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow_resize_rightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("flowtest.qml"));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root);
+ root->setWidth(125);
+ root->setProperty("testRightToLeft", true);
+
+ QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
+ QTRY_VERIFY(one != 0);
+ QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
+ QVERIFY(two != 0);
+ QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
+ QVERIFY(three != 0);
+ QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
+ QVERIFY(four != 0);
+ QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 75.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 55.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 5.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 75.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 65.0);
+ QCOMPARE(five->y(), 50.0);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_flow_implicit_resize()
+{
+ QQuickView *canvas = createView(TESTDATA("flow-testimplicitsize.qml"));
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickFlow *flow = canvas->rootObject()->findChild<QQuickFlow*>("flow");
+ QVERIFY(flow != 0);
+
+ QCOMPARE(flow->width(), 100.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ canvas->rootObject()->setProperty("flowLayout", 0);
+ QCOMPARE(flow->flow(), QQuickFlow::LeftToRight);
+ QCOMPARE(flow->width(), 220.0);
+ QCOMPARE(flow->height(), 50.0);
+
+ canvas->rootObject()->setProperty("flowLayout", 1);
+ QCOMPARE(flow->flow(), QQuickFlow::TopToBottom);
+ QCOMPARE(flow->width(), 100.0);
+ QCOMPARE(flow->height(), 120.0);
+
+ canvas->rootObject()->setProperty("flowLayout", 2);
+ QCOMPARE(flow->layoutDirection(), Qt::RightToLeft);
+ QCOMPARE(flow->width(), 220.0);
+ QCOMPARE(flow->height(), 50.0);
+
+ delete canvas;
+}
+
+QString warningMessage;
+
+void interceptWarnings(QtMsgType type, const char *msg)
+{
+ Q_UNUSED( type );
+ warningMessage = msg;
+}
+
+void tst_qquickpositioners::test_conflictinganchors()
+{
+ QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings);
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine);
+
+ component.setData("import QtQuick 2.0\nColumn { Item {} }", QUrl::fromLocalFile(""));
+ QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ delete item;
+
+ component.setData("import QtQuick 2.0\nRow { Item {} }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ delete item;
+
+ component.setData("import QtQuick 2.0\nGrid { Item {} }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ delete item;
+
+ component.setData("import QtQuick 2.0\nFlow { Item {} }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ delete item;
+
+ component.setData("import QtQuick 2.0\nColumn { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nColumn { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nColumn { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nRow { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nRow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nRow { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QVERIFY(warningMessage.isEmpty());
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nGrid { Item { anchors.horizontalCenter: parent.horizontalCenter } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nGrid { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
+ warningMessage.clear();
+ delete item;
+
+ component.setData("import QtQuick 2.0\nFlow { Item { anchors.verticalCenter: parent.verticalCenter } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
+ delete item;
+
+ component.setData("import QtQuick 2.0\nFlow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
+ item = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(item);
+ QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
+ qInstallMsgHandler(oldMsgHandler);
+ delete item;
+}
+
+void tst_qquickpositioners::test_mirroring()
+{
+ QList<QString> qmlFiles;
+ qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
+ QList<QString> objectNames;
+ objectNames << "one" << "two" << "three" << "four" << "five";
+
+ foreach (const QString qmlFile, qmlFiles) {
+ QQuickView *canvasA = createView(TESTDATA(qmlFile));
+ QQuickItem *rootA = qobject_cast<QQuickItem*>(canvasA->rootObject());
+
+ QQuickView *canvasB = createView(TESTDATA(qmlFile));
+ QQuickItem *rootB = qobject_cast<QQuickItem*>(canvasB->rootObject());
+
+ rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
+
+ // LTR != RTL
+ foreach (const QString objectName, objectNames) {
+ // horizontal.qml only has three items
+ if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ break;
+ QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
+ QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
+ QTRY_VERIFY(itemA->x() != itemB->x());
+ }
+
+ QQuickItemPrivate* rootPrivateB = QQuickItemPrivate::get(rootB);
+
+ rootPrivateB->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
+ rootPrivateB->isMirrorImplicit = false;
+ rootPrivateB->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
+ rootPrivateB->resolveLayoutMirror();
+
+ // RTL == mirror
+ foreach (const QString objectName, objectNames) {
+ // horizontal.qml only has three items
+ if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ break;
+ QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
+ QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
+ QTRY_COMPARE(itemA->x(), itemB->x());
+ }
+
+ rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
+ rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
+
+ // LTR == RTL + mirror
+ foreach (const QString objectName, objectNames) {
+ // horizontal.qml only has three items
+ if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+ break;
+ QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
+ QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
+ QTRY_COMPARE(itemA->x(), itemB->x());
+ }
+ delete canvasA;
+ delete canvasB;
+ }
+}
+
+void tst_qquickpositioners::test_allInvisible()
+{
+ //QTBUG-19361
+ QQuickView *canvas = createView(TESTDATA("allInvisible.qml"));
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(root);
+
+ QQuickRow *row = canvas->rootObject()->findChild<QQuickRow*>("row");
+ QVERIFY(row != 0);
+ QVERIFY(row->width() == 0);
+ QVERIFY(row->height() == 0);
+ QQuickColumn *column = canvas->rootObject()->findChild<QQuickColumn*>("column");
+ QVERIFY(column != 0);
+ QVERIFY(column->width() == 0);
+ QVERIFY(column->height() == 0);
+}
+
+void tst_qquickpositioners::test_attachedproperties()
+{
+ QFETCH(QString, filename);
+
+ QQuickView *canvas = createView(filename);
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickRectangle *greenRect = canvas->rootObject()->findChild<QQuickRectangle *>("greenRect");
+ QVERIFY(greenRect != 0);
+
+ int posIndex = greenRect->property("posIndex").toInt();
+ QVERIFY(posIndex == 0);
+ bool isFirst = greenRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == true);
+ bool isLast = greenRect->property("isLastItem").toBool();
+ QVERIFY(isLast == false);
+
+ QQuickRectangle *yellowRect = canvas->rootObject()->findChild<QQuickRectangle *>("yellowRect");
+ QVERIFY(yellowRect != 0);
+
+ posIndex = yellowRect->property("posIndex").toInt();
+ QVERIFY(posIndex == -1);
+ isFirst = yellowRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = yellowRect->property("isLastItem").toBool();
+ QVERIFY(isLast == false);
+
+ yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
+
+ posIndex = yellowRect->property("posIndex").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = yellowRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = yellowRect->property("isLastItem").toBool();
+ QVERIFY(isLast == true);
+
+ delete canvas;
+}
+
+void tst_qquickpositioners::test_attachedproperties_data()
+{
+ QTest::addColumn<QString>("filename");
+
+ QTest::newRow("column") << TESTDATA("attachedproperties-column.qml");
+ QTest::newRow("row") << TESTDATA("attachedproperties-row.qml");
+ QTest::newRow("grid") << TESTDATA("attachedproperties-grid.qml");
+ QTest::newRow("flow") << TESTDATA("attachedproperties-flow.qml");
+}
+
+void tst_qquickpositioners::test_attachedproperties_dynamic()
+{
+ QQuickView *canvas = createView(TESTDATA("attachedproperties-dynamic.qml"));
+ QVERIFY(canvas->rootObject() != 0);
+
+ QQuickRow *row = canvas->rootObject()->findChild<QQuickRow *>("pos");
+ QVERIFY(row != 0);
+
+ QQuickRectangle *rect0 = canvas->rootObject()->findChild<QQuickRectangle *>("rect0");
+ QVERIFY(rect0 != 0);
+
+ int posIndex = rect0->property("index").toInt();
+ QVERIFY(posIndex == 0);
+ bool isFirst = rect0->property("firstItem").toBool();
+ QVERIFY(isFirst == true);
+ bool isLast = rect0->property("lastItem").toBool();
+ QVERIFY(isLast == false);
+
+ QQuickRectangle *rect1 = canvas->rootObject()->findChild<QQuickRectangle *>("rect1");
+ QVERIFY(rect1 != 0);
+
+ posIndex = rect1->property("index").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = rect1->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect1->property("lastItem").toBool();
+ QVERIFY(isLast == true);
+
+ row->metaObject()->invokeMethod(row, "createSubRect");
+
+ QTRY_VERIFY(rect1->property("index").toInt() == 1);
+ QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
+ QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
+
+ QQuickRectangle *rect2 = canvas->rootObject()->findChild<QQuickRectangle *>("rect2");
+ QVERIFY(rect2 != 0);
+
+ posIndex = rect2->property("index").toInt();
+ QVERIFY(posIndex == 2);
+ isFirst = rect2->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect2->property("lastItem").toBool();
+ QVERIFY(isLast == true);
+
+ row->metaObject()->invokeMethod(row, "destroySubRect");
+
+ qApp->processEvents(QEventLoop::DeferredDeletion);
+
+ QTRY_VERIFY(rect1->property("index").toInt() == 1);
+ QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
+ QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
+
+ delete canvas;
+}
+
+QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait)
+{
+ QQuickView *canvas = new QQuickView(0);
+
+ canvas->setSource(QUrl::fromLocalFile(filename));
+ canvas->show();
+ if (wait)
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
+
+ return canvas;
+}
+
+
+QTEST_MAIN(tst_qquickpositioners)
+
+#include "tst_qquickpositioners.moc"
diff --git a/tests/auto/declarative/qquickrepeater/data/asyncloader.qml b/tests/auto/qtquick2/qquickrepeater/data/asyncloader.qml
index 82094e2666..82094e2666 100644
--- a/tests/auto/declarative/qquickrepeater/data/asyncloader.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/asyncloader.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/initparent.qml b/tests/auto/qtquick2/qquickrepeater/data/initparent.qml
index e6571f09d3..e6571f09d3 100644
--- a/tests/auto/declarative/qquickrepeater/data/initparent.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/initparent.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/intmodel.qml b/tests/auto/qtquick2/qquickrepeater/data/intmodel.qml
index 30a650dd52..30a650dd52 100644
--- a/tests/auto/declarative/qquickrepeater/data/intmodel.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/intmodel.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/itemlist.qml b/tests/auto/qtquick2/qquickrepeater/data/itemlist.qml
index 174bfd4d18..174bfd4d18 100644
--- a/tests/auto/declarative/qquickrepeater/data/itemlist.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/itemlist.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/modelChanged.qml b/tests/auto/qtquick2/qquickrepeater/data/modelChanged.qml
index 23af127e79..23af127e79 100644
--- a/tests/auto/declarative/qquickrepeater/data/modelChanged.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/modelChanged.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/objlist.qml b/tests/auto/qtquick2/qquickrepeater/data/objlist.qml
index c49d5926e5..c49d5926e5 100644
--- a/tests/auto/declarative/qquickrepeater/data/objlist.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/objlist.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/properties.qml b/tests/auto/qtquick2/qquickrepeater/data/properties.qml
index 035431c784..035431c784 100644
--- a/tests/auto/declarative/qquickrepeater/data/properties.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/properties.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/repeater1.qml b/tests/auto/qtquick2/qquickrepeater/data/repeater1.qml
index 596dc9131e..596dc9131e 100644
--- a/tests/auto/declarative/qquickrepeater/data/repeater1.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/repeater1.qml
diff --git a/tests/auto/declarative/qquickrepeater/data/repeater2.qml b/tests/auto/qtquick2/qquickrepeater/data/repeater2.qml
index 691fbda1e5..691fbda1e5 100644
--- a/tests/auto/declarative/qquickrepeater/data/repeater2.qml
+++ b/tests/auto/qtquick2/qquickrepeater/data/repeater2.qml
diff --git a/tests/auto/qtquick2/qquickrepeater/qquickrepeater.pro b/tests/auto/qtquick2/qquickrepeater/qquickrepeater.pro
new file mode 100644
index 0000000000..7e740f98aa
--- /dev/null
+++ b/tests/auto/qtquick2/qquickrepeater/qquickrepeater.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickrepeater
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickrepeater.cpp
+
+testFiles.files = data
+testFiles.path = .
+DEPLOYMENT += testFiles
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/qtquick2/qquickrepeater/tst_qquickrepeater.cpp
new file mode 100644
index 0000000000..1d6af452e4
--- /dev/null
+++ b/tests/auto/qtquick2/qquickrepeater/tst_qquickrepeater.cpp
@@ -0,0 +1,764 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <private/qlistmodelinterface_p.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtQuick/qquickview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
+#include <private/qquickrepeater_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+
+#include "../../shared/util.h"
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(TESTDATA(filename));
+}
+
+class tst_QQuickRepeater : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickRepeater();
+
+private slots:
+ void numberModel();
+ void objectList();
+ void stringList();
+ void dataModel_adding();
+ void dataModel_removing();
+ void dataModel_changes();
+ void itemModel();
+ void resetModel();
+ void modelChanged();
+ void properties();
+ void asynchronous();
+ void initParent();
+
+private:
+ QQuickView *createView();
+ template<typename T>
+ T *findItem(QObject *parent, const QString &objectName, int index);
+ template<typename T>
+ T *findItem(QObject *parent, const QString &id);
+};
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool error READ error WRITE setError)
+ Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
+
+public:
+ TestObject() : QObject(), mError(true), mUseModel(false) {}
+
+ bool error() const { return mError; }
+ void setError(bool err) { mError = err; }
+
+ bool useModel() const { return mUseModel; }
+ void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
+
+signals:
+ void useModelChanged();
+
+private:
+ bool mError;
+ bool mUseModel;
+};
+
+class TestModel : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void moveItem(int from, int to) {
+ emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
+ list.move(from, to);
+ emit endMoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+tst_QQuickRepeater::tst_QQuickRepeater()
+{
+}
+
+void tst_QQuickRepeater::numberModel()
+{
+ QQuickView *canvas = createView();
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", 5);
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(TEST_FILE("intmodel.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
+
+ QVERIFY(!repeater->itemAt(-1));
+ for (int i=0; i<repeater->count(); i++)
+ QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
+ QVERIFY(!repeater->itemAt(repeater->count()));
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ delete testObject;
+ delete canvas;
+}
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int idx READ idx CONSTANT)
+public:
+ MyObject(int i) : QObject(), m_idx(i) {}
+
+ int idx() const { return m_idx; }
+
+ int m_idx;
+};
+
+void tst_QQuickRepeater::objectList()
+{
+ QQuickView *canvas = createView();
+ QObjectList data;
+ for (int i=0; i<100; i++)
+ data << new MyObject(i);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", QVariant::fromValue(data));
+
+ canvas->setSource(TEST_FILE("objlist.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
+ QCOMPARE(repeater->property("instantiated").toInt(), 100);
+
+ QVERIFY(!repeater->itemAt(-1));
+ for (int i=0; i<data.count(); i++)
+ QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
+ QVERIFY(!repeater->itemAt(data.count()));
+
+ QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
+ QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
+ ctxt->setContextProperty("testData", QVariant::fromValue(data));
+ QCOMPARE(addedSpy.count(), data.count());
+ QCOMPARE(removedSpy.count(), data.count());
+
+ qDeleteAll(data);
+ delete canvas;
+}
+
+/*
+The Repeater element creates children at its own position in its parent's
+stacking order. In this test we insert a repeater between two other Text
+elements to test this.
+*/
+void tst_QQuickRepeater::stringList()
+{
+ QQuickView *canvas = createView();
+
+ QStringList data;
+ data << "One";
+ data << "Two";
+ data << "Three";
+ data << "Four";
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", data);
+
+ canvas->setSource(TEST_FILE("repeater1.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->childItems().count(), data.count() + 3);
+
+ bool saw_repeater = false;
+ for (int i = 0; i < container->childItems().count(); ++i) {
+
+ if (i == 0) {
+ QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), QLatin1String("Zero"));
+ } else if (i == container->childItems().count() - 2) {
+ // The repeater itself
+ QQuickRepeater *rep = qobject_cast<QQuickRepeater*>(container->childItems().at(i));
+ QCOMPARE(rep, repeater);
+ saw_repeater = true;
+ continue;
+ } else if (i == container->childItems().count() - 1) {
+ QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), QLatin1String("Last"));
+ } else {
+ QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), data.at(i-1));
+ }
+ }
+ QVERIFY(saw_repeater);
+
+ delete canvas;
+}
+
+void tst_QQuickRepeater::dataModel_adding()
+{
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel testModel;
+ ctxt->setContextProperty("testData", &testModel);
+ canvas->setSource(TEST_FILE("repeater2.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+
+ QVERIFY(!repeater->itemAt(0));
+
+ QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
+ QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
+
+ // add to empty model
+ testModel.addItem("two", "2");
+ QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(addedSpy.count(), 1);
+ QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
+ QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
+ addedSpy.clear();
+
+ // insert at start
+ testModel.insertItem(0, "one", "1");
+ QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(addedSpy.count(), 1);
+ QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
+ QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
+ addedSpy.clear();
+
+ // insert at end
+ testModel.insertItem(2, "four", "4");
+ QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(addedSpy.count(), 1);
+ QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
+ QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
+ addedSpy.clear();
+
+ // insert in middle
+ testModel.insertItem(2, "three", "3");
+ QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(addedSpy.count(), 1);
+ QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
+ QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
+ addedSpy.clear();
+
+ delete testObject;
+ addedSpy.clear();
+ countSpy.clear();
+ delete canvas;
+}
+
+void tst_QQuickRepeater::dataModel_removing()
+{
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel testModel;
+ testModel.addItem("one", "1");
+ testModel.addItem("two", "2");
+ testModel.addItem("three", "3");
+ testModel.addItem("four", "4");
+ testModel.addItem("five", "5");
+
+ ctxt->setContextProperty("testData", &testModel);
+ canvas->setSource(TEST_FILE("repeater2.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+ QCOMPARE(container->childItems().count(), repeater->count()+1);
+
+ QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
+ QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
+
+ // remove at start
+ QQuickItem *item = repeater->itemAt(0);
+ QCOMPARE(item, container->childItems().at(0));
+
+ testModel.removeItem(0);
+ QVERIFY(repeater->itemAt(0) != item);
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(removedSpy.count(), 1);
+ QCOMPARE(removedSpy.at(0).at(0).toInt(), 0);
+ QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
+ removedSpy.clear();
+
+ // remove at end
+ int lastIndex = testModel.count()-1;
+ item = repeater->itemAt(lastIndex);
+ QCOMPARE(item, container->childItems().at(lastIndex));
+
+ testModel.removeItem(lastIndex);
+ QVERIFY(repeater->itemAt(lastIndex) != item);
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(removedSpy.count(), 1);
+ QCOMPARE(removedSpy.at(0).at(0).toInt(), lastIndex);
+ QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
+ removedSpy.clear();
+
+ // remove from middle
+ item = repeater->itemAt(1);
+ QCOMPARE(item, container->childItems().at(1));
+
+ testModel.removeItem(1);
+ QVERIFY(repeater->itemAt(lastIndex) != item);
+ QCOMPARE(countSpy.count(), 1); countSpy.clear();
+ QCOMPARE(removedSpy.count(), 1);
+ QCOMPARE(removedSpy.at(0).at(0).toInt(), 1);
+ QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
+ removedSpy.clear();
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickRepeater::dataModel_changes()
+{
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ TestModel testModel;
+ testModel.addItem("one", "1");
+ testModel.addItem("two", "2");
+ testModel.addItem("three", "3");
+
+ ctxt->setContextProperty("testData", &testModel);
+ canvas->setSource(TEST_FILE("repeater2.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+ QCOMPARE(container->childItems().count(), repeater->count()+1);
+
+ // Check that model changes are propagated
+ QQuickText *text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
+ QVERIFY(text);
+ QCOMPARE(text->text(), QString("two"));
+
+ testModel.modifyItem(1, "Item two", "_2");
+ text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
+ QVERIFY(text);
+ QCOMPARE(text->text(), QString("Item two"));
+
+ text = findItem<QQuickText>(canvas->rootObject(), "myNumber", 1);
+ QVERIFY(text);
+ QCOMPARE(text->text(), QString("_2"));
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickRepeater::itemModel()
+{
+ QQuickView *canvas = createView();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(TEST_FILE("itemlist.qml"));
+ qApp->processEvents();
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->childItems().count(), 1);
+
+ testObject->setUseModel(true);
+ QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
+ QVERIFY(testObject->error() == false);
+
+ QCOMPARE(container->childItems().count(), 4);
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
+ QVERIFY(container->childItems().at(3) == repeater);
+
+ QMetaObject::invokeMethod(canvas->rootObject(), "switchModel");
+ QCOMPARE(container->childItems().count(), 3);
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item4");
+ QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item5");
+ QVERIFY(container->childItems().at(2) == repeater);
+
+ testObject->setUseModel(false);
+ QCOMPARE(container->childItems().count(), 1);
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QQuickRepeater::resetModel()
+{
+ QQuickView *canvas = createView();
+
+ QStringList dataA;
+ for (int i=0; i<10; i++)
+ dataA << QString::number(i);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testData", dataA);
+ canvas->setSource(TEST_FILE("repeater1.qml"));
+ qApp->processEvents();
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
+ QVERIFY(repeater != 0);
+ QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(repeater->count(), dataA.count());
+ for (int i=0; i<repeater->count(); i++)
+ QCOMPARE(repeater->itemAt(i), container->childItems().at(i+1)); // +1 to skip first Text object
+
+ QSignalSpy modelChangedSpy(repeater, SIGNAL(modelChanged()));
+ QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
+ QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
+ QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
+
+ QStringList dataB;
+ for (int i=0; i<20; i++)
+ dataB << QString::number(i);
+
+ // reset context property
+ ctxt->setContextProperty("testData", dataB);
+ QCOMPARE(repeater->count(), dataB.count());
+
+ QCOMPARE(modelChangedSpy.count(), 1);
+ QCOMPARE(countSpy.count(), 1);
+ QCOMPARE(removedSpy.count(), dataA.count());
+ QCOMPARE(addedSpy.count(), dataB.count());
+ for (int i=0; i<dataB.count(); i++) {
+ QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
+ QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
+ }
+ modelChangedSpy.clear();
+ countSpy.clear();
+ removedSpy.clear();
+ addedSpy.clear();
+
+ // reset via setModel()
+ repeater->setModel(dataA);
+ QCOMPARE(repeater->count(), dataA.count());
+
+ QCOMPARE(modelChangedSpy.count(), 1);
+ QCOMPARE(countSpy.count(), 1);
+ QCOMPARE(removedSpy.count(), dataB.count());
+ QCOMPARE(addedSpy.count(), dataA.count());
+ for (int i=0; i<dataA.count(); i++) {
+ QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
+ QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
+ }
+
+ modelChangedSpy.clear();
+ countSpy.clear();
+ removedSpy.clear();
+ addedSpy.clear();
+
+ delete canvas;
+}
+
+// QTBUG-17156
+void tst_QQuickRepeater::modelChanged()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, TEST_FILE("modelChanged.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootObject);
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
+ QVERIFY(repeater);
+
+ repeater->setModel(4);
+ QCOMPARE(repeater->count(), 4);
+ QCOMPARE(repeater->property("itemsCount").toInt(), 4);
+ QCOMPARE(repeater->property("itemsFound").toList().count(), 4);
+
+ repeater->setModel(10);
+ QCOMPARE(repeater->count(), 10);
+ QCOMPARE(repeater->property("itemsCount").toInt(), 10);
+ QCOMPARE(repeater->property("itemsFound").toList().count(), 10);
+
+ delete rootObject;
+}
+
+void tst_QQuickRepeater::properties()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, TEST_FILE("properties.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootObject);
+
+ QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
+ QVERIFY(repeater);
+
+ QSignalSpy modelSpy(repeater, SIGNAL(modelChanged()));
+ repeater->setModel(3);
+ QCOMPARE(modelSpy.count(),1);
+ repeater->setModel(3);
+ QCOMPARE(modelSpy.count(),1);
+
+ QSignalSpy delegateSpy(repeater, SIGNAL(delegateChanged()));
+
+ QDeclarativeComponent rectComponent(&engine);
+ rectComponent.setData("import QtQuick 2.0; Rectangle {}", QUrl::fromLocalFile(""));
+
+ repeater->setDelegate(&rectComponent);
+ QCOMPARE(delegateSpy.count(),1);
+ repeater->setDelegate(&rectComponent);
+ QCOMPARE(delegateSpy.count(),1);
+
+ delete rootObject;
+}
+
+void tst_QQuickRepeater::asynchronous()
+{
+ QQuickView *canvas = createView();
+ canvas->show();
+ QDeclarativeIncubationController controller;
+ canvas->engine()->setIncubationController(&controller);
+
+ canvas->setSource(TEST_FILE("asyncloader.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(rootObject);
+
+ QQuickItem *container = findItem<QQuickItem>(rootObject, "container");
+ QVERIFY(!container);
+ while (!container) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ container = findItem<QQuickItem>(rootObject, "container");
+ }
+
+ QQuickRepeater *repeater = 0;
+ while (!repeater) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ repeater = findItem<QQuickRepeater>(rootObject, "repeater");
+ }
+
+ // items will be created one at a time
+ for (int i = 0; i < 10; ++i) {
+ QString name("delegate");
+ name += QString::number(i);
+ QVERIFY(findItem<QQuickItem>(container, name) == 0);
+ QQuickItem *item = 0;
+ while (!item) {
+ bool b = false;
+ controller.incubateWhile(&b);
+ item = findItem<QQuickItem>(container, name);
+ }
+ }
+
+ {
+ bool b = true;
+ controller.incubateWhile(&b);
+ }
+
+ // verify positioning
+ for (int i = 0; i < 10; ++i) {
+ QString name("delegate");
+ name += QString::number(i);
+ QQuickItem *item = findItem<QQuickItem>(container, name);
+ QTRY_COMPARE(item->y(), i * 50.0);
+ }
+
+ delete canvas;
+}
+
+void tst_QQuickRepeater::initParent()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, TEST_FILE("initparent.qml"));
+
+ QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(qvariant_cast<QQuickItem*>(rootObject->property("parentItem")), rootObject);
+}
+
+QQuickView *tst_QQuickRepeater::createView()
+{
+ QQuickView *canvas = new QQuickView(0);
+ canvas->setGeometry(0,0,240,320);
+
+ return canvas;
+}
+
+template<typename T>
+T *tst_QQuickRepeater::findItem(QObject *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->children().count() << "children";
+ for (int i = 0; i < parent->children().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->children().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeExpression e(qmlContext(item), item, "index");
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+template<typename T>
+T *tst_QQuickRepeater::findItem(QObject *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ if (mo.cast(parent) && (objectName.isEmpty() || parent->objectName() == objectName))
+ return static_cast<T*>(parent);
+ for (int i = 0; i < parent->children().count(); ++i) {
+ QQuickItem *child = qobject_cast<QQuickItem*>(parent->children().at(i));
+ if (!child)
+ continue;
+ QQuickItem *item = findItem<T>(child, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QQuickRepeater)
+
+#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/qtquick2/qquickshadereffect/qquickshadereffect.pro b/tests/auto/qtquick2/qquickshadereffect/qquickshadereffect.pro
new file mode 100644
index 0000000000..de8b247340
--- /dev/null
+++ b/tests/auto/qtquick2/qquickshadereffect/qquickshadereffect.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qquickshadereffect
+SOURCES += tst_qquickshadereffect.cpp
+
+macx:CONFIG -= app_bundle
+
+CONFIG += parallel_test
+QT += core-private gui-private declarative-private quick-private widgets testlib
diff --git a/tests/auto/declarative/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/qtquick2/qquickshadereffect/tst_qquickshadereffect.cpp
index 327fecf1ab..327fecf1ab 100644
--- a/tests/auto/declarative/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/qtquick2/qquickshadereffect/tst_qquickshadereffect.cpp
diff --git a/tests/auto/declarative/qquickspriteimage/data/basic.qml b/tests/auto/qtquick2/qquickspriteimage/data/basic.qml
index 1fcdfd99c3..1fcdfd99c3 100644
--- a/tests/auto/declarative/qquickspriteimage/data/basic.qml
+++ b/tests/auto/qtquick2/qquickspriteimage/data/basic.qml
diff --git a/tests/auto/declarative/qquickspriteimage/data/squarefacesprite.png b/tests/auto/qtquick2/qquickspriteimage/data/squarefacesprite.png
index f9a5d5fcce..f9a5d5fcce 100644
--- a/tests/auto/declarative/qquickspriteimage/data/squarefacesprite.png
+++ b/tests/auto/qtquick2/qquickspriteimage/data/squarefacesprite.png
Binary files differ
diff --git a/tests/auto/qtquick2/qquickspriteimage/qquickspriteimage.pro b/tests/auto/qtquick2/qquickspriteimage/qquickspriteimage.pro
new file mode 100644
index 0000000000..fe788f5b7b
--- /dev/null
+++ b/tests/auto/qtquick2/qquickspriteimage/qquickspriteimage.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquickspriteimage
+SOURCES += tst_qquickspriteimage.cpp
+macx:CONFIG -= app_bundle
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private quick-private network testlib
diff --git a/tests/auto/qtquick2/qquickspriteimage/tst_qquickspriteimage.cpp b/tests/auto/qtquick2/qquickspriteimage/tst_qquickspriteimage.cpp
new file mode 100644
index 0000000000..5c09019b03
--- /dev/null
+++ b/tests/auto/qtquick2/qquickspriteimage/tst_qquickspriteimage.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <QtTest/QtTest>
+#include "../../shared/util.h"
+#include <QtQuick/qquickview.h>
+#include <private/qquickspriteimage_p.h>
+
+class tst_qquickspriteimage : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickspriteimage(){}
+
+private slots:
+ void test_properties();
+};
+
+void tst_qquickspriteimage::test_properties()
+{
+ QQuickView *canvas = new QQuickView(0);
+
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("basic.qml")));
+ canvas->show();
+ QTest::qWaitForWindowShown(canvas);
+
+ QVERIFY(canvas->rootObject());
+ QQuickSpriteImage* sprite = canvas->rootObject()->findChild<QQuickSpriteImage*>("sprite");
+ QVERIFY(sprite);
+
+ QVERIFY(sprite->running());
+ QVERIFY(sprite->interpolate());
+
+ sprite->setRunning(false);
+ QVERIFY(!sprite->running());
+ sprite->setInterpolate(false);
+ QVERIFY(!sprite->interpolate());
+
+ delete canvas;
+}
+
+QTEST_MAIN(tst_qquickspriteimage)
+
+#include "tst_qquickspriteimage.moc"
diff --git a/tests/auto/declarative/qquicktext/data/alignments.qml b/tests/auto/qtquick2/qquicktext/data/alignments.qml
index 9798d9c736..9798d9c736 100644
--- a/tests/auto/declarative/qquicktext/data/alignments.qml
+++ b/tests/auto/qtquick2/qquicktext/data/alignments.qml
diff --git a/tests/auto/declarative/qquicktext/data/alignments_cb.png b/tests/auto/qtquick2/qquicktext/data/alignments_cb.png
index cf6199a418..cf6199a418 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_cb.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_cb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_cc.png b/tests/auto/qtquick2/qquicktext/data/alignments_cc.png
index f81ccb4238..f81ccb4238 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_cc.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_cc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_ct.png b/tests/auto/qtquick2/qquicktext/data/alignments_ct.png
index 9ba64125d5..9ba64125d5 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_ct.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_ct.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_lb.png b/tests/auto/qtquick2/qquicktext/data/alignments_lb.png
index 1b50a81f3d..1b50a81f3d 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_lb.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_lb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_lc.png b/tests/auto/qtquick2/qquicktext/data/alignments_lc.png
index f041b868f8..f041b868f8 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_lc.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_lc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_lt.png b/tests/auto/qtquick2/qquicktext/data/alignments_lt.png
index c75e0d158e..c75e0d158e 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_lt.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_lt.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_rb.png b/tests/auto/qtquick2/qquicktext/data/alignments_rb.png
index b06a5da715..b06a5da715 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_rb.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_rb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_rc.png b/tests/auto/qtquick2/qquicktext/data/alignments_rc.png
index e468857cd0..e468857cd0 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_rc.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_rc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/alignments_rt.png b/tests/auto/qtquick2/qquicktext/data/alignments_rt.png
index 576715ffce..576715ffce 100644
--- a/tests/auto/declarative/qquicktext/data/alignments_rt.png
+++ b/tests/auto/qtquick2/qquicktext/data/alignments_rt.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/embeddedImagesLocal.qml b/tests/auto/qtquick2/qquicktext/data/embeddedImagesLocal.qml
index 74b2ab817a..74b2ab817a 100644
--- a/tests/auto/declarative/qquicktext/data/embeddedImagesLocal.qml
+++ b/tests/auto/qtquick2/qquicktext/data/embeddedImagesLocal.qml
diff --git a/tests/auto/declarative/qquicktext/data/embeddedImagesLocalError.qml b/tests/auto/qtquick2/qquicktext/data/embeddedImagesLocalError.qml
index a2f7e0c89f..a2f7e0c89f 100644
--- a/tests/auto/declarative/qquicktext/data/embeddedImagesLocalError.qml
+++ b/tests/auto/qtquick2/qquicktext/data/embeddedImagesLocalError.qml
diff --git a/tests/auto/declarative/qquicktext/data/embeddedImagesRemote.qml b/tests/auto/qtquick2/qquicktext/data/embeddedImagesRemote.qml
index 702633c538..702633c538 100644
--- a/tests/auto/declarative/qquicktext/data/embeddedImagesRemote.qml
+++ b/tests/auto/qtquick2/qquicktext/data/embeddedImagesRemote.qml
diff --git a/tests/auto/declarative/qquicktext/data/embeddedImagesRemoteError.qml b/tests/auto/qtquick2/qquicktext/data/embeddedImagesRemoteError.qml
index 5762f3e47d..5762f3e47d 100644
--- a/tests/auto/declarative/qquicktext/data/embeddedImagesRemoteError.qml
+++ b/tests/auto/qtquick2/qquicktext/data/embeddedImagesRemoteError.qml
diff --git a/tests/auto/declarative/qquicktext/data/horizontalAlignment_RightToLeft.qml b/tests/auto/qtquick2/qquicktext/data/horizontalAlignment_RightToLeft.qml
index 5ba4d35684..5ba4d35684 100644
--- a/tests/auto/declarative/qquicktext/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/qtquick2/qquicktext/data/horizontalAlignment_RightToLeft.qml
diff --git a/tests/auto/declarative/qquicktext/data/http/exists.png b/tests/auto/qtquick2/qquicktext/data/http/exists.png
index 399bd0b1d9..399bd0b1d9 100644
--- a/tests/auto/declarative/qquicktext/data/http/exists.png
+++ b/tests/auto/qtquick2/qquicktext/data/http/exists.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktext/data/lineCount.qml b/tests/auto/qtquick2/qquicktext/data/lineCount.qml
index b672863684..b672863684 100644
--- a/tests/auto/declarative/qquicktext/data/lineCount.qml
+++ b/tests/auto/qtquick2/qquicktext/data/lineCount.qml
diff --git a/tests/auto/declarative/qquicktext/data/lineHeight.qml b/tests/auto/qtquick2/qquicktext/data/lineHeight.qml
index c1f337aa05..c1f337aa05 100644
--- a/tests/auto/declarative/qquicktext/data/lineHeight.qml
+++ b/tests/auto/qtquick2/qquicktext/data/lineHeight.qml
diff --git a/tests/auto/declarative/qquicktext/data/lineLayout.qml b/tests/auto/qtquick2/qquicktext/data/lineLayout.qml
index cb2474791e..cb2474791e 100644
--- a/tests/auto/declarative/qquicktext/data/lineLayout.qml
+++ b/tests/auto/qtquick2/qquicktext/data/lineLayout.qml
diff --git a/tests/auto/declarative/qquicktext/data/multilineelide.qml b/tests/auto/qtquick2/qquicktext/data/multilineelide.qml
index 23398a84a1..23398a84a1 100644
--- a/tests/auto/declarative/qquicktext/data/multilineelide.qml
+++ b/tests/auto/qtquick2/qquicktext/data/multilineelide.qml
diff --git a/tests/auto/declarative/qquicktext/data/qtbug_14734.qml b/tests/auto/qtquick2/qquicktext/data/qtbug_14734.qml
index e71a798421..e71a798421 100644
--- a/tests/auto/declarative/qquicktext/data/qtbug_14734.qml
+++ b/tests/auto/qtquick2/qquicktext/data/qtbug_14734.qml
diff --git a/tests/auto/declarative/qquicktext/data/rotated.qml b/tests/auto/qtquick2/qquicktext/data/rotated.qml
index fecf64b249..fecf64b249 100644
--- a/tests/auto/declarative/qquicktext/data/rotated.qml
+++ b/tests/auto/qtquick2/qquicktext/data/rotated.qml
diff --git a/tests/auto/qtquick2/qquicktext/qquicktext.pro b/tests/auto/qtquick2/qquicktext/qquicktext.pro
new file mode 100644
index 0000000000..e5bd50afc6
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/qquicktext.pro
@@ -0,0 +1,17 @@
+CONFIG += testcase
+TARGET = tst_qquicktext
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktext.cpp
+
+INCLUDEPATH += ../../shared/
+HEADERS += ../../shared/testhttpserver.h
+SOURCES += ../../shared/testhttpserver.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private widgets-private opengl-private network testlib
diff --git a/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp b/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
new file mode 100644
index 0000000000..60e8571a47
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
@@ -0,0 +1,1460 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <private/qquicktext_p_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include <QFontMetrics>
+#include <QGraphicsSceneMouseEvent>
+#include <qmath.h>
+#include <QtQuick/QQuickView>
+#include <private/qapplication_p.h>
+#include <limits.h>
+#include <QtGui/QMouseEvent>
+#include "../../shared/util.h"
+#include "testhttpserver.h"
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
+class tst_qquicktext : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquicktext();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void text();
+ void width();
+ void wrap();
+ void elide();
+ void multilineElide();
+ void textFormat();
+
+ void alignments_data();
+ void alignments();
+
+ void embeddedImages_data();
+ void embeddedImages();
+
+ void lineCount();
+ void lineHeight();
+
+ // ### these tests may be trivial
+ void horizontalAlignment();
+ void horizontalAlignment_RightToLeft();
+ void verticalAlignment();
+ void font();
+ void style();
+ void color();
+ void smooth();
+
+ // QDeclarativeFontValueType
+ void weight();
+ void underline();
+ void overline();
+ void strikeout();
+ void capitalization();
+ void letterSpacing();
+ void wordSpacing();
+
+ void clickLink();
+
+ void implicitSize_data();
+ void implicitSize();
+
+ void lineLaidOut();
+
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList horizontalAlignmentmentStrings;
+ QStringList verticalAlignmentmentStrings;
+
+ QList<Qt::Alignment> verticalAlignmentments;
+ QList<Qt::Alignment> horizontalAlignmentments;
+
+ QStringList styleStrings;
+ QList<QQuickText::TextStyle> styles;
+
+ QStringList colorStrings;
+
+ QDeclarativeEngine engine;
+
+ QQuickView *createView(const QString &filename);
+};
+void tst_qquicktext::initTestCase()
+{
+}
+
+void tst_qquicktext::cleanupTestCase()
+{
+
+}
+tst_qquicktext::tst_qquicktext()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ horizontalAlignmentmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ verticalAlignmentmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ horizontalAlignmentments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ verticalAlignmentments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ styleStrings << "Normal"
+ << "Outline"
+ << "Raised"
+ << "Sunken";
+
+ styles << QQuickText::Normal
+ << QQuickText::Outline
+ << QQuickText::Raised
+ << QQuickText::Sunken;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+QQuickView *tst_qquicktext::createView(const QString &filename)
+{
+ QQuickView *canvas = new QQuickView(0);
+
+ canvas->setSource(QUrl::fromLocalFile(filename));
+ return canvas;
+}
+
+void tst_qquicktext::text()
+{
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), QString(""));
+ QVERIFY(textObject->width() == 0);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), standard.at(i));
+ QVERIFY(textObject->width() > 0);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QString expected = richText.at(i);
+ QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
+ QVERIFY(textObject->width() > 0);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 0.);
+
+ delete textObject;
+ }
+
+ bool requiresUnhintedMetrics = !qmlDisableDistanceField();
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
+
+ QFont f;
+ qreal metricWidth = 0.0;
+
+ if (requiresUnhintedMetrics) {
+ QString s = standard.at(i);
+ s.replace(QLatin1Char('\n'), QChar::LineSeparator);
+
+ QTextLayout layout(s);
+ layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
+ {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+
+ layout.endLayout();
+
+ metricWidth = qCeil(layout.boundingRect().width());
+ } else {
+ QFontMetricsF fm(f);
+ qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+ metricWidth = qCeil(metricWidth);
+ }
+
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->boundingRect().width() > 0);
+ QCOMPARE(textObject->width(), qreal(metricWidth));
+ QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
+
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QVERIFY(textObject != 0);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
+ QVERIFY(textPrivate != 0);
+
+ QTextDocument *doc = textPrivate->textDocument();
+ QVERIFY(doc != 0);
+
+ QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
+ QVERIFY(textObject->textFormat() == QQuickText::RichText);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::wrap()
+{
+ int textHeight = 0;
+ // for specified width and wrap set true
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ textHeight = textObject->height();
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
+ QCOMPARE(textObject->width(), 300.);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->height() > textHeight);
+
+ int oldHeight = textObject->height();
+ textObject->setWidth(100);
+ QVERIFY(textObject->height() < oldHeight);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->height() > textHeight);
+
+ qreal oldHeight = textObject->height();
+ textObject->setWidth(100);
+ QVERIFY(textObject->height() < oldHeight);
+
+ delete textObject;
+ }
+
+ // richtext again with a fixed height
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->implicitHeight() > textHeight);
+
+ qreal oldHeight = textObject->implicitHeight();
+ textObject->setWidth(100);
+ QVERIFY(textObject->implicitHeight() < oldHeight);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::elide()
+{
+ for (QQuickText::TextElideMode m = QQuickText::ElideLeft; m<=QQuickText::ElideNone; m=QQuickText::TextElideMode(int(m)+1)) {
+ const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
+ QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
+
+ // XXX Poor coverage.
+
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+
+ delete textObject;
+ }
+
+ // richtext - does nothing
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->elideMode(), m);
+ QCOMPARE(textObject->width(), 100.);
+
+ delete textObject;
+ }
+ }
+}
+
+void tst_qquicktext::multilineElide()
+{
+ QQuickView *canvas = createView(TESTDATA("multilineelide.qml"));
+
+ QQuickText *myText = qobject_cast<QQuickText*>(canvas->rootObject());
+ QVERIFY(myText != 0);
+
+ QCOMPARE(myText->lineCount(), 3);
+ QCOMPARE(myText->truncated(), true);
+
+ qreal lineHeight = myText->paintedHeight() / 3.;
+
+ // reduce size and ensure fewer lines are drawn
+ myText->setHeight(lineHeight * 2);
+ QCOMPARE(myText->lineCount(), 2);
+
+ myText->setHeight(lineHeight);
+ QCOMPARE(myText->lineCount(), 1);
+
+ myText->setHeight(5);
+ QCOMPARE(myText->lineCount(), 1);
+
+ myText->setHeight(lineHeight * 3);
+ QCOMPARE(myText->lineCount(), 3);
+
+ // remove max count and show all lines.
+ myText->setHeight(1000);
+ myText->resetMaximumLineCount();
+
+ QCOMPARE(myText->truncated(), false);
+
+ // reduce size again
+ myText->setHeight(lineHeight * 2);
+ QCOMPARE(myText->lineCount(), 2);
+ QCOMPARE(myText->truncated(), true);
+
+ // change line height
+ myText->setLineHeight(1.1);
+ QCOMPARE(myText->lineCount(), 1);
+
+ delete canvas;
+}
+
+void tst_qquicktext::textFormat()
+{
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QQuickText::RichText);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
+ QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate->richText == true);
+
+ delete textObject;
+ }
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QQuickText::AutoText);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
+ QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate->styledText == true);
+
+ delete textObject;
+ }
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QQuickText::PlainText);
+
+ delete textObject;
+ }
+}
+
+
+void tst_qquicktext::alignments_data()
+{
+ QTest::addColumn<int>("hAlign");
+ QTest::addColumn<int>("vAlign");
+ QTest::addColumn<QString>("expectfile");
+
+ QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << TESTDATA("alignments_lt.png");
+ QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << TESTDATA("alignments_rt.png");
+ QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << TESTDATA("alignments_ct.png");
+
+ QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << TESTDATA("alignments_lb.png");
+ QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << TESTDATA("alignments_rb.png");
+ QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << TESTDATA("alignments_cb.png");
+
+ QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << TESTDATA("alignments_lc.png");
+ QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << TESTDATA("alignments_rc.png");
+ QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << TESTDATA("alignments_cc.png");
+}
+
+
+void tst_qquicktext::alignments()
+{
+ QSKIP("Text alignment pixmap comparison tests will not work with scenegraph");
+#if (0)// No widgets in scenegraph
+ QFETCH(int, hAlign);
+ QFETCH(int, vAlign);
+ QFETCH(QString, expectfile);
+
+ QQuickView *canvas = createView(TESTDATA("alignments.qml"));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWait(50);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
+
+ QObject *ob = canvas->rootObject();
+ QVERIFY(ob != 0);
+ ob->setProperty("horizontalAlignment",hAlign);
+ ob->setProperty("verticalAlignment",vAlign);
+ QTRY_COMPARE(ob->property("running").toBool(),false);
+ QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
+ actual.fill(qRgb(255,255,255));
+ QPainter p(&actual);
+ canvas->render(&p);
+
+ QImage expect(expectfile);
+ if (QApplicationPrivate::graphics_system_name == "raster" || QApplicationPrivate::graphics_system_name == "") {
+ QCOMPARE(actual,expect);
+ }
+ delete canvas;
+#endif
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qquicktext::horizontalAlignment()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
+
+ delete textObject;
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
+
+ delete textObject;
+ }
+ }
+
+}
+
+void tst_qquicktext::horizontalAlignment_RightToLeft()
+{
+ QQuickView *canvas = createView(TESTDATA("horizontalAlignment_RightToLeft.qml"));
+ QQuickText *text = canvas->rootObject()->findChild<QQuickText*>("text");
+ QVERIFY(text != 0);
+ canvas->show();
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
+ QVERIFY(textPrivate != 0);
+
+ // implicit alignment should follow the reading direction of RTL text
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
+
+ // explicitly left aligned text
+ text->setHAlign(QQuickText::AlignLeft);
+ QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
+
+ // explicitly right aligned text
+ text->setHAlign(QQuickText::AlignRight);
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
+
+ // change to rich text
+ QString textString = text->text();
+ text->setText(QString("<i>") + textString + QString("</i>"));
+ text->setTextFormat(QQuickText::RichText);
+ text->resetHAlign();
+
+ // implicitly aligned rich text should follow the reading direction of text
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
+
+ // explicitly left aligned rich text
+ text->setHAlign(QQuickText::AlignLeft);
+ QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight);
+
+ // explicitly right aligned rich text
+ text->setHAlign(QQuickText::AlignRight);
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
+
+ text->setText(textString);
+ text->setTextFormat(QQuickText::PlainText);
+
+ // explicitly center aligned
+ text->setHAlign(QQuickText::AlignHCenter);
+ QCOMPARE(text->hAlign(), QQuickText::AlignHCenter);
+ QCOMPARE(text->effectiveHAlign(), text->hAlign());
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2);
+
+ // reseted alignment should go back to following the text reading direction
+ text->resetHAlign();
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
+
+ // mirror the text item
+ QQuickItemPrivate::get(text)->setLayoutMirror(true);
+
+ // mirrored implicit alignment should continue to follow the reading direction of the text
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
+
+ // mirrored explicitly right aligned behaves as left aligned
+ text->setHAlign(QQuickText::AlignRight);
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+ QCOMPARE(text->effectiveHAlign(), QQuickText::AlignLeft);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
+
+ // mirrored explicitly left aligned behaves as right aligned
+ text->setHAlign(QQuickText::AlignLeft);
+ QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
+ QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
+
+ // disable mirroring
+ QQuickItemPrivate::get(text)->setLayoutMirror(false);
+ text->resetHAlign();
+
+ // English text should be implicitly left aligned
+ text->setText("Hello world!");
+ QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
+ QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
+
+#ifndef Q_OS_MAC // QTBUG-18040
+ // empty text with implicit alignment follows the system locale-based
+ // keyboard input direction from QApplication::keyboardInputDirection
+ text->setText("");
+ QCOMPARE(text->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickText::AlignLeft : QQuickText::AlignRight);
+ text->setHAlign(QQuickText::AlignRight);
+ QCOMPARE(text->hAlign(), QQuickText::AlignRight);
+#endif
+
+ delete canvas;
+
+#ifndef Q_OS_MAC // QTBUG-18040
+ // alignment of Text with no text set to it
+ QString componentStr = "import QtQuick 2.0\nText {}";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickText::AlignLeft : QQuickText::AlignRight);
+ delete textObject;
+#endif
+}
+
+void tst_qquicktext::verticalAlignment()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
+
+ delete textObject;
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
+
+ delete textObject;
+ }
+ }
+
+}
+
+void tst_qquicktext::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().pointSize(), 40);
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+
+ delete textObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().pixelSize(), 40);
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+
+ delete textObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().bold(), true);
+ QCOMPARE(textObject->font().italic(), false);
+
+ delete textObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().italic(), true);
+ QCOMPARE(textObject->font().bold(), false);
+
+ delete textObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textObject->font().bold(), false);
+ QCOMPARE(textObject->font().italic(), false);
+
+ delete textObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->font().family(), QString(""));
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::style()
+{
+ //test style
+ for (int i = 0; i < styles.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->style(), (int)styles.at(i));
+ QCOMPARE(textObject->styleColor(), QColor("white"));
+
+ delete textObject;
+ }
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QRectF brPre = textObject->boundingRect();
+ textObject->setStyle(QQuickText::Outline);
+ QRectF brPost = textObject->boundingRect();
+
+ QVERIFY(brPre.width() < brPost.width());
+ QVERIFY(brPre.height() < brPost.height());
+
+ delete textObject;
+}
+
+void tst_qquicktext::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor());
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
+ // default color to black?
+ QCOMPARE(textObject->color(), QColor("black"));
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ for (int j = 0; j < colorStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
+
+ delete textObject;
+ }
+ }
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), testColor);
+
+ delete textObject;
+ }
+}
+
+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) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), true);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), false);
+
+ delete textObject;
+ }
+ }
+ for (int i = 0; i < richText.size(); i++)
+ {
+ {
+ QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), true);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+ QCOMPARE(textObject->smooth(), false);
+
+ delete textObject;
+ }
+ }
+}
+
+void tst_qquicktext::weight()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Normal);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Bold);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::underline()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().underline(), false);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.underline: true; text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().underline(), true);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::overline()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().overline(), false);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.overline: true; text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().overline(), true);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::strikeout()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().strikeOut(), false);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { font.strikeout: true; text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().strikeOut(), true);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::capitalization()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::MixedCase);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllUppercase);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllLowercase);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::SmallCaps);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::Capitalize);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::letterSpacing()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), 0.0);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), -2.);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().letterSpacing(), 3.);
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::wordSpacing()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), 0.0);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), -50.);
+
+ delete textObject;
+ }
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->font().wordSpacing(), 200.);
+
+ delete textObject;
+ }
+}
+
+
+
+
+class EventSender : public QQuickItem
+{
+public:
+ void sendEvent(QMouseEvent *event) {
+ if (event->type() == QEvent::MouseButtonPress)
+ mousePressEvent(event);
+ else if (event->type() == QEvent::MouseButtonRelease)
+ mouseReleaseEvent(event);
+ else
+ qWarning() << "Trying to send unsupported event type";
+ }
+};
+
+class LinkTest : public QObject
+{
+ Q_OBJECT
+public:
+ LinkTest() {}
+
+ QString link;
+
+public slots:
+ void linkClicked(QString l) { link = l; }
+};
+
+void tst_qquicktext::clickLink()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+
+ LinkTest test;
+ QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
+
+ {
+ QMouseEvent me(QEvent::MouseButtonPress,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+ static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
+
+ }
+
+ {
+ QMouseEvent me(QEvent::MouseButtonRelease,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+ static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
+
+ }
+
+
+ QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
+
+ delete textObject;
+ }
+}
+
+void tst_qquicktext::embeddedImages_data()
+{
+ QTest::addColumn<QUrl>("qmlfile");
+ QTest::addColumn<QString>("error");
+ QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocal.qml")) << "";
+ QTest::newRow("local-error") << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocalError.qml"))
+ << QUrl::fromLocalFile(TESTDATA("embeddedImagesLocalError.qml")).toString()+":3:1: QML Text: Cannot open: " + QUrl::fromLocalFile(TESTDATA("http/notexists.png")).toString();
+ QTest::newRow("remote") << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemote.qml")) << "";
+ QTest::newRow("remote-error") << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemoteError.qml"))
+ << QUrl::fromLocalFile(TESTDATA("embeddedImagesRemoteError.qml")).toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found";
+}
+
+void tst_qquicktext::embeddedImages()
+{
+ // Tests QTBUG-9900
+
+ QFETCH(QUrl, qmlfile);
+ QFETCH(QString, error);
+
+ TestHTTPServer server(14453);
+ server.serveDirectory(TESTDATA("http"));
+
+ if (!error.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
+
+ QDeclarativeComponent textComponent(&engine, qmlfile);
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+
+ QTRY_COMPARE(textObject->resourcesLoading(), 0);
+
+ QPixmap pm(TESTDATA("http/exists.png"));
+ if (error.isEmpty()) {
+ QCOMPARE(textObject->width(), double(pm.width()));
+ QCOMPARE(textObject->height(), double(pm.height()));
+ } else {
+ QVERIFY(16 != pm.width()); // check test is effective
+ QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
+ QCOMPARE(textObject->height(), 16.0);
+ }
+
+ delete textObject;
+}
+
+void tst_qquicktext::lineCount()
+{
+ QQuickView *canvas = createView(TESTDATA("lineCount.qml"));
+
+ QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QVERIFY(myText->lineCount() > 1);
+ QVERIFY(!myText->truncated());
+ QCOMPARE(myText->maximumLineCount(), INT_MAX);
+
+ myText->setMaximumLineCount(2);
+ QCOMPARE(myText->lineCount(), 2);
+ QCOMPARE(myText->truncated(), true);
+ QCOMPARE(myText->maximumLineCount(), 2);
+
+ myText->resetMaximumLineCount();
+ QCOMPARE(myText->maximumLineCount(), INT_MAX);
+ QCOMPARE(myText->truncated(), false);
+
+ myText->setElideMode(QQuickText::ElideRight);
+ myText->setMaximumLineCount(2);
+ QCOMPARE(myText->lineCount(), 2);
+ QCOMPARE(myText->truncated(), true);
+ QCOMPARE(myText->maximumLineCount(), 2);
+
+ delete canvas;
+}
+
+void tst_qquicktext::lineHeight()
+{
+ QQuickView *canvas = createView(TESTDATA("lineHeight.qml"));
+
+ QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QVERIFY(myText->lineHeight() == 1);
+ QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
+
+ qreal h = myText->height();
+ myText->setLineHeight(1.5);
+ QVERIFY(myText->height() == qCeil(h * 1.5));
+
+ myText->setLineHeightMode(QQuickText::FixedHeight);
+ myText->setLineHeight(20);
+ QCOMPARE(myText->height(), myText->lineCount() * 20.0);
+
+ myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum.");
+ myText->setLineHeightMode(QQuickText::ProportionalHeight);
+ myText->setLineHeight(1.0);
+
+ qreal h2 = myText->height();
+ myText->setLineHeight(2.0);
+ QVERIFY(myText->height() == h2 * 2.0);
+
+ myText->setLineHeightMode(QQuickText::FixedHeight);
+ myText->setLineHeight(10);
+ QCOMPARE(myText->height(), myText->lineCount() * 10.0);
+
+ delete canvas;
+}
+
+void tst_qquicktext::implicitSize_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("wrap");
+ QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap";
+ QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.NoWrap";
+ QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap";
+ QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.Wrap";
+}
+
+void tst_qquicktext::implicitSize()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
+
+ QVERIFY(textObject->width() < textObject->implicitWidth());
+ QVERIFY(textObject->height() == textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QVERIFY(textObject->width() == textObject->implicitWidth());
+ QVERIFY(textObject->height() == textObject->implicitHeight());
+
+ delete textObject;
+}
+
+void tst_qquicktext::lineLaidOut()
+{
+ QQuickView *canvas = createView(TESTDATA("lineLayout.qml"));
+
+ QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+ QVERIFY(myText != 0);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != 0);
+
+ QTextDocument *doc = textPrivate->textDocument();
+ QVERIFY(doc == 0);
+
+ QVERIFY(myText->lineCount() == textPrivate->linesRects.count());
+
+ for (int i = 0; i < textPrivate->linesRects.count(); ++i) {
+ QRectF r = textPrivate->linesRects.at(i);
+ QVERIFY(r.width() == i * 15);
+ if (i >= 30)
+ QVERIFY(r.x() == r.width() + 30);
+ if (i >= 60) {
+ QVERIFY(r.x() == r.width() * 2 + 60);
+ QVERIFY(r.height() == 20);
+ }
+ }
+}
+
+QTEST_MAIN(tst_qquicktext)
+
+#include "tst_qquicktext.moc"
diff --git a/tests/auto/declarative/qquicktextedit/data/CursorRect.qml b/tests/auto/qtquick2/qquicktextedit/data/CursorRect.qml
index cae3e63b72..cae3e63b72 100644
--- a/tests/auto/declarative/qquicktextedit/data/CursorRect.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/CursorRect.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments.qml b/tests/auto/qtquick2/qquicktextedit/data/alignments.qml
index 7d365da8cb..7d365da8cb 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_cb.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_cb.png
index 99de2192de..99de2192de 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_cb.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_cb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_cc.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_cc.png
index cb85251180..cb85251180 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_cc.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_cc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_ct.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_ct.png
index ddca549c82..ddca549c82 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_ct.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_ct.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_lb.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_lb.png
index 1b50a81f3d..1b50a81f3d 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_lb.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_lb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_lc.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_lc.png
index f041b868f8..f041b868f8 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_lc.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_lc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_lt.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_lt.png
index c75e0d158e..c75e0d158e 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_lt.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_lt.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_rb.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_rb.png
index b06a5da715..b06a5da715 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_rb.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_rb.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_rc.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_rc.png
index e468857cd0..e468857cd0 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_rc.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_rc.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/alignments_rt.png b/tests/auto/qtquick2/qquicktextedit/data/alignments_rt.png
index 576715ffce..576715ffce 100644
--- a/tests/auto/declarative/qquicktextedit/data/alignments_rt.png
+++ b/tests/auto/qtquick2/qquicktextedit/data/alignments_rt.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextedit/data/cursorTest.qml b/tests/auto/qtquick2/qquicktextedit/data/cursorTest.qml
index 7bfc869403..7bfc869403 100644
--- a/tests/auto/declarative/qquicktextedit/data/cursorTest.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/cursorTest.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/cursorVisible.qml b/tests/auto/qtquick2/qquicktextedit/data/cursorVisible.qml
index 49e9386947..49e9386947 100644
--- a/tests/auto/declarative/qquicktextedit/data/cursorVisible.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/cursorVisible.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/geometrySignals.qml b/tests/auto/qtquick2/qquicktextedit/data/geometrySignals.qml
index 3dbe61c74b..3dbe61c74b 100644
--- a/tests/auto/declarative/qquicktextedit/data/geometrySignals.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/geometrySignals.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/horizontalAlignment_RightToLeft.qml b/tests/auto/qtquick2/qquicktextedit/data/horizontalAlignment_RightToLeft.qml
index 4cd92367ec..4cd92367ec 100644
--- a/tests/auto/declarative/qquicktextedit/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/horizontalAlignment_RightToLeft.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/ErrItem.qml b/tests/auto/qtquick2/qquicktextedit/data/http/ErrItem.qml
index 68c0e0c093..68c0e0c093 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/ErrItem.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/ErrItem.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/NormItem.qml b/tests/auto/qtquick2/qquicktextedit/data/http/NormItem.qml
index 2e4c1ed440..2e4c1ed440 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/NormItem.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/NormItem.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTest.qml b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTest.qml
index be4526e22b..be4526e22b 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTest.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTest.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail1.qml b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail1.qml
index 1d7763f913..1d7763f913 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail1.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail1.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail2.qml b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail2.qml
index c82ec02e68..c82ec02e68 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestFail2.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestFail2.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestPass.qml b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestPass.qml
index 96d582c95d..96d582c95d 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/cursorHttpTestPass.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/cursorHttpTestPass.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/http/qmldir b/tests/auto/qtquick2/qquicktextedit/data/http/qmldir
index 886e6ffec0..886e6ffec0 100644
--- a/tests/auto/declarative/qquicktextedit/data/http/qmldir
+++ b/tests/auto/qtquick2/qquicktextedit/data/http/qmldir
diff --git a/tests/auto/declarative/qquicktextedit/data/httpfail/FailItem.qml b/tests/auto/qtquick2/qquicktextedit/data/httpfail/FailItem.qml
index 8161843479..8161843479 100644
--- a/tests/auto/declarative/qquicktextedit/data/httpfail/FailItem.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/httpfail/FailItem.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/httpslow/WaitItem.qml b/tests/auto/qtquick2/qquicktextedit/data/httpslow/WaitItem.qml
index 8161843479..8161843479 100644
--- a/tests/auto/declarative/qquicktextedit/data/httpslow/WaitItem.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/httpslow/WaitItem.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/inputContext.qml b/tests/auto/qtquick2/qquicktextedit/data/inputContext.qml
index a37c77e3bf..a37c77e3bf 100644
--- a/tests/auto/declarative/qquicktextedit/data/inputContext.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/inputContext.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/inputMethodEvent.qml b/tests/auto/qtquick2/qquicktextedit/data/inputMethodEvent.qml
index e3f629ce3e..e3f629ce3e 100644
--- a/tests/auto/declarative/qquicktextedit/data/inputMethodEvent.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/inputMethodEvent.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/inputmethodhints.qml b/tests/auto/qtquick2/qquicktextedit/data/inputmethodhints.qml
index dec3b978e7..dec3b978e7 100644
--- a/tests/auto/declarative/qquicktextedit/data/inputmethodhints.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/inputmethodhints.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselection_default.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_default.qml
index ac32f4ced7..ac32f4ced7 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselection_default.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_default.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselection_false.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_false.qml
index ac32f4ced7..ac32f4ced7 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselection_false.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_false.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselection_false_words.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_false_words.qml
index 86aea46a85..86aea46a85 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselection_false_words.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_false_words.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselection_true.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_true.qml
index 7c7cb0b6fc..7c7cb0b6fc 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselection_true.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_true.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselection_true_words.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_true_words.qml
index c356999220..c356999220 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselection_true_words.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselection_true_words.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_characters.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_characters.qml
index c1fe42fd57..c1fe42fd57 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_characters.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_characters.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_default.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_default.qml
index 7c7cb0b6fc..7c7cb0b6fc 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_default.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_default.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_words.qml b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_words.qml
index 0a372bbf83..0a372bbf83 100644
--- a/tests/auto/declarative/qquicktextedit/data/mouseselectionmode_words.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/mouseselectionmode_words.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/navigation.qml b/tests/auto/qtquick2/qquicktextedit/data/navigation.qml
index 0201c62b3c..0201c62b3c 100644
--- a/tests/auto/declarative/qquicktextedit/data/navigation.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/navigation.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/openInputPanel.qml b/tests/auto/qtquick2/qquicktextedit/data/openInputPanel.qml
index d3aecf21be..d3aecf21be 100644
--- a/tests/auto/declarative/qquicktextedit/data/openInputPanel.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/openInputPanel.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/positionAt.qml b/tests/auto/qtquick2/qquicktextedit/data/positionAt.qml
index 19093281fe..19093281fe 100644
--- a/tests/auto/declarative/qquicktextedit/data/positionAt.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/positionAt.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/qtbug-22058.qml b/tests/auto/qtquick2/qquicktextedit/data/qtbug-22058.qml
index 8ad1514fbf..8ad1514fbf 100644
--- a/tests/auto/declarative/qquicktextedit/data/qtbug-22058.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/qtbug-22058.qml
diff --git a/tests/auto/declarative/qquicktextedit/data/readOnly.qml b/tests/auto/qtquick2/qquicktextedit/data/readOnly.qml
index 085adba5fb..085adba5fb 100644
--- a/tests/auto/declarative/qquicktextedit/data/readOnly.qml
+++ b/tests/auto/qtquick2/qquicktextedit/data/readOnly.qml
diff --git a/tests/auto/qtquick2/qquicktextedit/qquicktextedit.pro b/tests/auto/qtquick2/qquicktextedit/qquicktextedit.pro
new file mode 100644
index 0000000000..02a834beab
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktextedit/qquicktextedit.pro
@@ -0,0 +1,12 @@
+CONFIG += testcase
+TARGET = tst_qquicktextedit
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktextedit.cpp ../../shared/testhttpserver.cpp
+HEADERS += ../../shared/testhttpserver.h
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private network widgets-private testlib
diff --git a/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp
new file mode 100644
index 0000000000..97d7531321
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp
@@ -0,0 +1,3555 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include "../../shared/testhttpserver.h"
+#include <math.h>
+#include <QFile>
+#include <QTextDocument>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtGui/qguiapplication.h>
+#include <private/qquicktextedit_p.h>
+#include <private/qquicktextedit_p_p.h>
+#include <QFontMetrics>
+#include <QtQuick/QQuickView>
+#include <QDir>
+#include <QStyle>
+#include <QInputPanel>
+#include <QClipboard>
+#include <QMimeData>
+#include <private/qtextcontrol_p.h>
+#include "../../shared/util.h"
+#include <qplatforminputcontext_qpa.h>
+#include <private/qinputpanel_p.h>
+
+#ifdef Q_OS_MAC
+#include <Carbon/Carbon.h>
+#endif
+
+
+Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
+QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
+{
+ // XXX This will be replaced by some clever persistent platform image store.
+ QString persistent_dir = TESTDATA("");
+ QString arch = "unknown-architecture"; // QTest needs to help with this.
+
+ QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
+
+ if (!QFile::exists(expectfile)) {
+ actual.save(expectfile);
+ qWarning() << "created" << expectfile;
+ }
+
+ return expectfile;
+}
+
+typedef QPair<int, QChar> Key;
+
+class tst_qquicktextedit : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qquicktextedit();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void text();
+ void width();
+ void wrap();
+ void textFormat();
+ void alignments();
+ void alignments_data();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void hAlign_RightToLeft();
+ void vAlign();
+ void font();
+ void color();
+ void textMargin();
+ void persistentSelection();
+ void focusOnPress();
+ void selection();
+ void isRightToLeft_data();
+ void isRightToLeft();
+ void keySelection();
+ void moveCursorSelection_data();
+ void moveCursorSelection();
+ void moveCursorSelectionSequence_data();
+ void moveCursorSelectionSequence();
+ void mouseSelection_data();
+ void mouseSelection();
+ void mouseSelectionMode_data();
+ void mouseSelectionMode();
+ void dragMouseSelection();
+ void inputMethodHints();
+
+ void positionAt();
+
+ void cursorDelegate();
+ void cursorVisible();
+ void delegateLoading_data();
+ void delegateLoading();
+ void navigation();
+ void readOnly();
+ void copyAndPaste();
+ void canPaste();
+ void canPasteEmpty();
+ void textInput();
+ void openInputPanel();
+ void geometrySignals();
+ void pastingRichText_QTBUG_14003();
+ void implicitSize_data();
+ void implicitSize();
+ void testQtQuick11Attributes();
+ void testQtQuick11Attributes_data();
+
+ void preeditCursorRectangle();
+ void inputMethodComposing();
+ void cursorRectangleSize();
+
+ void getText_data();
+ void getText();
+ void getFormattedText_data();
+ void getFormattedText();
+ void insert_data();
+ void insert();
+ void remove_data();
+ void remove();
+
+ void keySequence_data();
+ void keySequence();
+
+ void undo_data();
+ void undo();
+ void redo_data();
+ void redo();
+ void undo_keypressevents_data();
+ void undo_keypressevents();
+
+ void emptytags_QTBUG_22058();
+
+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);
+
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList colorStrings;
+
+ QDeclarativeEngine engine;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+typedef QList<Key> KeyList;
+Q_DECLARE_METATYPE(KeyList)
+
+Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
+
+void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
+{
+ for (int i = 0; i < keys.count(); ++i) {
+ const int key = keys.at(i).first;
+ const int modifiers = key & Qt::KeyboardModifierMask;
+ const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
+
+ QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
+ QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
+
+ QGuiApplication::sendEvent(window, &press);
+ QGuiApplication::sendEvent(window, &release);
+ }
+}
+
+void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &sequence)
+{
+ for (uint i = 0; i < sequence.count(); ++i) {
+ const int key = sequence[i];
+ const int modifiers = key & Qt::KeyboardModifierMask;
+
+ QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
+ }
+}
+
+QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
+{
+ for (uint i = 0; i < sequence.count(); ++i)
+ keys << Key(sequence[i], QChar());
+ return keys;
+}
+
+template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
+{
+ for (int i = 0; i < N - 1; ++i) {
+ int key = QTest::asciiToKey(characters[i]);
+ QChar character = QLatin1Char(characters[i]);
+ keys << Key(key, character);
+ }
+ return keys;
+}
+
+QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
+{
+ keys << Key(key, QChar());
+ return keys;
+}
+
+
+void tst_qquicktextedit::initTestCase()
+{
+}
+
+void tst_qquicktextedit::cleanupTestCase()
+{
+
+}
+tst_qquicktextedit::tst_qquicktextedit()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog"
+ << "Hello, world!"
+ << "!dlrow ,olleH";
+
+ richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qquicktextedit::text()
+{
+ {
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), QString(""));
+ QCOMPARE(textEditObject->length(), 0);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), standard.at(i));
+ QCOMPARE(textEditObject->length(), standard.at(i).length());
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QString actual = textEditObject->text();
+ QString expected = richText.at(i);
+ actual.replace(QRegExp(".*<body[^>]*>"),"");
+ actual.replace(QRegExp("(<[^>]*>)+"),"<>");
+ expected.replace(QRegExp("(<[^>]*>)+"),"<>");
+ QCOMPARE(actual.simplified(),expected.simplified());
+
+ expected.replace("<>", " ");
+ QCOMPARE(textEditObject->length(), expected.simplified().length());
+ }
+}
+
+void tst_qquicktextedit::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 0.0);
+ }
+
+ bool requiresUnhintedMetrics = !qmlDisableDistanceField();
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ qreal metricWidth = 0.0;
+
+ if (requiresUnhintedMetrics) {
+ QString s = standard.at(i);
+ s.replace(QLatin1Char('\n'), QChar::LineSeparator);
+
+ QTextLayout layout(s);
+ layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
+ {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+
+ layout.endLayout();
+
+ metricWidth = ceil(layout.boundingRect().width());
+ } else {
+ QFontMetricsF fm(f);
+ metricWidth = fm.size(Qt::TextExpandTabs | Qt::TextShowMnemonic, standard.at(i)).width();
+ metricWidth = ceil(metricWidth);
+ }
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), qreal(metricWidth));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+ if (requiresUnhintedMetrics)
+ document.setUseDesignMetrics(true);
+
+ int documentWidth = ceil(document.idealWidth());
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), qreal(documentWidth));
+ }
+}
+
+void tst_qquicktextedit::wrap()
+{
+ // for specified width and wrap set true
+ {
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+}
+
+void tst_qquicktextedit::textFormat()
+{
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QQuickTextEdit::RichText);
+ }
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
+ }
+}
+
+void tst_qquicktextedit::alignments_data()
+{
+ QTest::addColumn<int>("hAlign");
+ QTest::addColumn<int>("vAlign");
+ QTest::addColumn<QString>("expectfile");
+
+ QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
+ QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
+ QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
+
+ QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
+ QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
+ QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
+
+ QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
+ QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
+ QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
+}
+
+
+void tst_qquicktextedit::alignments()
+{
+ QSKIP("Image comparison of text is almost guaranteed to fail during development");
+
+ QFETCH(int, hAlign);
+ QFETCH(int, vAlign);
+ QFETCH(QString, expectfile);
+
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("alignments.qml")));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QObject *ob = canvas.rootObject();
+ QVERIFY(ob != 0);
+ ob->setProperty("horizontalAlignment",hAlign);
+ ob->setProperty("verticalAlignment",vAlign);
+ QTRY_COMPARE(ob->property("running").toBool(),false);
+ QImage actual = canvas.grabFrameBuffer();
+
+ expectfile = createExpectedFileIfNotFound(expectfile, actual);
+
+ QImage expect(expectfile);
+
+ QCOMPARE(actual,expect);
+}
+
+
+//the alignment tests may be trivial o.oa
+void tst_qquicktextedit::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qquicktextedit::hAlign_RightToLeft()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment_RightToLeft.qml")));
+ QQuickTextEdit *textEdit = canvas.rootObject()->findChild<QQuickTextEdit*>("text");
+ QVERIFY(textEdit != 0);
+ canvas.show();
+
+ const QString rtlText = textEdit->text();
+
+ // implicit alignment should follow the reading direction of text
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // explicitly left aligned
+ textEdit->setHAlign(QQuickTextEdit::AlignLeft);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
+ QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+
+ // explicitly right aligned
+ textEdit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ QString textString = textEdit->text();
+ textEdit->setText(QString("<i>") + textString + QString("</i>"));
+ textEdit->resetHAlign();
+
+ // implicitly aligned rich text should follow the reading direction of RTL text
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // explicitly left aligned rich text
+ textEdit->setHAlign(QQuickTextEdit::AlignLeft);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
+ QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
+ QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+
+ // explicitly right aligned rich text
+ textEdit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ textEdit->setText(textString);
+
+ // explicitly center aligned
+ textEdit->setHAlign(QQuickTextEdit::AlignHCenter);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignHCenter);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // reseted alignment should go back to following the text reading direction
+ textEdit->resetHAlign();
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // mirror the text item
+ QQuickItemPrivate::get(textEdit)->setLayoutMirror(true);
+
+ // mirrored implicit alignment should continue to follow the reading direction of the text
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // mirrored explicitly right aligned behaves as left aligned
+ textEdit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
+ QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+
+ // mirrored explicitly left aligned behaves as right aligned
+ textEdit->setHAlign(QQuickTextEdit::AlignLeft);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
+ QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+
+ // disable mirroring
+ QQuickItemPrivate::get(textEdit)->setLayoutMirror(false);
+ textEdit->resetHAlign();
+
+ // English text should be implicitly left aligned
+ textEdit->setText("Hello world!");
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
+ QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ textEdit->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
+
+ // Clear pre-edit text. TextEdit should maybe do this itself on setText, but that may be
+ // redundant as an actual input method may take care of it.
+ { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+
+#ifndef Q_OS_MAC // QTBUG-18040
+ // empty text with implicit alignment follows the system locale-based
+ // keyboard input direction from QGuiApplication::keyboardInputDirection
+ textEdit->setText("");
+ QCOMPARE(textEdit->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickTextEdit::AlignLeft : QQuickTextEdit::AlignRight);
+ if (QGuiApplication::keyboardInputDirection() == Qt::LeftToRight)
+ QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ else
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ textEdit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+#endif
+
+#ifndef Q_OS_MAC // QTBUG-18040
+ // alignment of TextEdit with no text set to it
+ QString componentStr = "import QtQuick 2.0\nTextEdit {}";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
+ QCOMPARE(textObject->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickTextEdit::AlignLeft : QQuickTextEdit::AlignRight);
+ delete textObject;
+#endif
+}
+
+void tst_qquicktextedit::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qquicktextedit::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { font.pointSize: 40; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().pointSize(), 40);
+ QCOMPARE(textEditObject->font().bold(), false);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { font.bold: true; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().bold(), true);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { font.italic: true; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().italic(), true);
+ QCOMPARE(textEditObject->font().bold(), false);
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textEditObject->font().bold(), false);
+ QCOMPARE(textEditObject->font().italic(), false);
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { font.family: \"\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->font().family(), QString(""));
+ }
+}
+
+void tst_qquicktextedit::color()
+{
+ //test initial color
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QQuickTextEditPrivate *textEditPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(textEditObject));
+
+ QVERIFY(textEditObject);
+ QVERIFY(textEditPrivate);
+ QVERIFY(textEditPrivate->control);
+
+ QPalette pal = textEditPrivate->control->palette();
+ QCOMPARE(textEditPrivate->color, QColor("black"));
+ QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text));
+ }
+ //test normal
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
+ }
+
+ //test selection
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
+ }
+
+ //test selected text
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->color(), testColor);
+ }
+}
+
+void tst_qquicktextedit::textMargin()
+{
+ for (qreal i=0; i<=10; i+=0.3) {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->textMargin(), i);
+ }
+}
+
+void tst_qquicktextedit::persistentSelection()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { persistentSelection: true; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->persistentSelection(), true);
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { persistentSelection: false; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->persistentSelection(), false);
+ }
+}
+
+void tst_qquicktextedit::focusOnPress()
+{
+ {
+ QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
+ QDeclarativeComponent 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\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->focusOnPress(), false);
+ }
+}
+
+void tst_qquicktextedit::selection()
+{
+ QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+
+
+ //Test selection follows cursor
+ for (int i=0; i<= testStr.size(); i++) {
+ textEditObject->setCursorPosition(i);
+ QCOMPARE(textEditObject->cursorPosition(), i);
+ QCOMPARE(textEditObject->selectionStart(), i);
+ QCOMPARE(textEditObject->selectionEnd(), i);
+ QVERIFY(textEditObject->selectedText().isNull());
+ }
+
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ // Verify invalid positions are ignored.
+ textEditObject->setCursorPosition(-1);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ textEditObject->setCursorPosition(textEditObject->text().count()+1);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ //Test selection
+ for (int i=0; i<= testStr.size(); i++) {
+ textEditObject->select(0,i);
+ QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
+ }
+ for (int i=0; i<= testStr.size(); i++) {
+ textEditObject->select(i,testStr.size());
+ QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
+ }
+
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->cursorPosition() == 0);
+ QVERIFY(textEditObject->selectionStart() == 0);
+ QVERIFY(textEditObject->selectionEnd() == 0);
+ QVERIFY(textEditObject->selectedText().isNull());
+
+ //Test Error Ignoring behaviour
+ textEditObject->setCursorPosition(0);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(-10,0);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(100,101);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(0,-10);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(0,100);
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(0,10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->select(-10,0);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->select(100,101);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->select(0,-10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->select(0,100);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+
+ textEditObject->deselect();
+ QVERIFY(textEditObject->selectedText().isNull());
+ textEditObject->select(0,10);
+ QVERIFY(textEditObject->selectedText().size() == 10);
+ textEditObject->deselect();
+ QVERIFY(textEditObject->selectedText().isNull());
+}
+
+void tst_qquicktextedit::isRightToLeft_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<bool>("emptyString");
+ QTest::addColumn<bool>("firstCharacter");
+ QTest::addColumn<bool>("lastCharacter");
+ QTest::addColumn<bool>("middleCharacter");
+ QTest::addColumn<bool>("startString");
+ QTest::addColumn<bool>("midString");
+ QTest::addColumn<bool>("endString");
+
+ const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
+ QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
+ QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
+ QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
+ QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
+ QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
+ QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
+}
+
+void tst_qquicktextedit::isRightToLeft()
+{
+ QFETCH(QString, text);
+ QFETCH(bool, emptyString);
+ QFETCH(bool, firstCharacter);
+ QFETCH(bool, lastCharacter);
+ QFETCH(bool, middleCharacter);
+ QFETCH(bool, startString);
+ QFETCH(bool, midString);
+ QFETCH(bool, endString);
+
+ QQuickTextEdit textEdit;
+ textEdit.setText(text);
+
+ // first test that the right string is delivered to the QString::isRightToLeft()
+ QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
+ QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
+ QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
+ QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
+ QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
+ QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
+ if (text.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
+ QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
+
+ // then test that the feature actually works
+ QCOMPARE(textEdit.isRightToLeft(0,0), emptyString);
+ QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter);
+ QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
+ QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
+ QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString);
+ QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString);
+ if (text.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
+ QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString);
+}
+
+void tst_qquicktextedit::keySelection()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+
+ QSignalSpy spy(input, SIGNAL(selectionChanged()));
+
+ simulateKey(&canvas, Qt::Key_Right, Qt::ShiftModifier);
+ QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(input->selectedText(), QString("a"));
+ QCOMPARE(spy.count(), 1);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(input->selectedText(), QString());
+ QCOMPARE(spy.count(), 2);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == false);
+ QCOMPARE(input->selectedText(), QString());
+ QCOMPARE(spy.count(), 2);
+
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(spy.count(), 2);
+ simulateKey(&canvas, Qt::Key_Left, Qt::ShiftModifier);
+ QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(input->selectedText(), QString("a"));
+ QCOMPARE(spy.count(), 3);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == true);
+ QCOMPARE(input->selectedText(), QString());
+ QCOMPARE(spy.count(), 4);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == false);
+ QCOMPARE(input->selectedText(), QString());
+ QCOMPARE(spy.count(), 4);
+}
+
+void tst_qquicktextedit::moveCursorSelection_data()
+{
+ QTest::addColumn<QString>("testStr");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<int>("movePosition");
+ QTest::addColumn<QQuickTextEdit::SelectionMode>("mode");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<bool>("reversible");
+
+ QTest::newRow("(t)he|characters")
+ << standard[0] << 0 << 1 << QQuickTextEdit::SelectCharacters << 0 << 1 << true;
+ QTest::newRow("do(g)|characters")
+ << standard[0] << 43 << 44 << QQuickTextEdit::SelectCharacters << 43 << 44 << true;
+ QTest::newRow("jum(p)ed|characters")
+ << standard[0] << 23 << 24 << QQuickTextEdit::SelectCharacters << 23 << 24 << true;
+ QTest::newRow("jumped( )over|characters")
+ << standard[0] << 26 << 27 << QQuickTextEdit::SelectCharacters << 26 << 27 << true;
+ QTest::newRow("(the )|characters")
+ << standard[0] << 0 << 4 << QQuickTextEdit::SelectCharacters << 0 << 4 << true;
+ QTest::newRow("( dog)|characters")
+ << standard[0] << 40 << 44 << QQuickTextEdit::SelectCharacters << 40 << 44 << true;
+ QTest::newRow("( jumped )|characters")
+ << standard[0] << 19 << 27 << QQuickTextEdit::SelectCharacters << 19 << 27 << true;
+ QTest::newRow("th(e qu)ick|characters")
+ << standard[0] << 2 << 6 << QQuickTextEdit::SelectCharacters << 2 << 6 << true;
+ QTest::newRow("la(zy d)og|characters")
+ << standard[0] << 38 << 42 << QQuickTextEdit::SelectCharacters << 38 << 42 << true;
+ QTest::newRow("jum(ped ov)er|characters")
+ << standard[0] << 23 << 29 << QQuickTextEdit::SelectCharacters << 23 << 29 << true;
+ QTest::newRow("()the|characters")
+ << standard[0] << 0 << 0 << QQuickTextEdit::SelectCharacters << 0 << 0 << true;
+ QTest::newRow("dog()|characters")
+ << standard[0] << 44 << 44 << QQuickTextEdit::SelectCharacters << 44 << 44 << true;
+ QTest::newRow("jum()ped|characters")
+ << standard[0] << 23 << 23 << QQuickTextEdit::SelectCharacters << 23 << 23 << true;
+
+ QTest::newRow("<(t)he>|words")
+ << standard[0] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 3 << true;
+ QTest::newRow("<do(g)>|words")
+ << standard[0] << 43 << 44 << QQuickTextEdit::SelectWords << 41 << 44 << true;
+ QTest::newRow("<jum(p)ed>|words")
+ << standard[0] << 23 << 24 << QQuickTextEdit::SelectWords << 20 << 26 << true;
+ QTest::newRow("<jumped( )>over|words")
+ << standard[0] << 26 << 27 << QQuickTextEdit::SelectWords << 20 << 27 << false;
+ QTest::newRow("jumped<( )over>|words,reversed")
+ << standard[0] << 27 << 26 << QQuickTextEdit::SelectWords << 26 << 31 << false;
+ QTest::newRow("<(the )>quick|words")
+ << standard[0] << 0 << 4 << QQuickTextEdit::SelectWords << 0 << 4 << false;
+ QTest::newRow("<(the )quick>|words,reversed")
+ << standard[0] << 4 << 0 << QQuickTextEdit::SelectWords << 0 << 9 << false;
+ QTest::newRow("<lazy( dog)>|words")
+ << standard[0] << 40 << 44 << QQuickTextEdit::SelectWords << 36 << 44 << false;
+ QTest::newRow("lazy<( dog)>|words,reversed")
+ << standard[0] << 44 << 40 << QQuickTextEdit::SelectWords << 40 << 44 << false;
+ QTest::newRow("<fox( jumped )>over|words")
+ << standard[0] << 19 << 27 << QQuickTextEdit::SelectWords << 16 << 27 << false;
+ QTest::newRow("fox<( jumped )over>|words,reversed")
+ << standard[0] << 27 << 19 << QQuickTextEdit::SelectWords << 19 << 31 << false;
+ QTest::newRow("<th(e qu)ick>|words")
+ << standard[0] << 2 << 6 << QQuickTextEdit::SelectWords << 0 << 9 << true;
+ QTest::newRow("<la(zy d)og|words>")
+ << standard[0] << 38 << 42 << QQuickTextEdit::SelectWords << 36 << 44 << true;
+ QTest::newRow("<jum(ped ov)er>|words")
+ << standard[0] << 23 << 29 << QQuickTextEdit::SelectWords << 20 << 31 << true;
+ QTest::newRow("<()>the|words")
+ << standard[0] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
+ QTest::newRow("dog<()>|words")
+ << standard[0] << 44 << 44 << QQuickTextEdit::SelectWords << 44 << 44 << true;
+ QTest::newRow("jum<()>ped|words")
+ << standard[0] << 23 << 23 << QQuickTextEdit::SelectWords << 23 << 23 << true;
+
+ QTest::newRow("Hello<(,)> |words")
+ << standard[2] << 5 << 6 << QQuickTextEdit::SelectWords << 5 << 6 << true;
+ QTest::newRow("Hello<(, )>world|words")
+ << standard[2] << 5 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
+ QTest::newRow("Hello<(, )world>|words,reversed")
+ << standard[2] << 7 << 5 << QQuickTextEdit::SelectWords << 5 << 12 << false;
+ QTest::newRow("<Hel(lo, )>world|words")
+ << standard[2] << 3 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
+ QTest::newRow("<Hel(lo, )world>|words,reversed")
+ << standard[2] << 7 << 3 << QQuickTextEdit::SelectWords << 0 << 12 << false;
+ QTest::newRow("<Hel(lo)>,|words")
+ << standard[2] << 3 << 5 << QQuickTextEdit::SelectWords << 0 << 5 << true;
+ QTest::newRow("Hello<()>,|words")
+ << standard[2] << 5 << 5 << QQuickTextEdit::SelectWords << 5 << 5 << true;
+ QTest::newRow("Hello,<()>|words")
+ << standard[2] << 6 << 6 << QQuickTextEdit::SelectWords << 6 << 6 << true;
+ QTest::newRow("Hello<,( )>world|words")
+ << standard[2] << 6 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
+ QTest::newRow("Hello,<( )world>|words,reversed")
+ << standard[2] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
+ QTest::newRow("Hello<,( world)>|words")
+ << standard[2] << 6 << 12 << QQuickTextEdit::SelectWords << 5 << 12 << false;
+ QTest::newRow("Hello,<( world)>|words,reversed")
+ << standard[2] << 12 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
+ QTest::newRow("Hello<,( world!)>|words")
+ << standard[2] << 6 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << false;
+ QTest::newRow("Hello,<( world!)>|words,reversed")
+ << standard[2] << 13 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
+ QTest::newRow("Hello<(, world!)>|words")
+ << standard[2] << 5 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << true;
+ QTest::newRow("world<(!)>|words")
+ << standard[2] << 12 << 13 << QQuickTextEdit::SelectWords << 12 << 13 << true;
+ QTest::newRow("world!<()>)|words")
+ << standard[2] << 13 << 13 << QQuickTextEdit::SelectWords << 13 << 13 << true;
+ QTest::newRow("world<()>!)|words")
+ << standard[2] << 12 << 12 << QQuickTextEdit::SelectWords << 12 << 12 << true;
+
+ QTest::newRow("<(,)>olleH |words")
+ << standard[3] << 7 << 8 << QQuickTextEdit::SelectWords << 7 << 8 << true;
+ QTest::newRow("<dlrow( ,)>olleH|words")
+ << standard[3] << 6 << 8 << QQuickTextEdit::SelectWords << 1 << 8 << false;
+ QTest::newRow("dlrow<( ,)>olleH|words,reversed")
+ << standard[3] << 8 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
+ QTest::newRow("<dlrow( ,ol)leH>|words")
+ << standard[3] << 6 << 10 << QQuickTextEdit::SelectWords << 1 << 13 << false;
+ QTest::newRow("dlrow<( ,ol)leH>|words,reversed")
+ << standard[3] << 10 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
+ QTest::newRow(",<(ol)leH>,|words")
+ << standard[3] << 8 << 10 << QQuickTextEdit::SelectWords << 8 << 13 << true;
+ QTest::newRow(",<()>olleH|words")
+ << standard[3] << 8 << 8 << QQuickTextEdit::SelectWords << 8 << 8 << true;
+ QTest::newRow("<()>,olleH|words")
+ << standard[3] << 7 << 7 << QQuickTextEdit::SelectWords << 7 << 7 << true;
+ QTest::newRow("<dlrow( )>,olleH|words")
+ << standard[3] << 6 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
+ QTest::newRow("dlrow<( ),>olleH|words,reversed")
+ << standard[3] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
+ QTest::newRow("<(dlrow )>,olleH|words")
+ << standard[3] << 1 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
+ QTest::newRow("<(dlrow ),>olleH|words,reversed")
+ << standard[3] << 7 << 1 << QQuickTextEdit::SelectWords << 1 << 8 << false;
+ QTest::newRow("<(!dlrow )>,olleH|words")
+ << standard[3] << 0 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
+ QTest::newRow("<(!dlrow ),>olleH|words,reversed")
+ << standard[3] << 7 << 0 << QQuickTextEdit::SelectWords << 0 << 8 << false;
+ QTest::newRow("(!dlrow ,)olleH|words")
+ << standard[3] << 0 << 8 << QQuickTextEdit::SelectWords << 0 << 8 << true;
+ QTest::newRow("<(!)>dlrow|words")
+ << standard[3] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 1 << true;
+ QTest::newRow("<()>!dlrow|words")
+ << standard[3] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
+ QTest::newRow("!<()>dlrow|words")
+ << standard[3] << 1 << 1 << QQuickTextEdit::SelectWords << 1 << 1 << true;
+}
+
+void tst_qquicktextedit::moveCursorSelection()
+{
+ QFETCH(QString, testStr);
+ QFETCH(int, cursorPosition);
+ QFETCH(int, movePosition);
+ QFETCH(QQuickTextEdit::SelectionMode, mode);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(bool, reversible);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(textinputComponent.create());
+ QVERIFY(texteditObject != 0);
+
+ texteditObject->setCursorPosition(cursorPosition);
+ texteditObject->moveCursorSelection(movePosition, mode);
+
+ QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
+ QCOMPARE(texteditObject->selectionStart(), selectionStart);
+ QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
+
+ if (reversible) {
+ texteditObject->setCursorPosition(movePosition);
+ texteditObject->moveCursorSelection(cursorPosition, mode);
+
+ QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
+ QCOMPARE(texteditObject->selectionStart(), selectionStart);
+ QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
+ }
+}
+
+void tst_qquicktextedit::moveCursorSelectionSequence_data()
+{
+ QTest::addColumn<QString>("testStr");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<int>("movePosition1");
+ QTest::addColumn<int>("movePosition2");
+ QTest::addColumn<int>("selection1Start");
+ QTest::addColumn<int>("selection1End");
+ QTest::addColumn<int>("selection2Start");
+ QTest::addColumn<int>("selection2End");
+
+ QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 17
+ << 4 << 15
+ << 4 << 19;
+ QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 17
+ << 9 << 15
+ << 10 << 19;
+ QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 16
+ << 4 << 15
+ << 4 << 16;
+ QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 16
+ << 9 << 15
+ << 10 << 16;
+ QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 15
+ << 4 << 15
+ << 4 << 15;
+ QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 15
+ << 9 << 15
+ << 10 << 15;
+ QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 10
+ << 4 << 15
+ << 4 << 10;
+ QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl")
+ << standard[0]
+ << 13 << 9 << 10
+ << 9 << 15
+ << 10 << 15;
+ QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 9
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
+ << standard[0]
+ << 13 << 9 << 9
+ << 9 << 15
+ << 9 << 15;
+ QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 7
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 7
+ << 9 << 15
+ << 4 << 15;
+ QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 4
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 4
+ << 9 << 15
+ << 4 << 15;
+ QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 3
+ << 4 << 15
+ << 3 << 9;
+ QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 3
+ << 9 << 15
+ << 3 << 15;
+ QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 1
+ << 4 << 15
+ << 0 << 9;
+ QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 1
+ << 9 << 15
+ << 0 << 15;
+
+ QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
+ << standard[2]
+ << 2 << 4 << 8
+ << 0 << 5
+ << 0 << 12;
+ QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
+ << standard[2]
+ << 4 << 2 << 8
+ << 0 << 5
+ << 0 << 12;
+
+ QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
+ << standard[3]
+ << 9 << 11 << 5
+ << 8 << 13
+ << 1 << 13;
+ QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
+ << standard[3]
+ << 11 << 9 << 5
+ << 8 << 13
+ << 1 << 13;
+}
+
+void tst_qquicktextedit::moveCursorSelectionSequence()
+{
+ QFETCH(QString, testStr);
+ QFETCH(int, cursorPosition);
+ QFETCH(int, movePosition1);
+ QFETCH(int, movePosition2);
+ QFETCH(int, selection1Start);
+ QFETCH(int, selection1End);
+ QFETCH(int, selection2Start);
+ QFETCH(int, selection2End);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(texteditObject != 0);
+
+ texteditObject->setCursorPosition(cursorPosition);
+
+ texteditObject->moveCursorSelection(movePosition1, QQuickTextEdit::SelectWords);
+ QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
+ QCOMPARE(texteditObject->selectionStart(), selection1Start);
+ QCOMPARE(texteditObject->selectionEnd(), selection1End);
+
+ texteditObject->moveCursorSelection(movePosition2, QQuickTextEdit::SelectWords);
+ QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
+ QCOMPARE(texteditObject->selectionStart(), selection2Start);
+ QCOMPARE(texteditObject->selectionEnd(), selection2End);
+}
+
+
+void tst_qquicktextedit::mouseSelection_data()
+{
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<QString>("selectedText");
+
+ // import installed
+ QTest::newRow("on") << TESTDATA("mouseselection_true.qml") << 4 << 9 << "45678";
+ QTest::newRow("off") << TESTDATA("mouseselection_false.qml") << 4 << 9 << QString();
+ QTest::newRow("default") << TESTDATA("mouseselection_default.qml") << 4 << 9 << QString();
+ QTest::newRow("off word selection") << TESTDATA("mouseselection_false_words.qml") << 4 << 9 << QString();
+ QTest::newRow("on word selection (4,9)") << TESTDATA("mouseselection_true_words.qml") << 4 << 9 << "0123456789";
+ QTest::newRow("on word selection (2,13)") << TESTDATA("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (2,30)") << TESTDATA("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,13)") << TESTDATA("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,30)") << TESTDATA("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (13,2)") << TESTDATA("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (20,2)") << TESTDATA("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (12,9)") << TESTDATA("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (30,9)") << TESTDATA("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+}
+
+void tst_qquicktextedit::mouseSelection()
+{
+ QFETCH(QString, qmlfile);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(QString, selectedText);
+
+ QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(textEditObject != 0);
+
+ // press-and-drag-and-release from x1 to x2
+ QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
+ QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
+ QTest::mouseMove(&canvas, p2);
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
+ QTest::qWait(50);
+ QTRY_COMPARE(textEditObject->selectedText(), selectedText);
+
+ // 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);
+ QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
+ QTest::qWait(50);
+ QTRY_COMPARE(textEditObject->selectedText(), selectedText);
+}
+
+void tst_qquicktextedit::dragMouseSelection()
+{
+ QString qmlfile = TESTDATA("mouseselection_true.qml");
+
+ QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(textEditObject != 0);
+
+ // press-and-drag-and-release from x1 to x2
+ int x1 = 10;
+ int x2 = 70;
+ int y = textEditObject->height()/2;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2, y));
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::qWait(300);
+ QString str1;
+ QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
+
+ // press and drag the current selection.
+ x1 = 40;
+ x2 = 100;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2, y));
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::qWait(300);
+ QString str2;
+ QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
+
+ QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and not the first moved.
+}
+
+void tst_qquicktextedit::mouseSelectionMode_data()
+{
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<bool>("selectWords");
+
+ // import installed
+ QTest::newRow("SelectWords") << TESTDATA("mouseselectionmode_words.qml") << true;
+ QTest::newRow("SelectCharacters") << TESTDATA("mouseselectionmode_characters.qml") << false;
+ QTest::newRow("default") << TESTDATA("mouseselectionmode_default.qml") << false;
+}
+
+void tst_qquicktextedit::mouseSelectionMode()
+{
+ QFETCH(QString, qmlfile);
+ QFETCH(bool, selectWords);
+
+ QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(textEditObject != 0);
+
+ // press-and-drag-and-release from x1 to x2
+ int x1 = 10;
+ int x2 = 70;
+ int y = textEditObject->height()/2;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2, y));
+ //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
+// QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+// QGuiApplication::sendEvent(&canvas, &mv);
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QString str = textEditObject->selectedText();
+ if (selectWords) {
+ QTRY_COMPARE(textEditObject->selectedText(), text);
+ } else {
+ QTRY_VERIFY(textEditObject->selectedText().length() > 3);
+ QVERIFY(str != text);
+ }
+}
+
+void tst_qquicktextedit::inputMethodHints()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("inputmethodhints.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
+ textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
+ QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
+}
+
+void tst_qquicktextedit::positionAt()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
+ QVERIFY(canvas.rootObject() != 0);
+ canvas.show();
+ canvas.requestActivateWindow();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(texteditObject != 0);
+
+ QFontMetrics fm(texteditObject->font());
+ const int y0 = fm.height() / 2;
+ const int y1 = fm.height() * 3 / 2;
+
+ int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
+ int widthBegin = 0;
+ int widthEnd = 0;
+ if (!qmlDisableDistanceField()) {
+ QTextLayout layout(texteditObject->text());
+
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ widthBegin = floor(line.cursorToX(pos - 1));
+ widthEnd = ceil(line.cursorToX(pos + 1));
+ } else {
+ widthBegin = fm.width(texteditObject->text().left(pos - 1));
+ widthEnd = fm.width(texteditObject->text().left(pos + 1));
+ }
+
+ QVERIFY(widthBegin <= texteditObject->width() / 2);
+ QVERIFY(widthEnd >= texteditObject->width() / 2);
+
+ const qreal x0 = texteditObject->positionToRectangle(pos).x();
+ const qreal x1 = texteditObject->positionToRectangle(pos + 1).x();
+
+ QString preeditText = texteditObject->text().mid(0, pos);
+ texteditObject->setText(texteditObject->text().mid(pos));
+ texteditObject->setCursorPosition(0);
+
+ QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent);
+
+ // Check all points within the preedit text return the same position.
+ QCOMPARE(texteditObject->positionAt(0, y0), 0);
+ QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0);
+ QCOMPARE(texteditObject->positionAt(x0, y0), 0);
+
+ // Verify positioning returns to normal after the preedit text.
+ QCOMPARE(texteditObject->positionAt(x1, y0), 1);
+ QCOMPARE(texteditObject->positionToRectangle(1).x(), x1);
+
+ QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0);
+}
+
+void tst_qquicktextedit::cursorDelegate()
+{
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorTest.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+ QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+ //Test Delegate gets created
+ textEditObject->setFocus(true);
+ QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance");
+ QVERIFY(delegateObject);
+ QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
+ //Test Delegate gets moved
+ for (int i=0; i<= textEditObject->text().length(); i++) {
+ textEditObject->setCursorPosition(i);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+ }
+ // Clear preedit text;
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(&view, &event);
+
+
+ // Test delegate gets moved on mouse press.
+ textEditObject->setSelectByMouse(true);
+ textEditObject->setCursorPosition(0);
+ const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
+ QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
+ QTest::qWait(50);
+ QTRY_VERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ // Test delegate gets moved on mouse drag
+ textEditObject->setCursorPosition(0);
+ const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
+ QTest::mousePress(&view, Qt::LeftButton, 0, point1);
+ QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QGuiApplication::sendEvent(&view, &mv);
+ QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
+ QTest::qWait(50);
+ QTRY_COMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setReadOnly(true);
+ textEditObject->setCursorPosition(0);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QTest::qWait(50);
+ QTRY_VERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setCursorPosition(0);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QTest::qWait(50);
+ QTRY_VERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setCursorPosition(0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+ //Test Delegate gets deleted
+ textEditObject->setCursorDelegate(0);
+ QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+}
+
+void tst_qquicktextedit::cursorVisible()
+{
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorVisible.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QQuickTextEdit edit;
+ QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
+
+ QCOMPARE(edit.isCursorVisible(), false);
+
+ edit.setCursorVisible(true);
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 1);
+
+ edit.setCursorVisible(false);
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 2);
+
+ edit.setFocus(true);
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 2);
+
+ edit.setParentItem(view.rootObject());
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 3);
+
+ edit.setFocus(false);
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 4);
+
+ edit.setFocus(true);
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 5);
+
+ QQuickView alternateView;
+ alternateView.show();
+ alternateView.requestActivateWindow();
+ QTest::qWaitForWindowShown(&alternateView);
+
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 6);
+
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 7);
+}
+
+void tst_qquicktextedit::delegateLoading_data()
+{
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QString>("error");
+
+ // import installed
+ QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
+ QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
+ QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
+}
+
+void tst_qquicktextedit::delegateLoading()
+{
+ QFETCH(QString, qmlfile);
+ QFETCH(QString, error);
+
+ TestHTTPServer server(42332);
+ server.serveDirectory(TESTDATA("httpfail"), TestHTTPServer::Disconnect);
+ server.serveDirectory(TESTDATA("httpslow"), TestHTTPServer::Delay);
+ server.serveDirectory(TESTDATA("http"));
+
+ QQuickView view(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
+ view.show();
+ view.requestActivateWindow();
+
+ if (!error.isEmpty()) {
+ QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
+ QTRY_VERIFY(view.status()==QQuickView::Error);
+ QTRY_VERIFY(!view.rootObject()); // there is fail item inside this test
+ } else {
+ QTRY_VERIFY(view.rootObject());//Wait for loading to finish.
+ QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+ // view.rootObject()->dumpObjectTree();
+ QVERIFY(textEditObject != 0);
+ textEditObject->setFocus(true);
+ QQuickItem *delegate;
+ delegate = view.rootObject()->findChild<QQuickItem*>("delegateOkay");
+ QVERIFY(delegate);
+ delegate = view.rootObject()->findChild<QQuickItem*>("delegateSlow");
+ QVERIFY(delegate);
+
+ delete delegate;
+ }
+
+
+ //A test should be added here with a component which is ready but component.create() returns null
+ //Not sure how to accomplish this with QQuickTextEdits cursor delegate
+ //###This was only needed for code coverage, and could be a case of overzealous defensive programming
+ //delegate = view.rootObject()->findChild<QQuickItem*>("delegateErrorB");
+ //QVERIFY(!delegate);
+}
+
+/*
+TextEdit element should only handle left/right keys until the cursor reaches
+the extent of the text, then they should ignore the keys.
+*/
+void tst_qquicktextedit::navigation()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickItem *input = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == false);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == true);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == true);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == false);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == true);
+}
+
+void tst_qquicktextedit::copyAndPaste() {
+#ifndef QT_NO_CLIPBOARD
+
+#ifdef Q_OS_MAC
+ {
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ else
+ QSKIP("This machine doesn't support the clipboard");
+ }
+#endif
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ // copy and paste
+ QCOMPARE(textEdit->text().length(), 12);
+ textEdit->select(0, textEdit->text().length());;
+ textEdit->copy();
+ QCOMPARE(textEdit->selectedText(), QString("Hello world!"));
+ QCOMPARE(textEdit->selectedText().length(), 12);
+ textEdit->setCursorPosition(0);
+ QVERIFY(textEdit->canPaste());
+ textEdit->paste();
+ QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textEdit->text().length(), 24);
+
+ // canPaste
+ QVERIFY(textEdit->canPaste());
+ textEdit->setReadOnly(true);
+ QVERIFY(!textEdit->canPaste());
+ textEdit->setReadOnly(false);
+ QVERIFY(textEdit->canPaste());
+
+ // QTBUG-12339
+ // test that document and internal text attribute are in sync
+ QQuickItemPrivate* pri = QQuickItemPrivate::get(textEdit);
+ QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(pri);
+ QCOMPARE(textEdit->text(), editPrivate->text);
+
+ // select word
+ textEdit->setCursorPosition(0);
+ textEdit->selectWord();
+ QCOMPARE(textEdit->selectedText(), QString("Hello"));
+
+ // select all and cut
+ textEdit->selectAll();
+ textEdit->cut();
+ QCOMPARE(textEdit->text().length(), 0);
+ textEdit->paste();
+ QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textEdit->text().length(), 24);
+#endif
+}
+
+void tst_qquicktextedit::canPaste() {
+#ifndef QT_NO_CLIPBOARD
+
+ QGuiApplication::clipboard()->setText("Some text");
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ // check initial value - QTBUG-17765
+ QTextControl tc;
+ QCOMPARE(textEdit->canPaste(), tc.canPaste());
+
+#endif
+}
+
+void tst_qquicktextedit::canPasteEmpty() {
+#ifndef QT_NO_CLIPBOARD
+
+ QGuiApplication::clipboard()->clear();
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ // check initial value - QTBUG-17765
+ QTextControl tc;
+ QCOMPARE(textEdit->canPaste(), tc.canPaste());
+
+#endif
+}
+
+void tst_qquicktextedit::readOnly()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("readOnly.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(edit != 0);
+ QTRY_VERIFY(edit->hasActiveFocus() == true);
+ QVERIFY(edit->isReadOnly() == true);
+ QString initial = edit->text();
+ for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
+ simulateKey(&canvas, k);
+ simulateKey(&canvas, Qt::Key_Return);
+ simulateKey(&canvas, Qt::Key_Space);
+ simulateKey(&canvas, Qt::Key_Escape);
+ QCOMPARE(edit->text(), initial);
+
+ edit->setCursorPosition(3);
+ edit->setReadOnly(false);
+ QCOMPARE(edit->isReadOnly(), false);
+ QCOMPARE(edit->cursorPosition(), edit->text().length());
+}
+
+void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers)
+{
+ QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
+ QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
+
+ QGuiApplication::sendEvent(view, &press);
+ QGuiApplication::sendEvent(view, &release);
+}
+
+void tst_qquicktextedit::textInput()
+{
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QVERIFY(edit);
+ QVERIFY(edit->hasActiveFocus() == true);
+
+ // test that input method event is committed
+ QInputMethodEvent event;
+ event.setCommitString( "Hello world!", 0, 0);
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+ QCOMPARE(edit->text(), QString("Hello world!"));
+
+ // QTBUG-12339
+ // test that document and internal text attribute are in sync
+ QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(edit));
+ QCOMPARE(editPrivate->text, QString("Hello world!"));
+}
+
+class PlatformInputContext : public QPlatformInputContext
+{
+public:
+ PlatformInputContext() : m_visible(false) {}
+
+ virtual void showInputPanel()
+ {
+ m_visible = true;
+ }
+ virtual void hideInputPanel()
+ {
+ m_visible = false;
+ }
+ virtual bool isInputPanelVisible() const
+ {
+ return m_visible;
+ }
+
+ bool m_visible;
+};
+
+void tst_qquicktextedit::openInputPanel()
+{
+ PlatformInputContext platformInputContext;
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = &platformInputContext;
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("openInputPanel.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QVERIFY(edit);
+
+ // check default values
+ QVERIFY(edit->focusOnPress());
+ QVERIFY(!edit->hasActiveFocus());
+ qDebug() << &edit << qApp->inputPanel()->inputItem();
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should open on focus
+ QPoint centerPoint(view.width()/2, view.height()/2);
+ Qt::KeyboardModifiers noModifiers = 0;
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QVERIFY(edit->hasActiveFocus());
+ QCOMPARE(qApp->inputPanel()->inputItem(), edit);
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+
+ // input panel should be re-opened when pressing already focused TextEdit
+ qApp->inputPanel()->hide();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QVERIFY(edit->hasActiveFocus());
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+
+ // input panel should stay visible if focus is lost to another text editor
+ QSignalSpy inputPanelVisibilitySpy(qApp->inputPanel(), SIGNAL(visibleChanged()));
+ QQuickTextEdit anotherEdit;
+ anotherEdit.setParentItem(view.rootObject());
+ anotherEdit.setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QCOMPARE(qApp->inputPanel()->inputItem(), qobject_cast<QObject*>(&anotherEdit));
+ QCOMPARE(inputPanelVisibilitySpy.count(), 0);
+
+ anotherEdit.setFocus(false);
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+ QCOMPARE(view.activeFocusItem(), view.rootItem());
+ anotherEdit.setFocus(true);
+
+ // input item should be null if focus is lost to an item that doesn't accept inputs
+ QQuickItem item;
+ item.setParentItem(view.rootObject());
+ item.setFocus(true);
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+ QCOMPARE(view.activeFocusItem(), &item);
+
+ qApp->inputPanel()->hide();
+
+ // input panel should not be opened if TextEdit is read only
+ edit->setReadOnly(true);
+ edit->setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should not be opened if focusOnPress is set to false
+ edit->setFocusOnPress(false);
+ edit->setFocus(false);
+ edit->setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should open when openSoftwareInputPanel is called
+ edit->openSoftwareInputPanel();
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+
+ // input panel should close when closeSoftwareInputPanel is called
+ edit->closeSoftwareInputPanel();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ inputPanelPrivate->testContext = 0;
+}
+
+void tst_qquicktextedit::geometrySignals()
+{
+ QDeclarativeComponent component(&engine, TESTDATA("geometrySignals.qml"));
+ QObject *o = component.create();
+ QVERIFY(o);
+ QCOMPARE(o->property("bindingWidth").toInt(), 400);
+ QCOMPARE(o->property("bindingHeight").toInt(), 500);
+ delete o;
+}
+
+void tst_qquicktextedit::pastingRichText_QTBUG_14003()
+{
+#ifndef QT_NO_CLIPBOARD
+ QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.PlainText }";
+ QDeclarativeComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(component.create());
+
+ QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
+
+ QMimeData *mData = new QMimeData;
+ mData->setHtml("<font color=\"red\">Hello</font>");
+ QGuiApplication::clipboard()->setMimeData(mData);
+
+ obj->paste();
+ QTRY_VERIFY(obj->text() == "");
+ QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
+#endif
+}
+
+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";
+}
+
+void tst_qquicktextedit::implicitSize()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(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_qquicktextedit::testQtQuick11Attributes()
+{
+ QFETCH(QString, code);
+ QFETCH(QString, warning);
+ QFETCH(QString, error);
+
+ QDeclarativeEngine engine;
+ QObject *obj;
+
+ QDeclarativeComponent valid(&engine);
+ valid.setData("import QtQuick 2.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
+ obj = valid.create();
+ QVERIFY(obj);
+ QVERIFY(valid.errorString().isEmpty());
+ delete obj;
+
+ QDeclarativeComponent invalid(&engine);
+ invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
+ QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
+ obj = invalid.create();
+ QCOMPARE(invalid.errorString(), error);
+ delete obj;
+}
+
+void tst_qquicktextedit::testQtQuick11Attributes_data()
+{
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("warning");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("canPaste") << "property bool foo: canPaste"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
+ << "";
+
+ QTest::newRow("lineCount") << "property int foo: lineCount"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount"
+ << "";
+
+ QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
+ << "";
+
+ QTest::newRow("deselect") << "Component.onCompleted: deselect()"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
+ << "";
+
+ QTest::newRow("onLinkActivated") << "onLinkActivated: {}"
+ << "QDeclarativeComponent: Component is not ready"
+ << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n";
+}
+
+void tst_qquicktextedit::preeditCursorRectangle()
+{
+ QString preeditText = "super";
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QVERIFY(edit);
+
+ QSignalSpy editSpy(edit, SIGNAL(cursorRectangleChanged()));
+ QSignalSpy panelSpy(qGuiApp->inputPanel(), SIGNAL(cursorRectangleChanged()));
+
+ QRect currentRect;
+
+ QInputMethodQueryEvent query(Qt::ImCursorRectangle);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
+
+ // Verify that the micro focus rect is positioned the same for position 0 as
+ // it would be if there was no preedit text.
+ QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCOMPARE(currentRect, previousRect);
+ QCOMPARE(editSpy.count(), 0);
+ QCOMPARE(panelSpy.count(), 0);
+
+ // Verify that the micro focus rect moves to the left as the cursor position
+ // is incremented.
+ for (int i = 1; i <= 5; ++i) {
+ QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QVERIFY(previousRect.left() < currentRect.left());
+ QVERIFY(editSpy.count() > 0); editSpy.clear();
+ QVERIFY(panelSpy.count() > 0); panelSpy.clear();
+ previousRect = currentRect;
+ }
+
+ // Verify that if there is no preedit cursor then the micro focus rect is the
+ // same as it would be if it were positioned at the end of the preedit text.
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+ editSpy.clear();
+ panelSpy.clear();
+ { QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent); }
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCOMPARE(currentRect, previousRect);
+ QVERIFY(editSpy.count() > 0);
+ QVERIFY(panelSpy.count() > 0);
+}
+
+void tst_qquicktextedit::inputMethodComposing()
+{
+ QString text = "supercalifragisiticexpialidocious!";
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
+ QVERIFY(edit);
+ QSignalSpy spy(edit, SIGNAL(inputMethodComposingChanged()));
+ edit->setCursorPosition(12);
+
+ QCOMPARE(edit->isInputMethodComposing(), false);
+
+ {
+ QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(edit, &event);
+ }
+
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 1);
+
+ {
+ QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(spy.count(), 1);
+
+ {
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_qquicktextedit::cursorRectangleSize()
+{
+ QQuickView *canvas = new QQuickView(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
+ QVERIFY(canvas->rootObject() != 0);
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(canvas->rootObject());
+
+ // make sure cursor rectangle is not at (0,0)
+ textEdit->setX(10);
+ textEdit->setY(10);
+ textEdit->setCursorPosition(3);
+ QVERIFY(textEdit != 0);
+ textEdit->setFocus(true);
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+
+ QInputMethodQueryEvent event(Qt::ImCursorRectangle);
+ qApp->sendEvent(qApp->inputPanel()->inputItem(), &event);
+ QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
+
+ QRect cursorRectFromItem = textEdit->cursorRectangle();
+ QRectF cursorRectFromPositionToRectangle = textEdit->positionToRectangle(textEdit->cursorPosition());
+
+ // item and input query cursor rectangles match
+ QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
+
+ // item cursor rectangle and positionToRectangle calculations match
+ QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
+
+ // item-canvas transform and input item transform match
+ QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToCanvasTransform(), qApp->inputPanel()->inputItemTransform());
+
+ // input panel cursorRectangle property and tranformed item cursor rectangle match
+ QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToCanvasTransform().mapRect(cursorRectFromItem);
+ QCOMPARE(sceneCursorRect, qApp->inputPanel()->cursorRectangle());
+
+ delete canvas;
+}
+
+void tst_qquicktextedit::getText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("end");
+ QTest::addColumn<QString>("expectedText");
+
+ const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
+ const QString plainBoldText = QStringLiteral("This is some bold text");
+
+ QTest::newRow("all plain text")
+ << standard.at(0)
+ << 0 << standard.at(0).length()
+ << standard.at(0);
+
+ QTest::newRow("plain text sub string")
+ << standard.at(0)
+ << 0 << 12
+ << standard.at(0).mid(0, 12);
+
+ QTest::newRow("plain text sub string reversed")
+ << standard.at(0)
+ << 12 << 0
+ << standard.at(0).mid(0, 12);
+
+ QTest::newRow("plain text cropped beginning")
+ << standard.at(0)
+ << -3 << 4
+ << standard.at(0).mid(0, 4);
+
+ QTest::newRow("plain text cropped end")
+ << standard.at(0)
+ << 23 << standard.at(0).length() + 8
+ << standard.at(0).mid(23);
+
+ QTest::newRow("plain text cropped beginning and end")
+ << standard.at(0)
+ << -9 << standard.at(0).length() + 4
+ << standard.at(0);
+
+ QTest::newRow("all rich text")
+ << richBoldText
+ << 0 << plainBoldText.length()
+ << plainBoldText;
+
+ QTest::newRow("rich text sub string")
+ << richBoldText
+ << 14 << 21
+ << plainBoldText.mid(14, 7);
+}
+
+void tst_qquicktextedit::getText()
+{
+ QFETCH(QString, text);
+ QFETCH(int, start);
+ QFETCH(int, end);
+ QFETCH(QString, expectedText);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ QCOMPARE(textEdit->getText(start, end), expectedText);
+}
+
+void tst_qquicktextedit::getFormattedText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("end");
+ QTest::addColumn<QString>("expectedText");
+
+ const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
+ const QString plainBoldText = QStringLiteral("This is some bold text");
+
+ QTest::newRow("all plain text")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << 0 << standard.at(0).length()
+ << standard.at(0);
+
+ QTest::newRow("plain text sub string")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << 0 << 12
+ << standard.at(0).mid(0, 12);
+
+ QTest::newRow("plain text sub string reversed")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << 12 << 0
+ << standard.at(0).mid(0, 12);
+
+ QTest::newRow("plain text cropped beginning")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << -3 << 4
+ << standard.at(0).mid(0, 4);
+
+ QTest::newRow("plain text cropped end")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << 23 << standard.at(0).length() + 8
+ << standard.at(0).mid(23);
+
+ QTest::newRow("plain text cropped beginning and end")
+ << standard.at(0)
+ << QQuickTextEdit::PlainText
+ << -9 << standard.at(0).length() + 4
+ << standard.at(0);
+
+ QTest::newRow("all rich (Auto) text")
+ << richBoldText
+ << QQuickTextEdit::AutoText
+ << 0 << plainBoldText.length()
+ << QString("This is some \\<.*\\>bold\\</.*\\> text");
+
+ QTest::newRow("all rich (Rich) text")
+ << richBoldText
+ << QQuickTextEdit::RichText
+ << 0 << plainBoldText.length()
+ << QString("This is some \\<.*\\>bold\\</.*\\> text");
+
+ QTest::newRow("all rich (Plain) text")
+ << richBoldText
+ << QQuickTextEdit::PlainText
+ << 0 << richBoldText.length()
+ << richBoldText;
+
+ QTest::newRow("rich (Auto) text sub string")
+ << richBoldText
+ << QQuickTextEdit::AutoText
+ << 14 << 21
+ << QString("\\<.*\\>old\\</.*\\> tex");
+
+ QTest::newRow("rich (Rich) text sub string")
+ << richBoldText
+ << QQuickTextEdit::RichText
+ << 14 << 21
+ << QString("\\<.*\\>old\\</.*\\> tex");
+
+ QTest::newRow("rich (Plain) text sub string")
+ << richBoldText
+ << QQuickTextEdit::PlainText
+ << 17 << 27
+ << richBoldText.mid(17, 10);
+}
+
+void tst_qquicktextedit::getFormattedText()
+{
+ QFETCH(QString, text);
+ QFETCH(QQuickTextEdit::TextFormat, textFormat);
+ QFETCH(int, start);
+ QFETCH(int, end);
+ QFETCH(QString, expectedText);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit {}";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ textEdit->setTextFormat(textFormat);
+ textEdit->setText(text);
+
+ if (textFormat == QQuickTextEdit::RichText
+ || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
+ QVERIFY(textEdit->getFormattedText(start, end).contains(QRegExp(expectedText)));
+ } else {
+ QCOMPARE(textEdit->getFormattedText(start, end), expectedText);
+ }
+}
+
+void tst_qquicktextedit::insert_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<int>("insertPosition");
+ QTest::addColumn<QString>("insertText");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<int>("expectedSelectionStart");
+ QTest::addColumn<int>("expectedSelectionEnd");
+ QTest::addColumn<int>("expectedCursorPosition");
+ QTest::addColumn<bool>("selectionChanged");
+ QTest::addColumn<bool>("cursorPositionChanged");
+
+ QTest::newRow("at cursor position (beginning)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0 << 0
+ << QString("Hello")
+ << QString("Hello") + standard.at(0)
+ << 5 << 5 << 5
+ << false << true;
+
+ QTest::newRow("at cursor position (end)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << standard.at(0).length() << standard.at(0).length() << standard.at(0).length()
+ << QString("Hello")
+ << standard.at(0) + QString("Hello")
+ << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
+ << false << true;
+
+ QTest::newRow("at cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 18 << 18 << 18
+ << QString("Hello")
+ << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
+ << 23 << 23 << 23
+ << false << true;
+
+ QTest::newRow("after cursor position (beginning)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0 << 18
+ << QString("Hello")
+ << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("before cursor position (end)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << standard.at(0).length() << standard.at(0).length() << 18
+ << QString("Hello")
+ << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
+ << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
+ << false << true;
+
+ QTest::newRow("before cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 18 << 18 << 0
+ << QString("Hello")
+ << QString("Hello") + standard.at(0)
+ << 23 << 23 << 23
+ << false << true;
+
+ QTest::newRow("after cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 18 << 18 << standard.at(0).length()
+ << QString("Hello")
+ << standard.at(0) + QString("Hello")
+ << 18 << 18 << 18
+ << false << false;
+
+ QTest::newRow("before selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 19 << 0
+ << QString("Hello")
+ << QString("Hello") + standard.at(0)
+ << 19 << 24 << 24
+ << false << true;
+
+ QTest::newRow("before reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 19 << 14 << 0
+ << QString("Hello")
+ << QString("Hello") + standard.at(0)
+ << 19 << 24 << 19
+ << false << true;
+
+ QTest::newRow("after selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 19 << standard.at(0).length()
+ << QString("Hello")
+ << standard.at(0) + QString("Hello")
+ << 14 << 19 << 19
+ << false << false;
+
+ QTest::newRow("after reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 19 << 14 << standard.at(0).length()
+ << QString("Hello")
+ << standard.at(0) + QString("Hello")
+ << 14 << 19 << 14
+ << false << false;
+
+ QTest::newRow("into selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 19 << 18
+ << QString("Hello")
+ << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
+ << 14 << 24 << 24
+ << true << true;
+
+ QTest::newRow("into reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 19 << 14 << 18
+ << QString("Hello")
+ << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
+ << 14 << 24 << 14
+ << true << false;
+
+ QTest::newRow("rich text into plain text")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0 << 0
+ << QString("<b>Hello</b>")
+ << QString("<b>Hello</b>") + standard.at(0)
+ << 12 << 12 << 12
+ << false << true;
+
+ QTest::newRow("rich text into rich text")
+ << standard.at(0) << QQuickTextEdit::RichText
+ << 0 << 0 << 0
+ << QString("<b>Hello</b>")
+ << QString("Hello") + standard.at(0)
+ << 5 << 5 << 5
+ << false << true;
+
+ QTest::newRow("rich text into auto text")
+ << standard.at(0) << QQuickTextEdit::AutoText
+ << 0 << 0 << 0
+ << QString("<b>Hello</b>")
+ << QString("Hello") + standard.at(0)
+ << 5 << 5 << 5
+ << false << true;
+
+ QTest::newRow("before start")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0 << -3
+ << QString("Hello")
+ << standard.at(0)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("past end")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0 << standard.at(0).length() + 3
+ << QString("Hello")
+ << standard.at(0)
+ << 0 << 0 << 0
+ << false << false;
+}
+
+void tst_qquicktextedit::insert()
+{
+ QFETCH(QString, text);
+ QFETCH(QQuickTextEdit::TextFormat, textFormat);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(int, insertPosition);
+ QFETCH(QString, insertText);
+ QFETCH(QString, expectedText);
+ QFETCH(int, expectedSelectionStart);
+ QFETCH(int, expectedSelectionEnd);
+ QFETCH(int, expectedCursorPosition);
+ QFETCH(bool, selectionChanged);
+ QFETCH(bool, cursorPositionChanged);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ textEdit->setTextFormat(textFormat);
+ textEdit->select(selectionStart, selectionEnd);
+
+ QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+ QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
+ QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
+ QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString)));
+ QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
+
+ textEdit->insert(insertPosition, insertText);
+
+ if (textFormat == QQuickTextEdit::RichText || (textFormat == QQuickTextEdit::AutoText && (
+ Qt::mightBeRichText(text) || Qt::mightBeRichText(insertText)))) {
+ QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
+ } else {
+ QCOMPARE(textEdit->text(), expectedText);
+
+ }
+ QCOMPARE(textEdit->length(), expectedText.length());
+
+ QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
+ QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
+ QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
+
+ if (selectionStart > selectionEnd)
+ qSwap(selectionStart, selectionEnd);
+
+ QEXPECT_FAIL("into selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("into reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QCOMPARE(selectionSpy.count() > 0, selectionChanged);
+ QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
+ QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
+ QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
+ QCOMPARE(textSpy.count() > 0, text != expectedText);
+ QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
+}
+
+void tst_qquicktextedit::remove_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<int>("removeStart");
+ QTest::addColumn<int>("removeEnd");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<int>("expectedSelectionStart");
+ QTest::addColumn<int>("expectedSelectionEnd");
+ QTest::addColumn<int>("expectedCursorPosition");
+ QTest::addColumn<bool>("selectionChanged");
+ QTest::addColumn<bool>("cursorPositionChanged");
+
+ const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
+ const QString plainBoldText = QStringLiteral("This is some bold text");
+
+ QTest::newRow("from cursor position (beginning)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << 0 << 5
+ << standard.at(0).mid(5)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("to cursor position (beginning)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << 5 << 0
+ << standard.at(0).mid(5)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("to cursor position (end)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << standard.at(0).length() << standard.at(0).length()
+ << standard.at(0).length() << standard.at(0).length() - 5
+ << standard.at(0).mid(0, standard.at(0).length() - 5)
+ << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
+ << false << true;
+
+ QTest::newRow("to cursor position (end)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << standard.at(0).length() << standard.at(0).length()
+ << standard.at(0).length() - 5 << standard.at(0).length()
+ << standard.at(0).mid(0, standard.at(0).length() - 5)
+ << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
+ << false << true;
+
+ QTest::newRow("from cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 18 << 18
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 18 << 18 << 18
+ << false << false;
+
+ QTest::newRow("to cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 23 << 23
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 18 << 18 << 18
+ << false << true;
+
+ QTest::newRow("after cursor position (beginning)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("before cursor position (end)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << standard.at(0).length() << standard.at(0).length()
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
+ << false << true;
+
+ QTest::newRow("before cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 23 << 23
+ << 0 << 5
+ << standard.at(0).mid(5)
+ << 18 << 18 << 18
+ << false << true;
+
+ QTest::newRow("after cursor position (middle)")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 18 << 18
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 18 << 18 << 18
+ << false << false;
+
+ QTest::newRow("before selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 19
+ << 0 << 5
+ << standard.at(0).mid(5)
+ << 9 << 14 << 14
+ << false << true;
+
+ QTest::newRow("before reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 19 << 14
+ << 0 << 5
+ << standard.at(0).mid(5)
+ << 9 << 14 << 9
+ << false << true;
+
+ QTest::newRow("after selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 19
+ << standard.at(0).length() - 5 << standard.at(0).length()
+ << standard.at(0).mid(0, standard.at(0).length() - 5)
+ << 14 << 19 << 19
+ << false << false;
+
+ QTest::newRow("after reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 19 << 14
+ << standard.at(0).length() - 5 << standard.at(0).length()
+ << standard.at(0).mid(0, standard.at(0).length() - 5)
+ << 14 << 19 << 14
+ << false << false;
+
+ QTest::newRow("from selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 14 << 24
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 14 << 19 << 19
+ << true << true;
+
+ QTest::newRow("from reversed selection")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 24 << 14
+ << 18 << 23
+ << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
+ << 14 << 19 << 14
+ << true << false;
+
+ QTest::newRow("plain text cropped beginning")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << -3 << 4
+ << standard.at(0).mid(4)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("plain text cropped end")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << 23 << standard.at(0).length() + 8
+ << standard.at(0).mid(0, 23)
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("plain text cropped beginning and end")
+ << standard.at(0) << QQuickTextEdit::PlainText
+ << 0 << 0
+ << -9 << standard.at(0).length() + 4
+ << QString()
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("all rich text")
+ << richBoldText << QQuickTextEdit::RichText
+ << 0 << 0
+ << 0 << plainBoldText.length()
+ << QString()
+ << 0 << 0 << 0
+ << false << false;
+
+ QTest::newRow("rick text sub string")
+ << richBoldText << QQuickTextEdit::RichText
+ << 0 << 0
+ << 14 << 21
+ << plainBoldText.mid(0, 14) + plainBoldText.mid(21)
+ << 0 << 0 << 0
+ << false << false;
+}
+
+void tst_qquicktextedit::remove()
+{
+ QFETCH(QString, text);
+ QFETCH(QQuickTextEdit::TextFormat, textFormat);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(int, removeStart);
+ QFETCH(int, removeEnd);
+ QFETCH(QString, expectedText);
+ QFETCH(int, expectedSelectionStart);
+ QFETCH(int, expectedSelectionEnd);
+ QFETCH(int, expectedCursorPosition);
+ QFETCH(bool, selectionChanged);
+ QFETCH(bool, cursorPositionChanged);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ textEdit->setTextFormat(textFormat);
+ textEdit->select(selectionStart, selectionEnd);
+
+ QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+ QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
+ QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
+ QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString)));
+ QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
+
+ textEdit->remove(removeStart, removeEnd);
+
+ if (textFormat == QQuickTextEdit::RichText
+ || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
+ QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
+ } else {
+ QCOMPARE(textEdit->text(), expectedText);
+ }
+ QCOMPARE(textEdit->length(), expectedText.length());
+
+ if (selectionStart > selectionEnd) //
+ qSwap(selectionStart, selectionEnd);
+
+ QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
+ QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
+ QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
+
+ QEXPECT_FAIL("from selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("from reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QCOMPARE(selectionSpy.count() > 0, selectionChanged);
+ QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
+ QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
+ QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
+ QCOMPARE(textSpy.count() > 0, text != expectedText);
+
+
+ if (cursorPositionChanged) //
+ QVERIFY(cursorPositionSpy.count() > 0);
+}
+
+
+void tst_qquicktextedit::keySequence_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QKeySequence>("sequence");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("selectedText");
+
+ // 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);
+ QTest::newRow("select end of line")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
+ << 44 << standard.at(0) << standard.at(0).mid(5);
+ QTest::newRow("select end of document")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
+ << 44 << standard.at(0) << standard.at(0).mid(3);
+ QTest::newRow("select end of block")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
+ << 44 << standard.at(0) << standard.at(0).mid(18);
+ QTest::newRow("delete end of line")
+ << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
+ << 24 << standard.at(0).mid(0, 24) << QString();
+ QTest::newRow("move to start of line")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
+ << 0 << standard.at(0) << QString();
+ QTest::newRow("move to start of block")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
+ << 0 << standard.at(0) << QString();
+ 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")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
+ << 2 << standard.at(0) << QString();
+ QTest::newRow("select next char")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
+ << 24 << standard.at(0) << standard.at(0).mid(23, 1);
+ QTest::newRow("select previous char")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
+ << 18 << standard.at(0) << standard.at(0).mid(18, 1);
+ QTest::newRow("move to next word")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 10 << standard.at(0) << QString();
+ QTest::newRow("move to previous word")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 4 << standard.at(0) << QString();
+ QTest::newRow("select previous word")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
+ << 10 << standard.at(0) << standard.at(0).mid(10, 1);
+ 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();
+ 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();
+ 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();
+ 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();
+}
+
+void tst_qquicktextedit::keySequence()
+{
+ QFETCH(QString, text);
+ QFETCH(QKeySequence, sequence);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(int, cursorPosition);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, selectedText);
+
+ if (sequence.isEmpty()) {
+ QSKIP("Key sequence is undefined");
+ }
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; text: \"" + text + "\" }";
+ QDeclarativeComponent textEditComponent(&engine);
+ textEditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
+ QVERIFY(textEdit != 0);
+
+ QQuickCanvas canvas;
+ textEdit->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ textEdit->select(selectionStart, selectionEnd);
+
+ simulateKeys(&canvas, sequence);
+
+ QCOMPARE(textEdit->cursorPosition(), cursorPosition);
+ QCOMPARE(textEdit->text(), expectedText);
+ QCOMPARE(textEdit->selectedText(), selectedText);
+}
+
+#define NORMAL 0
+#define REPLACE_UNTIL_END 1
+
+void tst_qquicktextedit::undo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<IntList>("insertMode");
+ QTest::addColumn<QStringList>("expectedString");
+ QTest::addColumn<bool>("use_keys");
+
+ for (int i=0; i<2; i++) {
+ QString keys_str = "keyboard";
+ bool use_keys = true;
+ if (i==0) {
+ keys_str = "insert";
+ use_keys = false;
+ }
+
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "1";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "5";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "3";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "2";
+
+ insertIndex << 3;
+ insertMode << NORMAL;
+ insertString << "4";
+
+ expectedString << "12345";
+ expectedString << "1235";
+ expectedString << "135";
+ expectedString << "15";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "World"; // World
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Hello"; // HelloWorld
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Well"; // WellHelloWorld
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "WellHelloThereWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "HelloWorld";
+ expectedString << "World";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "Ensuring";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << " instan";
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "an ";
+
+ insertIndex << 10;
+ insertMode << REPLACE_UNTIL_END;
+ insertString << " unique instance.";
+
+ expectedString << "Ensuring a unique instance.";
+ expectedString << "Ensuring a "; // ### Not present in TextInput.
+ expectedString << "Ensuring an instan";
+ expectedString << "Ensuring instan";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ }
+}
+
+void tst_qquicktextedit::undo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(IntList, insertMode);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ int i;
+
+// STEP 1: First build up an undo history by inserting or typing some strings...
+ for (i = 0; i < insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ textInput->setCursorPosition(insertIndex[i]);
+
+ // experimental stuff
+ if (insertMode[i] == REPLACE_UNTIL_END) {
+ textInput->select(insertIndex[i], insertIndex[i] + 8);
+
+ // This is what I actually want...
+ // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
+ }
+
+ for (int j = 0; j < insertString.at(i).length(); j++)
+ QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ }
+
+// STEP 2: Next call undo several times and see if we can restore to the previous state
+ for (i = 0; i < expectedString.size() - 1; ++i) {
+ QCOMPARE(textInput->text(), expectedString[i]);
+ simulateKeys(&canvas, QKeySequence::Undo);
+ }
+
+// STEP 3: Verify that we have undone everything
+ QVERIFY(textInput->text().isEmpty());
+}
+
+void tst_qquicktextedit::redo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ IntList insertIndex;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertString << "World"; // World
+ insertIndex << 0;
+ insertString << "Hello"; // HelloWorld
+ insertIndex << 0;
+ insertString << "Well"; // WellHelloWorld
+ insertIndex << 9;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "World";
+ expectedString << "HelloWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "WellHelloThereWorld";
+
+ QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
+ }
+}
+
+void tst_qquicktextedit::redo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QQuickCanvas canvas;
+ textInput->setParentItem(canvas.rootItem());
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+
+ int i;
+ // inserts the diff strings at diff positions
+ for (i = 0; i < insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ textInput->setCursorPosition(insertIndex[i]);
+ for (int j = 0; j < insertString.at(i).length(); j++)
+ QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ }
+
+ // undo everything
+ while (!textInput->text().isEmpty())
+ simulateKeys(&canvas, QKeySequence::Undo);
+
+ for (i = 0; i < expectedString.size(); ++i) {
+ simulateKeys(&canvas, QKeySequence::Redo);
+ QCOMPARE(textInput->text() , expectedString[i]);
+ }
+}
+
+void tst_qquicktextedit::undo_keypressevents_data()
+{
+ QTest::addColumn<KeyList>("keys");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ KeyList keys;
+ QStringList expectedString;
+
+ keys << "AFRAID"
+ << Qt::Key_Home
+ << "VERY"
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << "BE"
+ << Qt::Key_End
+ << "!";
+
+ expectedString << "BEVERYAFRAID!";
+ expectedString << "BEVERYAFRAID";
+ expectedString << "VERYAFRAID";
+ expectedString << "AFRAID";
+
+ QTest::newRow("Inserts and moving cursor") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting '1234'
+ keys << "1234" << Qt::Key_Home
+ // skipping '12'
+ << Qt::Key_Right << Qt::Key_Right
+ // selecting '34'
+ << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
+ // deleting '34'
+ << Qt::Key_Delete;
+
+ expectedString << "12";
+ expectedString << "1234";
+
+ QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'AB12'
+ keys << "AB12"
+ << Qt::Key_Home
+ // selecting 'AB'
+ << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
+ << Qt::Key_Delete
+ << QKeySequence::Undo
+ // ### Text is selected in text input
+// << Qt::Key_Right
+ << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
+ << Qt::Key_Delete;
+
+ expectedString << "AB";
+ expectedString << "AB12";
+
+ QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'ABCD'
+ keys << "abcd"
+ //move left two
+ << Qt::Key_Left << Qt::Key_Left
+ // inserting '1234'
+ << "1234"
+ // selecting '1234'
+ << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
+ // overwriting '1234' with '5'
+ << "5"
+ // undoing deletion of 'AB'
+ << QKeySequence::Undo
+ // ### Text is selected in text input
+ << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
+ // overwriting '1234' with '6'
+ << "6";
+
+ expectedString << "ab6cd";
+ // for versions previous to 3.2 we overwrite needed two undo operations
+ expectedString << "ab1234cd";
+ expectedString << "abcd";
+
+ QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'ABC'
+ keys << "ABC"
+ // removes 'C'
+ << Qt::Key_Backspace;
+
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ keys << "ABC"
+ // removes 'C'
+ << Qt::Key_Backspace
+ // inserting 'Z'
+ << "Z";
+
+ expectedString << "ABZ";
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting '123'
+ keys << "123" << Qt::Key_Home
+ // selecting '123'
+ << (Qt::Key_End | Qt::ShiftModifier)
+ // overwriting '123' with 'ABC'
+ << "ABC";
+
+ expectedString << "ABC";
+ // ### One operation in TextInput.
+ expectedString << "A";
+ expectedString << "123";
+
+ QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
+ }
+}
+
+void tst_qquicktextedit::undo_keypressevents()
+{
+ QFETCH(KeyList, keys);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textInput = qobject_cast<QQuickTextEdit*>(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);
+
+ for (int i = 0; i < expectedString.size(); ++i) {
+ QCOMPARE(textInput->text() , expectedString[i]);
+ simulateKeys(&canvas, QKeySequence::Undo);
+ }
+ QVERIFY(textInput->text().isEmpty());
+}
+
+void tst_qquicktextedit::emptytags_QTBUG_22058()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("qtbug-22058.qml")));
+ QVERIFY(canvas.rootObject() != 0);
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("inputField")));
+ QVERIFY(input->hasActiveFocus());
+
+ QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());
+ event.setCommitString("<b>Bold<");
+ QGuiApplication::sendEvent(input, &event);
+ QCOMPARE(input->text(), QString("<b>Bold<"));
+ event.setCommitString(">");
+ QEXPECT_FAIL("", "Entering empty tags into a TextEdit asserts - QTBUG-22058", Abort);
+ QVERIFY(false);
+ QGuiApplication::sendEvent(input, &event);
+ QCOMPARE(input->text(), QString("<b>Bold<>"));
+}
+
+QTEST_MAIN(tst_qquicktextedit)
+
+#include "tst_qquicktextedit.moc"
diff --git a/tests/auto/declarative/qquicktextinput/data/cursorTest.qml b/tests/auto/qtquick2/qquicktextinput/data/cursorTest.qml
index 71a420ee7c..71a420ee7c 100644
--- a/tests/auto/declarative/qquicktextinput/data/cursorTest.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/cursorTest.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/cursorVisible.qml b/tests/auto/qtquick2/qquicktextinput/data/cursorVisible.qml
index 49e9386947..49e9386947 100644
--- a/tests/auto/declarative/qquicktextinput/data/cursorVisible.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/cursorVisible.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/echoMode.qml b/tests/auto/qtquick2/qquicktextinput/data/echoMode.qml
index f8a6cf1c89..f8a6cf1c89 100644
--- a/tests/auto/declarative/qquicktextinput/data/echoMode.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/echoMode.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/geometrySignals.qml b/tests/auto/qtquick2/qquicktextinput/data/geometrySignals.qml
index 90855a61cf..90855a61cf 100644
--- a/tests/auto/declarative/qquicktextinput/data/geometrySignals.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/geometrySignals.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/halign_center.png b/tests/auto/qtquick2/qquicktextinput/data/halign_center.png
index 53e09a8e5b..53e09a8e5b 100644
--- a/tests/auto/declarative/qquicktextinput/data/halign_center.png
+++ b/tests/auto/qtquick2/qquicktextinput/data/halign_center.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextinput/data/halign_left.png b/tests/auto/qtquick2/qquicktextinput/data/halign_left.png
index 247acbc9df..247acbc9df 100644
--- a/tests/auto/declarative/qquicktextinput/data/halign_left.png
+++ b/tests/auto/qtquick2/qquicktextinput/data/halign_left.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextinput/data/halign_right.png b/tests/auto/qtquick2/qquicktextinput/data/halign_right.png
index 691bc75c89..691bc75c89 100644
--- a/tests/auto/declarative/qquicktextinput/data/halign_right.png
+++ b/tests/auto/qtquick2/qquicktextinput/data/halign_right.png
Binary files differ
diff --git a/tests/auto/declarative/qquicktextinput/data/horizontalAlignment.qml b/tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment.qml
index e0fef4c11e..e0fef4c11e 100644
--- a/tests/auto/declarative/qquicktextinput/data/horizontalAlignment.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment_RightToLeft.qml
index 5f88025536..5f88025536 100644
--- a/tests/auto/declarative/qquicktextinput/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/horizontalAlignment_RightToLeft.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/inputContext.qml b/tests/auto/qtquick2/qquicktextinput/data/inputContext.qml
index dfc80990c6..dfc80990c6 100644
--- a/tests/auto/declarative/qquicktextinput/data/inputContext.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/inputContext.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/inputMethodEvent.qml b/tests/auto/qtquick2/qquicktextinput/data/inputMethodEvent.qml
index 7aefdf28f4..7aefdf28f4 100644
--- a/tests/auto/declarative/qquicktextinput/data/inputMethodEvent.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/inputMethodEvent.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/inputmethods.qml b/tests/auto/qtquick2/qquicktextinput/data/inputmethods.qml
index 711e89144c..711e89144c 100644
--- a/tests/auto/declarative/qquicktextinput/data/inputmethods.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/inputmethods.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/masks.qml b/tests/auto/qtquick2/qquicktextinput/data/masks.qml
index 589b6a3c15..589b6a3c15 100644
--- a/tests/auto/declarative/qquicktextinput/data/masks.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/masks.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/maxLength.qml b/tests/auto/qtquick2/qquicktextinput/data/maxLength.qml
index cca537ed6b..cca537ed6b 100644
--- a/tests/auto/declarative/qquicktextinput/data/maxLength.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/maxLength.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/mouseselection_true.qml b/tests/auto/qtquick2/qquicktextinput/data/mouseselection_true.qml
index 974041b04a..974041b04a 100644
--- a/tests/auto/declarative/qquicktextinput/data/mouseselection_true.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/mouseselection_true.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_characters.qml b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_characters.qml
index f7c658b618..f7c658b618 100644
--- a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_characters.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_characters.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_default.qml b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_default.qml
index 974041b04a..974041b04a 100644
--- a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_default.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_default.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_words.qml b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_words.qml
index 20e777e470..20e777e470 100644
--- a/tests/auto/declarative/qquicktextinput/data/mouseselectionmode_words.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/mouseselectionmode_words.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/navigation.qml b/tests/auto/qtquick2/qquicktextinput/data/navigation.qml
index 3a7d07b3c7..3a7d07b3c7 100644
--- a/tests/auto/declarative/qquicktextinput/data/navigation.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/navigation.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/openInputPanel.qml b/tests/auto/qtquick2/qquicktextinput/data/openInputPanel.qml
index ca5cb263aa..ca5cb263aa 100644
--- a/tests/auto/declarative/qquicktextinput/data/openInputPanel.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/openInputPanel.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/positionAt.qml b/tests/auto/qtquick2/qquicktextinput/data/positionAt.qml
index 1840462c87..1840462c87 100644
--- a/tests/auto/declarative/qquicktextinput/data/positionAt.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/positionAt.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/preeditAutoScroll.qml b/tests/auto/qtquick2/qquicktextinput/data/preeditAutoScroll.qml
index 9d98a2e220..9d98a2e220 100644
--- a/tests/auto/declarative/qquicktextinput/data/preeditAutoScroll.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/preeditAutoScroll.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/qtbug-19956double.qml b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956double.qml
index e9b80fceb2..e9b80fceb2 100644
--- a/tests/auto/declarative/qquicktextinput/data/qtbug-19956double.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956double.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/qtbug-19956int.qml b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956int.qml
index 0d70eedb80..0d70eedb80 100644
--- a/tests/auto/declarative/qquicktextinput/data/qtbug-19956int.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956int.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/qtbug-19956regexp.qml b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956regexp.qml
index b5af13cc4c..b5af13cc4c 100644
--- a/tests/auto/declarative/qquicktextinput/data/qtbug-19956regexp.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/qtbug-19956regexp.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/readOnly.qml b/tests/auto/qtquick2/qquicktextinput/data/readOnly.qml
index 9cda7fbd1d..9cda7fbd1d 100644
--- a/tests/auto/declarative/qquicktextinput/data/readOnly.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/readOnly.qml
diff --git a/tests/auto/declarative/qquicktextinput/data/validators.qml b/tests/auto/qtquick2/qquicktextinput/data/validators.qml
index 0a074ce7dc..0a074ce7dc 100644
--- a/tests/auto/declarative/qquicktextinput/data/validators.qml
+++ b/tests/auto/qtquick2/qquicktextinput/data/validators.qml
diff --git a/tests/auto/qtquick2/qquicktextinput/qquicktextinput.pro b/tests/auto/qtquick2/qquicktextinput/qquicktextinput.pro
new file mode 100644
index 0000000000..f81da61634
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktextinput/qquicktextinput.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+TARGET = tst_qquicktextinput
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktextinput.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/auto/qtquick2/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/qtquick2/qquicktextinput/tst_qquicktextinput.cpp
new file mode 100644
index 0000000000..57b2df11c9
--- /dev/null
+++ b/tests/auto/qtquick2/qquicktextinput/tst_qquicktextinput.cpp
@@ -0,0 +1,3310 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include "../../shared/util.h"
+#include <private/qinputpanel_p.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QFile>
+#include <QtQuick/qquickview.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qstylehints.h>
+#include <QInputPanel>
+#include <private/qquicktextinput_p.h>
+#include <private/qquicktextinput_p_p.h>
+#include <QDebug>
+#include <QDir>
+#include <QStyle>
+#include <QtOpenGL/QGLShaderProgram>
+#include <math.h>
+#include <qplatforminputcontext_qpa.h>
+#include <private/qinputpanel_p.h>
+
+#ifdef Q_OS_MAC
+#include <Carbon/Carbon.h>
+#endif
+
+#include "qplatformdefs.h"
+
+Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode)
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
+QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
+{
+ // XXX This will be replaced by some clever persistent platform image store.
+ QString persistent_dir = TESTDATA("");
+ QString arch = "unknown-architecture"; // QTest needs to help with this.
+
+ QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
+
+ if (!QFile::exists(expectfile)) {
+ actual.save(expectfile);
+ qWarning() << "created" << expectfile;
+ }
+
+ return expectfile;
+}
+
+typedef QPair<int, QChar> Key;
+
+class tst_qquicktextinput : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qquicktextinput();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void cleanup();
+ void text();
+ void width();
+ void font();
+ void color();
+ void selection();
+ void isRightToLeft_data();
+ void isRightToLeft();
+ void moveCursorSelection_data();
+ void moveCursorSelection();
+ void moveCursorSelectionSequence_data();
+ void moveCursorSelectionSequence();
+ void dragMouseSelection();
+ void mouseSelectionMode_data();
+ void mouseSelectionMode();
+ void tripleClickSelectsAll();
+
+ void horizontalAlignment_data();
+ void horizontalAlignment();
+ void horizontalAlignment_RightToLeft();
+
+ void positionAt();
+
+ void maxLength();
+ void masks();
+ void validators();
+ void inputMethods();
+
+ void passwordCharacter();
+ void cursorDelegate();
+ void cursorVisible();
+ void cursorRectangle();
+ void navigation();
+ void navigation_RTL();
+ void copyAndPaste();
+ void copyAndPasteKeySequence();
+ void canPasteEmpty();
+ void canPaste();
+ void readOnly();
+
+ void openInputPanel();
+ void setHAlignClearCache();
+ void focusOutClearSelection();
+
+ void echoMode();
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+ void passwordEchoDelay();
+#endif
+ void geometrySignals();
+ void testQtQuick11Attributes();
+ void testQtQuick11Attributes_data();
+
+ void preeditAutoScroll();
+ void preeditCursorRectangle();
+ void inputContextMouseHandler();
+ void inputMethodComposing();
+ void cursorRectangleSize();
+
+ void keySequence_data();
+ void keySequence();
+
+ void undo_data();
+ void undo();
+ void redo_data();
+ void redo();
+ void undo_keypressevents_data();
+ void undo_keypressevents();
+
+ void QTBUG_19956();
+ void QTBUG_19956_data();
+ void QTBUG_19956_regexp();
+
+private:
+ void simulateKey(QQuickView *, int key);
+
+ void simulateKeys(QWindow *window, const QList<Key> &keys);
+ void simulateKeys(QWindow *window, const QKeySequence &sequence);
+
+ QDeclarativeEngine engine;
+ QStringList standard;
+ QStringList colorStrings;
+};
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+
+typedef QList<Key> KeyList;
+Q_DECLARE_METATYPE(KeyList)
+
+void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
+{
+ for (int i = 0; i < keys.count(); ++i) {
+ const int key = keys.at(i).first;
+ const int modifiers = key & Qt::KeyboardModifierMask;
+ const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
+
+ QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
+ QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
+
+ QGuiApplication::sendEvent(window, &press);
+ QGuiApplication::sendEvent(window, &release);
+ }
+}
+
+void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
+{
+ for (uint i = 0; i < sequence.count(); ++i) {
+ const int key = sequence[i];
+ const int modifiers = key & Qt::KeyboardModifierMask;
+
+ QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
+ }
+}
+
+QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
+{
+ for (uint i = 0; i < sequence.count(); ++i)
+ keys << Key(sequence[i], QChar());
+ return keys;
+}
+
+template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
+{
+ for (int i = 0; i < N - 1; ++i) {
+ int key = QTest::asciiToKey(characters[i]);
+ QChar character = QLatin1Char(characters[i]);
+ keys << Key(key, character);
+ }
+ return keys;
+}
+
+QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
+{
+ keys << Key(key, QChar());
+ return keys;
+}
+
+void tst_qquicktextinput::initTestCase()
+{
+}
+
+void tst_qquicktextinput::cleanupTestCase()
+{
+}
+
+void tst_qquicktextinput::cleanup()
+{
+ // ensure not even skipped tests with custom input context leave it dangling
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = 0;
+}
+
+tst_qquicktextinput::tst_qquicktextinput()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "It's supercalifragisiticexpialidocious!"
+ << "Hello, world!"
+ << "!dlrow ,olleH"
+ << " spacey text ";
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+}
+
+void tst_qquicktextinput::text()
+{
+ {
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->text(), QString(""));
+
+ delete textinputObject;
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->text(), standard.at(i));
+
+ delete textinputObject;
+ }
+
+}
+
+void tst_qquicktextinput::width()
+{
+ // uses Font metrics to find the width for standard
+ {
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->width(), 0.0);
+
+ delete textinputObject;
+ }
+
+ bool requiresUnhintedMetrics = !qmlDisableDistanceField();
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ qreal metricWidth = 0.0;
+ if (requiresUnhintedMetrics) {
+ QString s = standard.at(i);
+ s.replace(QLatin1Char('\n'), QChar::LineSeparator);
+
+ QTextLayout layout(s);
+ layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
+ {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+
+ layout.endLayout();
+
+ metricWidth = ceil(layout.boundingRect().width());
+ } else {
+ QFontMetricsF fm(f);
+ metricWidth = fm.width(standard.at(i));
+ }
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ int delta = abs(int(int(textinputObject->width()) - metricWidth));
+ QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
+
+ delete textinputObject;
+ }
+}
+
+void tst_qquicktextinput::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().pointSize(), 40);
+ QCOMPARE(textinputObject->font().bold(), false);
+ QCOMPARE(textinputObject->font().italic(), false);
+
+ delete textinputObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { font.bold: true; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().bold(), true);
+ QCOMPARE(textinputObject->font().italic(), false);
+
+ delete textinputObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { font.italic: true; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().italic(), true);
+ QCOMPARE(textinputObject->font().bold(), false);
+
+ delete textinputObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
+ QCOMPARE(textinputObject->font().bold(), false);
+ QCOMPARE(textinputObject->font().italic(), false);
+
+ delete textinputObject;
+ }
+
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->font().family(), QString(""));
+
+ delete textinputObject;
+ }
+}
+
+void tst_qquicktextinput::color()
+{
+ //test color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
+
+ delete textinputObject;
+ }
+
+ //test selection color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
+
+ delete textinputObject;
+ }
+
+ //test selected text color
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "import QtQuick 2.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
+
+ delete textinputObject;
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+
+ QVERIFY(textinputObject != 0);
+ QCOMPARE(textinputObject->color(), testColor);
+
+ delete textinputObject;
+ }
+}
+
+void tst_qquicktextinput::selection()
+{
+ QString testStr = standard[0];
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+
+
+ //Test selection follows cursor
+ for (int i=0; i<= testStr.size(); i++) {
+ textinputObject->setCursorPosition(i);
+ QCOMPARE(textinputObject->cursorPosition(), i);
+ QCOMPARE(textinputObject->selectionStart(), i);
+ QCOMPARE(textinputObject->selectionEnd(), i);
+ QVERIFY(textinputObject->selectedText().isNull());
+ }
+
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ // Verify invalid positions are ignored.
+ textinputObject->setCursorPosition(-1);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ textinputObject->setCursorPosition(textinputObject->text().count()+1);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ //Test selection
+ for (int i=0; i<= testStr.size(); i++) {
+ textinputObject->select(0,i);
+ QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
+ }
+ for (int i=0; i<= testStr.size(); i++) {
+ textinputObject->select(i,testStr.size());
+ QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
+ }
+
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->cursorPosition() == 0);
+ QVERIFY(textinputObject->selectionStart() == 0);
+ QVERIFY(textinputObject->selectionEnd() == 0);
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ //Test Error Ignoring behaviour
+ textinputObject->setCursorPosition(0);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(-10,0);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(100,110);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(0,-10);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(0,100);
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(0,10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->select(-10,10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->select(100,101);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->select(0,-10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->select(0,100);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+
+ textinputObject->deselect();
+ QVERIFY(textinputObject->selectedText().isNull());
+ textinputObject->select(0,10);
+ QVERIFY(textinputObject->selectedText().size() == 10);
+ textinputObject->deselect();
+ QVERIFY(textinputObject->selectedText().isNull());
+
+ // test input method selection
+ QSignalSpy selectionSpy(textinputObject, SIGNAL(selectedTextChanged()));
+ textinputObject->setFocus(true);
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(textinputObject, &event);
+ }
+ QCOMPARE(selectionSpy.count(), 1);
+ QCOMPARE(textinputObject->selectionStart(), 12);
+ QCOMPARE(textinputObject->selectionEnd(), 17);
+
+ delete textinputObject;
+}
+
+void tst_qquicktextinput::isRightToLeft_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<bool>("emptyString");
+ QTest::addColumn<bool>("firstCharacter");
+ QTest::addColumn<bool>("lastCharacter");
+ QTest::addColumn<bool>("middleCharacter");
+ QTest::addColumn<bool>("startString");
+ QTest::addColumn<bool>("midString");
+ QTest::addColumn<bool>("endString");
+
+ const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
+ QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
+ QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
+ QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
+ QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
+ QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
+ QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
+}
+
+void tst_qquicktextinput::isRightToLeft()
+{
+ QFETCH(QString, text);
+ QFETCH(bool, emptyString);
+ QFETCH(bool, firstCharacter);
+ QFETCH(bool, lastCharacter);
+ QFETCH(bool, middleCharacter);
+ QFETCH(bool, startString);
+ QFETCH(bool, midString);
+ QFETCH(bool, endString);
+
+ QQuickTextInput textInput;
+ textInput.setText(text);
+
+ // first test that the right string is delivered to the QString::isRightToLeft()
+ QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
+ QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
+ QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
+ QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
+ QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
+ QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
+ if (text.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
+ QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
+
+ // then test that the feature actually works
+ QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
+ QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
+ QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
+ QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
+ QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
+ QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
+ if (text.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
+ QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
+}
+
+void tst_qquicktextinput::moveCursorSelection_data()
+{
+ QTest::addColumn<QString>("testStr");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<int>("movePosition");
+ QTest::addColumn<QQuickTextInput::SelectionMode>("mode");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<bool>("reversible");
+
+ // () contains the text selected by the cursor.
+ // <> contains the actual selection.
+
+ QTest::newRow("(t)he|characters")
+ << standard[0] << 0 << 1 << QQuickTextInput::SelectCharacters << 0 << 1 << true;
+ QTest::newRow("do(g)|characters")
+ << standard[0] << 43 << 44 << QQuickTextInput::SelectCharacters << 43 << 44 << true;
+ QTest::newRow("jum(p)ed|characters")
+ << standard[0] << 23 << 24 << QQuickTextInput::SelectCharacters << 23 << 24 << true;
+ QTest::newRow("jumped( )over|characters")
+ << standard[0] << 26 << 27 << QQuickTextInput::SelectCharacters << 26 << 27 << true;
+ QTest::newRow("(the )|characters")
+ << standard[0] << 0 << 4 << QQuickTextInput::SelectCharacters << 0 << 4 << true;
+ QTest::newRow("( dog)|characters")
+ << standard[0] << 40 << 44 << QQuickTextInput::SelectCharacters << 40 << 44 << true;
+ QTest::newRow("( jumped )|characters")
+ << standard[0] << 19 << 27 << QQuickTextInput::SelectCharacters << 19 << 27 << true;
+ QTest::newRow("th(e qu)ick|characters")
+ << standard[0] << 2 << 6 << QQuickTextInput::SelectCharacters << 2 << 6 << true;
+ QTest::newRow("la(zy d)og|characters")
+ << standard[0] << 38 << 42 << QQuickTextInput::SelectCharacters << 38 << 42 << true;
+ QTest::newRow("jum(ped ov)er|characters")
+ << standard[0] << 23 << 29 << QQuickTextInput::SelectCharacters << 23 << 29 << true;
+ QTest::newRow("()the|characters")
+ << standard[0] << 0 << 0 << QQuickTextInput::SelectCharacters << 0 << 0 << true;
+ QTest::newRow("dog()|characters")
+ << standard[0] << 44 << 44 << QQuickTextInput::SelectCharacters << 44 << 44 << true;
+ QTest::newRow("jum()ped|characters")
+ << standard[0] << 23 << 23 << QQuickTextInput::SelectCharacters << 23 << 23 << true;
+
+ QTest::newRow("<(t)he>|words")
+ << standard[0] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 3 << true;
+ QTest::newRow("<do(g)>|words")
+ << standard[0] << 43 << 44 << QQuickTextInput::SelectWords << 41 << 44 << true;
+ QTest::newRow("<jum(p)ed>|words")
+ << standard[0] << 23 << 24 << QQuickTextInput::SelectWords << 20 << 26 << true;
+ QTest::newRow("<jumped( )>over|words,ltr")
+ << standard[0] << 26 << 27 << QQuickTextInput::SelectWords << 20 << 27 << false;
+ QTest::newRow("jumped<( )over>|words,rtl")
+ << standard[0] << 27 << 26 << QQuickTextInput::SelectWords << 26 << 31 << false;
+ QTest::newRow("<(the )>quick|words,ltr")
+ << standard[0] << 0 << 4 << QQuickTextInput::SelectWords << 0 << 4 << false;
+ QTest::newRow("<(the )quick>|words,rtl")
+ << standard[0] << 4 << 0 << QQuickTextInput::SelectWords << 0 << 9 << false;
+ QTest::newRow("<lazy( dog)>|words,ltr")
+ << standard[0] << 40 << 44 << QQuickTextInput::SelectWords << 36 << 44 << false;
+ QTest::newRow("lazy<( dog)>|words,rtl")
+ << standard[0] << 44 << 40 << QQuickTextInput::SelectWords << 40 << 44 << false;
+ QTest::newRow("<fox( jumped )>over|words,ltr")
+ << standard[0] << 19 << 27 << QQuickTextInput::SelectWords << 16 << 27 << false;
+ QTest::newRow("fox<( jumped )over>|words,rtl")
+ << standard[0] << 27 << 19 << QQuickTextInput::SelectWords << 19 << 31 << false;
+ QTest::newRow("<th(e qu)ick>|words")
+ << standard[0] << 2 << 6 << QQuickTextInput::SelectWords << 0 << 9 << true;
+ QTest::newRow("<la(zy d)og|words>")
+ << standard[0] << 38 << 42 << QQuickTextInput::SelectWords << 36 << 44 << true;
+ QTest::newRow("<jum(ped ov)er>|words")
+ << standard[0] << 23 << 29 << QQuickTextInput::SelectWords << 20 << 31 << true;
+ QTest::newRow("<()>the|words")
+ << standard[0] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
+ QTest::newRow("dog<()>|words")
+ << standard[0] << 44 << 44 << QQuickTextInput::SelectWords << 44 << 44 << true;
+ QTest::newRow("jum<()>ped|words")
+ << standard[0] << 23 << 23 << QQuickTextInput::SelectWords << 23 << 23 << true;
+
+ QTest::newRow("Hello<(,)> |words")
+ << standard[2] << 5 << 6 << QQuickTextInput::SelectWords << 5 << 6 << true;
+ QTest::newRow("Hello<(, )>world|words,ltr")
+ << standard[2] << 5 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
+ QTest::newRow("Hello<(, )world>|words,rtl")
+ << standard[2] << 7 << 5 << QQuickTextInput::SelectWords << 5 << 12 << false;
+ QTest::newRow("<Hel(lo, )>world|words,ltr")
+ << standard[2] << 3 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
+ QTest::newRow("<Hel(lo, )world>|words,rtl")
+ << standard[2] << 7 << 3 << QQuickTextInput::SelectWords << 0 << 12 << false;
+ QTest::newRow("<Hel(lo)>,|words")
+ << standard[2] << 3 << 5 << QQuickTextInput::SelectWords << 0 << 5 << true;
+ QTest::newRow("Hello<()>,|words")
+ << standard[2] << 5 << 5 << QQuickTextInput::SelectWords << 5 << 5 << true;
+ QTest::newRow("Hello,<()>|words")
+ << standard[2] << 6 << 6 << QQuickTextInput::SelectWords << 6 << 6 << true;
+ QTest::newRow("Hello<,( )>world|words,ltr")
+ << standard[2] << 6 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
+ QTest::newRow("Hello,<( )world>|words,rtl")
+ << standard[2] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
+ QTest::newRow("Hello<,( world)>|words,ltr")
+ << standard[2] << 6 << 12 << QQuickTextInput::SelectWords << 5 << 12 << false;
+ QTest::newRow("Hello,<( world)>|words,rtl")
+ << standard[2] << 12 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
+ QTest::newRow("Hello<,( world!)>|words,ltr")
+ << standard[2] << 6 << 13 << QQuickTextInput::SelectWords << 5 << 13 << false;
+ QTest::newRow("Hello,<( world!)>|words,rtl")
+ << standard[2] << 13 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
+ QTest::newRow("Hello<(, world!)>|words")
+ << standard[2] << 5 << 13 << QQuickTextInput::SelectWords << 5 << 13 << true;
+ // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings.
+ // QTBUG-11365
+ // QTest::newRow("world<(!)>|words")
+ // << standard[2] << 12 << 13 << QQuickTextInput::SelectWords << 12 << 13 << true;
+ QTest::newRow("world!<()>)|words")
+ << standard[2] << 13 << 13 << QQuickTextInput::SelectWords << 13 << 13 << true;
+ QTest::newRow("world<()>!)|words")
+ << standard[2] << 12 << 12 << QQuickTextInput::SelectWords << 12 << 12 << true;
+
+ QTest::newRow("<(,)>olleH |words")
+ << standard[3] << 7 << 8 << QQuickTextInput::SelectWords << 7 << 8 << true;
+ QTest::newRow("<dlrow( ,)>olleH|words,ltr")
+ << standard[3] << 6 << 8 << QQuickTextInput::SelectWords << 1 << 8 << false;
+ QTest::newRow("dlrow<( ,)>olleH|words,rtl")
+ << standard[3] << 8 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
+ QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
+ << standard[3] << 6 << 10 << QQuickTextInput::SelectWords << 1 << 13 << false;
+ QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
+ << standard[3] << 10 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
+ QTest::newRow(",<(ol)leH>,|words")
+ << standard[3] << 8 << 10 << QQuickTextInput::SelectWords << 8 << 13 << true;
+ QTest::newRow(",<()>olleH|words")
+ << standard[3] << 8 << 8 << QQuickTextInput::SelectWords << 8 << 8 << true;
+ QTest::newRow("<()>,olleH|words")
+ << standard[3] << 7 << 7 << QQuickTextInput::SelectWords << 7 << 7 << true;
+ QTest::newRow("<dlrow( )>,olleH|words,ltr")
+ << standard[3] << 6 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
+ QTest::newRow("dlrow<( ),>olleH|words,rtl")
+ << standard[3] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
+ QTest::newRow("<(dlrow )>,olleH|words,ltr")
+ << standard[3] << 1 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
+ QTest::newRow("<(dlrow ),>olleH|words,rtl")
+ << standard[3] << 7 << 1 << QQuickTextInput::SelectWords << 1 << 8 << false;
+ QTest::newRow("<(!dlrow )>,olleH|words,ltr")
+ << standard[3] << 0 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
+ QTest::newRow("<(!dlrow ),>olleH|words,rtl")
+ << standard[3] << 7 << 0 << QQuickTextInput::SelectWords << 0 << 8 << false;
+ QTest::newRow("(!dlrow ,)olleH|words")
+ << standard[3] << 0 << 8 << QQuickTextInput::SelectWords << 0 << 8 << true;
+ QTest::newRow("<(!)>dlrow|words")
+ << standard[3] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << true;
+ QTest::newRow("<()>!dlrow|words")
+ << standard[3] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
+ QTest::newRow("!<()>dlrow|words")
+ << standard[3] << 1 << 1 << QQuickTextInput::SelectWords << 1 << 1 << true;
+
+ QTest::newRow(" <s(pac)ey> text |words")
+ << standard[4] << 1 << 4 << QQuickTextInput::SelectWords << 1 << 7 << true;
+ QTest::newRow(" spacey <t(ex)t> |words")
+ << standard[4] << 11 << 13 << QQuickTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365
+ QTest::newRow("<( )>spacey text |words|ltr")
+ << standard[4] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << false;
+ QTest::newRow("<( )spacey> text |words|rtl")
+ << standard[4] << 1 << 0 << QQuickTextInput::SelectWords << 0 << 7 << false;
+ QTest::newRow("spacey <text( )>|words|ltr")
+ << standard[4] << 14 << 15 << QQuickTextInput::SelectWords << 10 << 15 << false;
+// QTBUG-11365
+// QTest::newRow("spacey text<( )>|words|rtl")
+// << standard[4] << 15 << 14 << QQuickTextInput::SelectWords << 14 << 15 << false;
+ QTest::newRow("<()> spacey text |words")
+ << standard[4] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << false;
+ QTest::newRow(" spacey text <()>|words")
+ << standard[4] << 15 << 15 << QQuickTextInput::SelectWords << 15 << 15 << false;
+}
+
+void tst_qquicktextinput::moveCursorSelection()
+{
+ QFETCH(QString, testStr);
+ QFETCH(int, cursorPosition);
+ QFETCH(int, movePosition);
+ QFETCH(QQuickTextInput::SelectionMode, mode);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(bool, reversible);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+
+ textinputObject->setCursorPosition(cursorPosition);
+ textinputObject->moveCursorSelection(movePosition, mode);
+
+ QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
+ QCOMPARE(textinputObject->selectionStart(), selectionStart);
+ QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
+
+ if (reversible) {
+ textinputObject->setCursorPosition(movePosition);
+ textinputObject->moveCursorSelection(cursorPosition, mode);
+
+ QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
+ QCOMPARE(textinputObject->selectionStart(), selectionStart);
+ QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
+ }
+
+ delete textinputObject;
+}
+
+void tst_qquicktextinput::moveCursorSelectionSequence_data()
+{
+ QTest::addColumn<QString>("testStr");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<int>("movePosition1");
+ QTest::addColumn<int>("movePosition2");
+ QTest::addColumn<int>("selection1Start");
+ QTest::addColumn<int>("selection1End");
+ QTest::addColumn<int>("selection2Start");
+ QTest::addColumn<int>("selection2End");
+
+ // () contains the text selected by the cursor.
+ // <> contains the actual selection.
+ // ^ is the revised cursor position.
+ // {} contains the revised selection.
+
+ QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 17
+ << 4 << 15
+ << 4 << 19;
+ QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 17
+ << 9 << 15
+ << 10 << 19;
+ QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 16
+ << 4 << 15
+ << 4 << 16;
+ QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 16
+ << 9 << 15
+ << 10 << 16;
+ QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
+ << standard[0]
+ << 9 << 13 << 15
+ << 4 << 15
+ << 4 << 15;
+ QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
+ << standard[0]
+ << 13 << 9 << 15
+ << 9 << 15
+ << 10 << 15;
+ QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 10
+ << 4 << 15
+ << 4 << 10;
+ QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
+ << standard[0]
+ << 13 << 9 << 10
+ << 9 << 15
+ << 10 << 15;
+ QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 9
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
+ << standard[0]
+ << 13 << 9 << 9
+ << 9 << 15
+ << 9 << 15;
+ QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 7
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 7
+ << 9 << 15
+ << 4 << 15;
+ QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 4
+ << 4 << 15
+ << 4 << 9;
+ QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 4
+ << 9 << 15
+ << 4 << 15;
+ QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 3
+ << 4 << 15
+ << 3 << 9;
+ QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 3
+ << 9 << 15
+ << 3 << 15;
+ QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
+ << standard[0]
+ << 9 << 13 << 1
+ << 4 << 15
+ << 0 << 9;
+ QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
+ << standard[0]
+ << 13 << 9 << 1
+ << 9 << 15
+ << 0 << 15;
+
+ QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
+ << standard[2]
+ << 2 << 4 << 8
+ << 0 << 5
+ << 0 << 12;
+ QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
+ << standard[2]
+ << 4 << 2 << 8
+ << 0 << 5
+ << 0 << 12;
+
+ QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
+ << standard[3]
+ << 9 << 11 << 5
+ << 8 << 13
+ << 1 << 13;
+ QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
+ << standard[3]
+ << 11 << 9 << 5
+ << 8 << 13
+ << 1 << 13;
+
+ QTest::newRow("{<(^} sp)acey> text |ltr")
+ << standard[4]
+ << 0 << 3 << 0
+ << 0 << 7
+ << 0 << 0;
+ QTest::newRow("{<( ^}sp)acey> text |ltr")
+ << standard[4]
+ << 0 << 3 << 1
+ << 0 << 7
+ << 0 << 1;
+ QTest::newRow("<( {s^p)acey>} text |rtl")
+ << standard[4]
+ << 3 << 0 << 2
+ << 0 << 7
+ << 1 << 7;
+ QTest::newRow("<( {^sp)acey>} text |rtl")
+ << standard[4]
+ << 3 << 0 << 1
+ << 0 << 7
+ << 1 << 7;
+
+ QTest::newRow(" spacey <te(xt {^)>}|rtl")
+ << standard[4]
+ << 15 << 12 << 15
+ << 10 << 15
+ << 15 << 15;
+// QTBUG-11365
+// QTest::newRow(" spacey <te(xt{^ )>}|rtl")
+// << standard[4]
+// << 15 << 12 << 14
+// << 10 << 15
+// << 14 << 15;
+ QTest::newRow(" spacey {<te(x^t} )>|ltr")
+ << standard[4]
+ << 12 << 15 << 13
+ << 10 << 15
+ << 10 << 14;
+// QTBUG-11365
+// QTest::newRow(" spacey {<te(xt^} )>|ltr")
+// << standard[4]
+// << 12 << 15 << 14
+// << 10 << 15
+// << 10 << 14;
+}
+
+void tst_qquicktextinput::moveCursorSelectionSequence()
+{
+ QFETCH(QString, testStr);
+ QFETCH(int, cursorPosition);
+ QFETCH(int, movePosition1);
+ QFETCH(int, movePosition2);
+ QFETCH(int, selection1Start);
+ QFETCH(int, selection1End);
+ QFETCH(int, selection2Start);
+ QFETCH(int, selection2End);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \""+ testStr +"\"; }";
+ QDeclarativeComponent textinputComponent(&engine);
+ textinputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
+ QVERIFY(textinputObject != 0);
+
+ textinputObject->setCursorPosition(cursorPosition);
+
+ textinputObject->moveCursorSelection(movePosition1, QQuickTextInput::SelectWords);
+ QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
+ QCOMPARE(textinputObject->selectionStart(), selection1Start);
+ QCOMPARE(textinputObject->selectionEnd(), selection1End);
+
+ textinputObject->moveCursorSelection(movePosition2, QQuickTextInput::SelectWords);
+ QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
+ QCOMPARE(textinputObject->selectionStart(), selection2Start);
+ QCOMPARE(textinputObject->selectionEnd(), selection2End);
+
+ delete textinputObject;
+}
+
+void tst_qquicktextinput::dragMouseSelection()
+{
+ QString qmlfile = TESTDATA("mouseselection_true.qml");
+
+ QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(textInputObject != 0);
+
+ // press-and-drag-and-release from x1 to x2
+ int x1 = 10;
+ int x2 = 70;
+ int y = textInputObject->height()/2;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2, y));
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::qWait(100);
+ QString str1;
+ QVERIFY((str1 = textInputObject->selectedText()).length() > 3);
+ QVERIFY(str1.length() > 3);
+
+ // press and drag the current selection.
+ x1 = 40;
+ x2 = 100;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2, y));
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::qWait(300);
+ QString str2 = textInputObject->selectedText();
+ QVERIFY(str2.length() > 3);
+
+ QVERIFY(str1 != str2);
+}
+
+void tst_qquicktextinput::mouseSelectionMode_data()
+{
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<bool>("selectWords");
+
+ // import installed
+ QTest::newRow("SelectWords") << TESTDATA("mouseselectionmode_words.qml") << true;
+ QTest::newRow("SelectCharacters") << TESTDATA("mouseselectionmode_characters.qml") << false;
+ QTest::newRow("default") << TESTDATA("mouseselectionmode_default.qml") << false;
+}
+
+void tst_qquicktextinput::mouseSelectionMode()
+{
+ QFETCH(QString, qmlfile);
+ QFETCH(bool, selectWords);
+
+ QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(textInputObject != 0);
+
+ // press-and-drag-and-release from x1 to x2
+ int x1 = 10;
+ int x2 = 70;
+ int y = textInputObject->height()/2;
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&canvas, QPoint(x2,y)); // doesn't work
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::qWait(300);
+ if (selectWords) {
+ QTRY_COMPARE(textInputObject->selectedText(), text);
+ } else {
+ QTRY_VERIFY(textInputObject->selectedText().length() > 3);
+ QVERIFY(textInputObject->selectedText() != text);
+ }
+}
+
+void tst_qquicktextinput::horizontalAlignment_data()
+{
+ QTest::addColumn<int>("hAlign");
+ QTest::addColumn<QString>("expectfile");
+
+ QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
+ QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
+ QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
+}
+
+void tst_qquicktextinput::horizontalAlignment()
+{
+ QSKIP("Image comparison of text is almost guaranteed to fail during development");
+
+ QFETCH(int, hAlign);
+ QFETCH(QString, expectfile);
+
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment.qml")));
+
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ QObject *ob = canvas.rootObject();
+ QVERIFY(ob != 0);
+ ob->setProperty("horizontalAlignment",hAlign);
+ QImage actual = canvas.grabFrameBuffer();
+
+ expectfile = createExpectedFileIfNotFound(expectfile, actual);
+
+ QImage expect(expectfile);
+
+ QCOMPARE(actual,expect);
+}
+
+void tst_qquicktextinput::horizontalAlignment_RightToLeft()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment_RightToLeft.qml")));
+ QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
+ QVERIFY(textInput != 0);
+ canvas.show();
+
+ const QString rtlText = textInput->text();
+
+ QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
+ QVERIFY(textInputPrivate != 0);
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // implicit alignment should follow the reading direction of RTL text
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // explicitly left aligned
+ textInput->setHAlign(QQuickTextInput::AlignLeft);
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+
+ // explicitly right aligned
+ textInput->setHAlign(QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // explicitly center aligned
+ textInput->setHAlign(QQuickTextInput::AlignHCenter);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignHCenter);
+ QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width > canvas.width()/2);
+
+ // reseted alignment should go back to following the text reading direction
+ textInput->resetHAlign();
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // mirror the text item
+ QQuickItemPrivate::get(textInput)->setLayoutMirror(true);
+
+ // mirrored implicit alignment should continue to follow the reading direction of the text
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // explicitly right aligned behaves as left aligned
+ textInput->setHAlign(QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignLeft);
+ QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+
+ // mirrored explicitly left aligned behaves as right aligned
+ textInput->setHAlign(QQuickTextInput::AlignLeft);
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
+ QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignRight);
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+ // disable mirroring
+ QQuickItemPrivate::get(textInput)->setLayoutMirror(false);
+ QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
+ textInput->resetHAlign();
+
+ // English text should be implicitly left aligned
+ textInput->setText("Hello world!");
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
+ QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ // If there is no commited text, the preedit text should determine the alignment.
+ textInput->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
+
+ // Clear pre-edit text. TextInput should maybe do this itself on setText, but that may be
+ // redundant as an actual input method may take care of it.
+ { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &ev); }
+
+#ifdef Q_OS_MAC
+ // empty text with implicit alignment follows the system locale-based
+ // keyboard input direction from QGuiApplication::keyboardInputDirection
+ QEXPECT_FAIL("", "QTBUG-18040", Abort);
+#endif
+ textInput->setText("");
+ QCOMPARE(textInput->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
+ if (QGuiApplication::keyboardInputDirection() == Qt::LeftToRight)
+ QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ else
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ textInput->setHAlign(QQuickTextInput::AlignRight);
+ QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
+ QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+
+
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL("", "QTBUG-18040", Abort); // alignment of TextInput with no text set to it
+#endif
+ QString componentStr = "import QtQuick 2.0\nTextInput {}";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
+ QCOMPARE(textObject->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
+ QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
+ delete textObject;
+}
+
+void tst_qquicktextinput::positionAt()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
+ QVERIFY(canvas.rootObject() != 0);
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(textinputObject != 0);
+
+ // Check autoscrolled...
+ QFontMetrics fm(textinputObject->font());
+
+ int pos = textinputObject->positionAt(textinputObject->width()/2);
+ int textWidth = 0;
+ int textLeftWidthBegin = 0;
+ int textLeftWidthEnd = 0;
+ if (!qmlDisableDistanceField()) {
+ QTextLayout layout(textinputObject->text());
+
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ textLeftWidthBegin = floor(line.cursorToX(pos - 1));
+ textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
+ textWidth = floor(line.horizontalAdvance());
+ } else {
+ textWidth = fm.width(textinputObject->text());
+ textLeftWidthBegin = fm.width(textinputObject->text().left(pos - 1));
+ textLeftWidthEnd = fm.width(textinputObject->text().left(pos + 1));
+ }
+
+ QVERIFY(textLeftWidthBegin <= textWidth - textinputObject->width() / 2);
+ QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
+
+ int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
+ QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
+ QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
+
+ // Check without autoscroll...
+ textinputObject->setAutoScroll(false);
+ pos = textinputObject->positionAt(textinputObject->width()/2);
+
+ if (!qmlDisableDistanceField()) {
+ QTextLayout layout(textinputObject->text());
+
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ textLeftWidthBegin = floor(line.cursorToX(pos - 1));
+ textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
+ } else {
+ textLeftWidthBegin = fm.width(textinputObject->text().left(pos - 1));
+ textLeftWidthEnd = fm.width(textinputObject->text().left(pos + 1));
+ }
+
+ QVERIFY(textLeftWidthBegin <= textinputObject->width() / 2);
+ QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
+
+ x = textinputObject->positionToRectangle(pos + 1).x() - 1;
+ QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
+ QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
+
+ const qreal x0 = textinputObject->positionToRectangle(pos).x();
+ const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
+
+ QString preeditText = textinputObject->text().mid(0, pos);
+ textinputObject->setText(textinputObject->text().mid(pos));
+ textinputObject->setCursorPosition(0);
+
+ QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent);
+
+ // Check all points within the preedit text return the same position.
+ QCOMPARE(textinputObject->positionAt(0), 0);
+ QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
+ QCOMPARE(textinputObject->positionAt(x0), 0);
+
+ // Verify positioning returns to normal after the preedit text.
+ QCOMPARE(textinputObject->positionAt(x1), 1);
+ QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
+}
+
+void tst_qquicktextinput::maxLength()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("maxLength.qml")));
+ QVERIFY(canvas.rootObject() != 0);
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject->text().isEmpty());
+ QVERIFY(textinputObject->maxLength() == 10);
+ foreach (const QString &str, standard) {
+ QVERIFY(textinputObject->text().length() <= 10);
+ textinputObject->setText(str);
+ QVERIFY(textinputObject->text().length() <= 10);
+ }
+
+ textinputObject->setText("");
+ QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
+ for (int i=0; i<20; i++) {
+ QTRY_COMPARE(textinputObject->text().length(), qMin(i,10));
+ //simulateKey(&canvas, Qt::Key_A);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ }
+}
+
+void tst_qquicktextinput::masks()
+{
+ //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
+ //QString componentStr = "import QtQuick 2.0\nTextInput { inputMask: 'HHHHhhhh'; }";
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("masks.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(textinputObject != 0);
+ QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
+ QVERIFY(textinputObject->text().length() == 0);
+ QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
+ for (int i=0; i<10; i++) {
+ QTRY_COMPARE(qMin(i,8), textinputObject->text().length());
+ QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
+ //simulateKey(&canvas, Qt::Key_A);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ }
+}
+
+void tst_qquicktextinput::validators()
+{
+ // Note that this test assumes that the validators are working properly
+ // so you may need to run their tests first. All validators are checked
+ // here to ensure that their exposure to QML is working.
+
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("validators.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *intInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("intInput")));
+ QVERIFY(intInput);
+ intInput->setFocus(true);
+ QTRY_VERIFY(intInput->hasActiveFocus());
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(intInput->text(), QLatin1String("1"));
+ QCOMPARE(intInput->hasAcceptableInput(), false);
+ QTest::keyPress(&canvas, Qt::Key_2);
+ QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(intInput->text(), QLatin1String("1"));
+ QCOMPARE(intInput->hasAcceptableInput(), false);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QCOMPARE(intInput->text(), QLatin1String("11"));
+ QCOMPARE(intInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_0);
+ QTest::keyRelease(&canvas, Qt::Key_0, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QCOMPARE(intInput->text(), QLatin1String("11"));
+ QCOMPARE(intInput->hasAcceptableInput(), true);
+
+ QQuickTextInput *dblInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("dblInput")));
+ QTRY_VERIFY(dblInput);
+ dblInput->setFocus(true);
+ QVERIFY(dblInput->hasActiveFocus() == true);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
+ QCOMPARE(dblInput->hasAcceptableInput(), false);
+ QTest::keyPress(&canvas, Qt::Key_2);
+ QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_Period);
+ QTest::keyRelease(&canvas, Qt::Key_Period, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+
+ QQuickTextInput *strInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("strInput")));
+ QTRY_VERIFY(strInput);
+ strInput->setFocus(true);
+ QVERIFY(strInput->hasActiveFocus() == true);
+ QTest::keyPress(&canvas, Qt::Key_1);
+ QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String(""));
+ QCOMPARE(strInput->hasAcceptableInput(), false);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String("a"));
+ QCOMPARE(strInput->hasAcceptableInput(), false);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String("aa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String("aaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+ QTest::keyPress(&canvas, Qt::Key_A);
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QTest::qWait(50);
+ QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
+ QCOMPARE(strInput->hasAcceptableInput(), true);
+}
+
+void tst_qquicktextinput::inputMethods()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("inputmethods.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+
+ // test input method hints
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(canvas.rootObject());
+ QVERIFY(input != 0);
+ QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
+ input->setInputMethodHints(Qt::ImhUppercaseOnly);
+ QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
+
+ input->setFocus(true);
+ QVERIFY(input->hasActiveFocus() == true);
+ // test that input method event is committed
+ QInputMethodEvent event;
+ event.setCommitString( "My ", -12, 0);
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+ QCOMPARE(input->text(), QString("My Hello world!"));
+
+ input->setCursorPosition(2);
+ event.setCommitString("Your", -2, 2);
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+ QCOMPARE(input->text(), QString("Your Hello world!"));
+ QCOMPARE(input->cursorPosition(), 4);
+
+ input->setCursorPosition(7);
+ event.setCommitString("Goodbye", -2, 5);
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+ QCOMPARE(input->text(), QString("Your Goodbye world!"));
+ QCOMPARE(input->cursorPosition(), 12);
+
+ input->setCursorPosition(8);
+ event.setCommitString("Our", -8, 4);
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+ QCOMPARE(input->text(), QString("Our Goodbye world!"));
+ QCOMPARE(input->cursorPosition(), 7);
+
+ // test that basic tentative commit gets to text property on preedit state
+ input->setText("");
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent preeditEvent("test", attributes);
+ preeditEvent.setTentativeCommitString("test");
+ QApplication::sendEvent(input, &preeditEvent);
+ QCOMPARE(input->text(), QString("test"));
+
+ // tentative commit not allowed present in surrounding text
+ QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
+ QApplication::sendEvent(input, &queryEvent);
+ QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
+
+ // if text with tentative commit does not validate, not allowed to be part of text property
+ input->setText(""); // ensure input state is reset
+ QValidator *validator = new QIntValidator(0, 100);
+ input->setValidator(validator);
+ QApplication::sendEvent(input, &preeditEvent);
+ QCOMPARE(input->text(), QString(""));
+ input->setValidator(0);
+ delete validator;
+}
+
+/*
+TextInput element should only handle left/right keys until the cursor reaches
+the extent of the text, then they should ignore the keys.
+
+*/
+void tst_qquicktextinput::navigation()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ input->setCursorPosition(0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == false);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == true);
+ //QT-2944: If text is selected, ensure we deselect upon cursor motion
+ input->setCursorPosition(input->text().length());
+ input->select(0,input->text().length());
+ QVERIFY(input->selectionStart() != input->selectionEnd());
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->selectionStart() == input->selectionEnd());
+ QVERIFY(input->selectionStart() == input->text().length());
+ QVERIFY(input->hasActiveFocus() == true);
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == false);
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == true);
+
+ // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
+ input->setCursorPosition(2);
+ QCOMPARE(input->cursorPosition(),2);
+ simulateKey(&canvas, Qt::Key_Up);
+ QCOMPARE(input->cursorPosition(),2);
+ simulateKey(&canvas, Qt::Key_Down);
+ QCOMPARE(input->cursorPosition(),2);
+}
+
+void tst_qquicktextinput::navigation_RTL()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("navigation.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
+ input->setText(QString::fromUtf16(arabic_str, 11));
+
+ input->setCursorPosition(0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+
+ // move off
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == false);
+
+ // move back
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == true);
+
+ input->setCursorPosition(input->text().length());
+ QVERIFY(input->hasActiveFocus() == true);
+
+ // move off
+ simulateKey(&canvas, Qt::Key_Left);
+ QVERIFY(input->hasActiveFocus() == false);
+
+ // move back
+ simulateKey(&canvas, Qt::Key_Right);
+ QVERIFY(input->hasActiveFocus() == true);
+}
+
+void tst_qquicktextinput::copyAndPaste() {
+#ifndef QT_NO_CLIPBOARD
+
+#ifdef Q_OS_MAC
+ {
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ else
+ QSKIP("This machine doesn't support the clipboard");
+ }
+#endif
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ // copy and paste
+ QCOMPARE(textInput->text().length(), 12);
+ textInput->select(0, textInput->text().length());;
+ textInput->copy();
+ QCOMPARE(textInput->selectedText(), QString("Hello world!"));
+ QCOMPARE(textInput->selectedText().length(), 12);
+ textInput->setCursorPosition(0);
+ QVERIFY(textInput->canPaste());
+ textInput->paste();
+ QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textInput->text().length(), 24);
+
+ // can paste
+ QVERIFY(textInput->canPaste());
+ textInput->setReadOnly(true);
+ QVERIFY(!textInput->canPaste());
+ textInput->setReadOnly(false);
+ QVERIFY(textInput->canPaste());
+
+ // select word
+ textInput->setCursorPosition(0);
+ textInput->selectWord();
+ QCOMPARE(textInput->selectedText(), QString("Hello"));
+
+ // select all and cut
+ textInput->selectAll();
+ textInput->cut();
+ QCOMPARE(textInput->text().length(), 0);
+ textInput->paste();
+ QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textInput->text().length(), 24);
+
+ // clear copy buffer
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ QVERIFY(clipboard);
+ clipboard->clear();
+ QVERIFY(!textInput->canPaste());
+
+ // test that copy functionality is disabled
+ // when echo mode is set to hide text/password mode
+ int index = 0;
+ while (index < 4) {
+ QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
+ textInput->setEchoMode(echoMode);
+ textInput->setText("My password");
+ textInput->select(0, textInput->text().length());;
+ textInput->copy();
+ if (echoMode == QQuickTextInput::Normal) {
+ QVERIFY(!clipboard->text().isEmpty());
+ QCOMPARE(clipboard->text(), QString("My password"));
+ clipboard->clear();
+ } else {
+ QVERIFY(clipboard->text().isEmpty());
+ }
+ index++;
+ }
+
+ delete textInput;
+#endif
+}
+
+void tst_qquicktextinput::copyAndPasteKeySequence() {
+#ifndef QT_NO_CLIPBOARD
+
+#ifdef Q_OS_MAC
+ {
+ PasteboardRef pasteboard;
+ OSStatus status = PasteboardCreate(0, &pasteboard);
+ if (status == noErr)
+ CFRelease(pasteboard);
+ else
+ QSKIP("This machine doesn't support the clipboard");
+ }
+#endif
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; focus: true }";
+ QDeclarativeComponent 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);
+
+ // copy and paste
+ QVERIFY(textInput->hasActiveFocus());
+ QCOMPARE(textInput->text().length(), 12);
+ textInput->select(0, textInput->text().length());
+ simulateKeys(&canvas, QKeySequence::Copy);
+ QCOMPARE(textInput->selectedText(), QString("Hello world!"));
+ QCOMPARE(textInput->selectedText().length(), 12);
+ textInput->setCursorPosition(0);
+ QVERIFY(textInput->canPaste());
+ simulateKeys(&canvas, QKeySequence::Paste);
+ QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textInput->text().length(), 24);
+
+ // select all and cut
+ simulateKeys(&canvas, QKeySequence::SelectAll);
+ simulateKeys(&canvas, QKeySequence::Cut);
+ QCOMPARE(textInput->text().length(), 0);
+ simulateKeys(&canvas, QKeySequence::Paste);
+ QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textInput->text().length(), 24);
+
+ // clear copy buffer
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ QVERIFY(clipboard);
+ clipboard->clear();
+ QVERIFY(!textInput->canPaste());
+
+ // test that copy functionality is disabled
+ // when echo mode is set to hide text/password mode
+ int index = 0;
+ while (index < 4) {
+ QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
+ textInput->setEchoMode(echoMode);
+ textInput->setText("My password");
+ textInput->select(0, textInput->text().length());;
+ simulateKeys(&canvas, QKeySequence::Copy);
+ if (echoMode == QQuickTextInput::Normal) {
+ QVERIFY(!clipboard->text().isEmpty());
+ QCOMPARE(clipboard->text(), QString("My password"));
+ clipboard->clear();
+ } else {
+ QVERIFY(clipboard->text().isEmpty());
+ }
+ index++;
+ }
+
+ delete textInput;
+#endif
+}
+
+void tst_qquicktextinput::canPasteEmpty() {
+#ifndef QT_NO_CLIPBOARD
+
+ QGuiApplication::clipboard()->clear();
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QLineControl lc;
+ bool cp = !lc.isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
+ QCOMPARE(textInput->canPaste(), cp);
+
+#endif
+}
+
+void tst_qquicktextinput::canPaste() {
+#ifndef QT_NO_CLIPBOARD
+
+ QGuiApplication::clipboard()->setText("Some text");
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ QLineControl lc;
+ bool cp = !lc.isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
+ QCOMPARE(textInput->canPaste(), cp);
+
+#endif
+}
+
+void tst_qquicktextinput::passwordCharacter()
+{
+ QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
+ QDeclarativeComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != 0);
+
+ textInput->setPasswordCharacter("X");
+ qreal implicitWidth = textInput->implicitWidth();
+ textInput->setPasswordCharacter(".");
+
+ // QTBUG-12383 content is updated and redrawn
+ QVERIFY(textInput->implicitWidth() < implicitWidth);
+
+ delete textInput;
+}
+
+void tst_qquicktextinput::cursorDelegate()
+{
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorTest.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QQuickTextInput *textInputObject = view.rootObject()->findChild<QQuickTextInput*>("textInputObject");
+ QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject->findChild<QQuickItem*>("cursorInstance"));
+ //Test Delegate gets created
+ textInputObject->setFocus(true);
+ QQuickItem* delegateObject = textInputObject->findChild<QQuickItem*>("cursorInstance");
+ QVERIFY(delegateObject);
+ QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
+ //Test Delegate gets moved
+ for (int i=0; i<= textInputObject->text().length(); i++) {
+ textInputObject->setCursorPosition(i);
+ QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
+ }
+ textInputObject->setCursorPosition(0);
+ QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
+ //Test Delegate gets deleted
+ textInputObject->setCursorDelegate(0);
+ QVERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
+}
+
+void tst_qquicktextinput::cursorVisible()
+{
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("cursorVisible.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QQuickTextInput input;
+ QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
+
+ QCOMPARE(input.isCursorVisible(), false);
+
+ input.setCursorVisible(true);
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 1);
+
+ input.setCursorVisible(false);
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 2);
+
+ input.setFocus(true);
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 2);
+
+ input.setParentItem(view.rootObject());
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 3);
+
+ input.setFocus(false);
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 4);
+
+ input.setFocus(true);
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 5);
+
+ QQuickView alternateView;
+ alternateView.show();
+ alternateView.requestActivateWindow();
+ QTest::qWaitForWindowShown(&alternateView);
+
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 6);
+
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 7);
+}
+
+void tst_qquicktextinput::cursorRectangle()
+{
+ QSKIP("QTBUG-21689");
+
+ QString text = "Hello World!";
+
+ QQuickTextInput input;
+ input.setText(text);
+ QFontMetricsF fm(input.font());
+ input.setWidth(fm.width(text.mid(0, 5)));
+
+ QRect 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) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+ int textWidth = fm.width(text.mid(0, i));
+
+ QVERIFY(r.left() < textWidth + error);
+ QVERIFY(r.right() > textWidth - error);
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
+ }
+
+ // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
+ QVERIFY(r.left() < input.boundingRect().width());
+ QVERIFY(r.right() >= input.width() - error);
+
+ for (int i = 6; i < text.length(); ++i) {
+ input.setCursorPosition(i);
+ QCOMPARE(r, input.cursorRectangle());
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
+ }
+
+ for (int i = text.length() - 2; i >= 0; --i) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+ QVERIFY(r.right() >= 0);
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
+ }
+
+ input.setText("Hi!");
+ input.setHAlign(QQuickTextInput::AlignRight);
+ r = input.cursorRectangle();
+ QVERIFY(r.left() < input.boundingRect().width());
+ QVERIFY(r.right() >= input.width() - error);
+}
+
+void tst_qquicktextinput::readOnly()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("readOnly.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->isReadOnly() == true);
+ QString initial = input->text();
+ for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
+ simulateKey(&canvas, k);
+ simulateKey(&canvas, Qt::Key_Return);
+ simulateKey(&canvas, Qt::Key_Space);
+ simulateKey(&canvas, Qt::Key_Escape);
+ QCOMPARE(input->text(), initial);
+
+ input->setCursorPosition(3);
+ input->setReadOnly(false);
+ QCOMPARE(input->isReadOnly(), false);
+ QCOMPARE(input->cursorPosition(), input->text().length());
+}
+
+void tst_qquicktextinput::echoMode()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("echoMode.qml")));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QVERIFY(input != 0);
+ QTRY_VERIFY(input->hasActiveFocus() == true);
+ QString initial = input->text();
+ Qt::InputMethodHints ref;
+ QCOMPARE(initial, QLatin1String("ABCDefgh"));
+ QCOMPARE(input->echoMode(), QQuickTextInput::Normal);
+ QCOMPARE(input->displayText(), input->text());
+ //Normal
+ ref &= ~Qt::ImhHiddenText;
+ ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ QCOMPARE(input->inputMethodHints(), ref);
+ input->setEchoMode(QQuickTextInput::NoEcho);
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), QLatin1String(""));
+ QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
+ //NoEcho
+ ref |= Qt::ImhHiddenText;
+ ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ QCOMPARE(input->inputMethodHints(), ref);
+ input->setEchoMode(QQuickTextInput::Password);
+ //Password
+ ref |= Qt::ImhHiddenText;
+ ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), QLatin1String("********"));
+ QCOMPARE(input->inputMethodHints(), ref);
+ input->setPasswordCharacter(QChar('Q'));
+ QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
+ input->setEchoMode(QQuickTextInput::PasswordEchoOnEdit);
+ //PasswordEchoOnEdit
+ ref &= ~Qt::ImhHiddenText;
+ ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ QCOMPARE(input->inputMethodHints(), ref);
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
+ QTest::keyPress(&canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
+ QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
+ QCOMPARE(input->text(), QLatin1String("a"));
+ QCOMPARE(input->displayText(), QLatin1String("a"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
+ input->setFocus(false);
+ QVERIFY(input->hasActiveFocus() == false);
+ QCOMPARE(input->displayText(), QLatin1String("Q"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
+ input->setFocus(true);
+ QVERIFY(input->hasActiveFocus());
+ QInputMethodEvent inputEvent;
+ inputEvent.setCommitString(initial);
+ QGuiApplication::sendEvent(input, &inputEvent);
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), initial);
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
+}
+
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+void tst_qdeclarativetextinput::passwordEchoDelay()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("echoMode.qml")));
+ canvas.show();
+ canvas.setFocus();
+ QGuiApplication::setActiveWindow(&canvas);
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QChar fillChar = QLatin1Char('*');
+
+ input->setEchoMode(QDeclarativeTextInput::Password);
+ QCOMPARE(input->displayText(), QString(8, fillChar));
+ input->setText(QString());
+ QCOMPARE(input->displayText(), QString());
+
+ QTest::keyPress(&canvas, '0');
+ QTest::keyPress(&canvas, '1');
+ QTest::keyPress(&canvas, '2');
+ QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
+ QTest::keyPress(&canvas, '3');
+ QTest::keyPress(&canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::keyPress(&canvas, Qt::Key_Backspace);
+ QCOMPARE(input->displayText(), QString(4, fillChar));
+ QTest::keyPress(&canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
+ QTRY_COMPARE(input->displayText(), QString(5, fillChar));
+ QTest::keyPress(&canvas, '5');
+ QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
+ input->setFocus(false);
+ QVERIFY(!input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ input->setFocus(true);
+ QTRY_VERIFY(input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ QTest::keyPress(&canvas, '6');
+ QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
+
+ QInputMethodEvent ev;
+ ev.setCommitString(QLatin1String("7"));
+ QGuiApplication::sendEvent(&canvas, &ev);
+ QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
+}
+#endif
+
+
+void tst_qquicktextinput::simulateKey(QQuickView *view, int key)
+{
+ QKeyEvent press(QKeyEvent::KeyPress, key, 0);
+ QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
+
+ QGuiApplication::sendEvent(view, &press);
+ QGuiApplication::sendEvent(view, &release);
+}
+
+class PlatformInputContext : public QPlatformInputContext
+{
+public:
+ PlatformInputContext()
+ : m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
+ m_invokeActionCallCount(0)
+ {
+ }
+
+ virtual void showInputPanel()
+ {
+ m_visible = true;
+ }
+ virtual void hideInputPanel()
+ {
+ m_visible = false;
+ }
+ virtual bool isInputPanelVisible() const
+ {
+ return m_visible;
+ }
+ virtual void invokeAction(QInputPanel::Action action, int cursorPosition)
+ {
+ m_invokeActionCallCount++;
+ m_action = action;
+ m_cursorPosition = cursorPosition;
+ }
+
+ bool m_visible;
+ QInputPanel::Action m_action;
+ int m_cursorPosition;
+ int m_invokeActionCallCount;
+};
+
+void tst_qquicktextinput::openInputPanel()
+{
+ PlatformInputContext platformInputContext;
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = &platformInputContext;
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("openInputPanel.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+
+ // check default values
+ QVERIFY(input->focusOnPress());
+ QVERIFY(!input->hasActiveFocus());
+ qDebug() << &input << qApp->inputPanel()->inputItem();
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should open on focus
+ QPoint centerPoint(view.width()/2, view.height()/2);
+ Qt::KeyboardModifiers noModifiers = 0;
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QVERIFY(input->hasActiveFocus());
+ QCOMPARE(qApp->inputPanel()->inputItem(), input);
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+
+ // input panel should be re-opened when pressing already focused TextInput
+ qApp->inputPanel()->hide();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QVERIFY(input->hasActiveFocus());
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+
+ // input panel should stay visible if focus is lost to another text inputor
+ QSignalSpy inputPanelVisibilitySpy(qApp->inputPanel(), SIGNAL(visibleChanged()));
+ QQuickTextInput anotherInput;
+ anotherInput.setParentItem(view.rootObject());
+ anotherInput.setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+ QCOMPARE(qApp->inputPanel()->inputItem(), qobject_cast<QObject*>(&anotherInput));
+ QCOMPARE(inputPanelVisibilitySpy.count(), 0);
+
+ anotherInput.setFocus(false);
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+ QCOMPARE(view.activeFocusItem(), view.rootItem());
+ anotherInput.setFocus(true);
+
+ // input item should be null if focus is lost to an item that doesn't accept inputs
+ QQuickItem item;
+ item.setParentItem(view.rootObject());
+ item.setFocus(true);
+ QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
+ QCOMPARE(view.activeFocusItem(), &item);
+
+ qApp->inputPanel()->hide();
+
+ // input panel should not be opened if TextInput is read only
+ input->setReadOnly(true);
+ input->setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QGuiApplication::processEvents();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should not be opened if focusOnPress is set to false
+ input->setFocusOnPress(false);
+ input->setFocus(false);
+ input->setFocus(true);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+ QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+
+ // input panel should open when openSoftwareInputPanel is called
+ input->openSoftwareInputPanel();
+ QCOMPARE(qApp->inputPanel()->visible(), true);
+
+ // input panel should close when closeSoftwareInputPanel is called
+ input->closeSoftwareInputPanel();
+ QCOMPARE(qApp->inputPanel()->visible(), false);
+}
+
+class MyTextInput : public QQuickTextInput
+{
+public:
+ MyTextInput(QQuickItem *parent = 0) : QQuickTextInput(parent)
+ {
+ nbPaint = 0;
+ }
+ virtual QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data)
+ {
+ nbPaint++;
+ return QQuickTextInput::updatePaintNode(node, data);
+ }
+ int nbPaint;
+};
+
+void tst_qquicktextinput::setHAlignClearCache()
+{
+ QQuickView view;
+ MyTextInput input;
+ input.setText("Hello world");
+ input.setParentItem(view.rootItem());
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(input.nbPaint, 1);
+ input.setHAlign(QQuickTextInput::AlignRight);
+ //Changing the alignment should trigger a repaint
+ QTRY_COMPARE(input.nbPaint, 2);
+}
+
+void tst_qquicktextinput::focusOutClearSelection()
+{
+ QQuickView view;
+ QQuickTextInput input;
+ QQuickTextInput input2;
+ input.setText(QLatin1String("Hello world"));
+ input.setFocus(true);
+ input2.setParentItem(view.rootItem());
+ input.setParentItem(view.rootItem());
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ input.select(2,5);
+ //The selection should work
+ QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
+ input2.setFocus(true);
+ QGuiApplication::processEvents();
+ //The input lost the focus selection should be cleared
+ QTRY_COMPARE(input.selectedText(), QLatin1String(""));
+}
+
+void tst_qquicktextinput::geometrySignals()
+{
+ QDeclarativeComponent component(&engine, TESTDATA("geometrySignals.qml"));
+ QObject *o = component.create();
+ QVERIFY(o);
+ QCOMPARE(o->property("bindingWidth").toInt(), 400);
+ QCOMPARE(o->property("bindingHeight").toInt(), 500);
+ delete o;
+}
+
+void tst_qquicktextinput::testQtQuick11Attributes()
+{
+ QFETCH(QString, code);
+ QFETCH(QString, warning);
+ QFETCH(QString, error);
+
+ QDeclarativeEngine engine;
+ QObject *obj;
+
+ QDeclarativeComponent valid(&engine);
+ valid.setData("import QtQuick 2.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
+ obj = valid.create();
+ QVERIFY(obj);
+ QVERIFY(valid.errorString().isEmpty());
+ delete obj;
+
+ QDeclarativeComponent invalid(&engine);
+ invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
+ QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
+ obj = invalid.create();
+ QCOMPARE(invalid.errorString(), error);
+ delete obj;
+}
+
+void tst_qquicktextinput::testQtQuick11Attributes_data()
+{
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("warning");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("canPaste") << "property bool foo: canPaste"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
+ << "";
+
+ QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
+ << "";
+
+ QTest::newRow("deselect") << "Component.onCompleted: deselect()"
+ << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
+ << "";
+}
+
+static void sendPreeditText(const QString &text, int cursor)
+{
+ QInputMethodEvent event(text, QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
+}
+
+void tst_qquicktextinput::preeditAutoScroll()
+{
+ QString preeditText = "califragisiticexpialidocious!";
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("preeditAutoScroll.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+ QVERIFY(input->hasActiveFocus());
+
+ input->setWidth(input->implicitWidth());
+
+ QSignalSpy cursorRectangleSpy(input, SIGNAL(cursorRectangleChanged()));
+ int cursorRectangleChanges = 0;
+
+ // test the text is scrolled so the preedit is visible.
+ sendPreeditText(preeditText.mid(0, 3), 1);
+ QVERIFY(input->positionAt(0) != 0);
+ QVERIFY(input->cursorRectangle().left() < input->boundingRect().width());
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+
+ // test the text is scrolled back when the preedit is removed.
+ QInputMethodEvent imEvent;
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+ QCOMPARE(input->positionAt(0), 0);
+ QCOMPARE(input->positionAt(input->width()), 5);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+
+ QTextLayout layout(preeditText);
+ if (!qmlDisableDistanceField()) {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ // test if the preedit is larger than the text input that the
+ // character preceding the cursor is still visible.
+ qreal x = input->positionToRectangle(0).x();
+ for (int i = 0; i < 3; ++i) {
+ sendPreeditText(preeditText, i + 1);
+ int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
+ QVERIFY(input->cursorRectangle().right() >= width - 3);
+ QVERIFY(input->positionToRectangle(0).x() < x);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+ x = input->positionToRectangle(0).x();
+ }
+ for (int i = 1; i >= 0; --i) {
+ sendPreeditText(preeditText, i + 1);
+ int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
+ QVERIFY(input->cursorRectangle().right() >= width - 3);
+ QVERIFY(input->positionToRectangle(0).x() > x);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+ x = input->positionToRectangle(0).x();
+ }
+
+ // Test incrementing the preedit cursor doesn't cause further
+ // scrolling when right most text is visible.
+ sendPreeditText(preeditText, preeditText.length() - 3);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+ x = input->positionToRectangle(0).x();
+ for (int i = 2; i >= 0; --i) {
+ sendPreeditText(preeditText, preeditText.length() - i);
+ QCOMPARE(input->positionToRectangle(0).x(), x);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+ }
+ for (int i = 1; i < 3; ++i) {
+ sendPreeditText(preeditText, preeditText.length() - i);
+ QCOMPARE(input->positionToRectangle(0).x(), x);
+ QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
+ }
+
+ // Test disabling auto scroll.
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+
+ input->setAutoScroll(false);
+ sendPreeditText(preeditText.mid(0, 3), 1);
+ QCOMPARE(input->positionAt(0), 0);
+ QCOMPARE(input->positionAt(input->width()), 5);
+}
+
+void tst_qquicktextinput::preeditCursorRectangle()
+{
+ QString preeditText = "super";
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputMethodEvent.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+
+ QRect currentRect;
+
+ QInputMethodQueryEvent query(Qt::ImCursorRectangle);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
+
+ // Verify that the micro focus rect is positioned the same for position 0 as
+ // it would be if there was no preedit text.
+ sendPreeditText(preeditText, 0);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCOMPARE(currentRect, previousRect);
+
+ QSignalSpy inputSpy(input, SIGNAL(cursorRectangleChanged()));
+ QSignalSpy panelSpy(qGuiApp->inputPanel(), SIGNAL(cursorRectangleChanged()));
+
+ // Verify that the micro focus rect moves to the left as the cursor position
+ // is incremented.
+ for (int i = 1; i <= 5; ++i) {
+ sendPreeditText(preeditText, i);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QVERIFY(previousRect.left() < currentRect.left());
+ QVERIFY(inputSpy.count() > 0); inputSpy.clear();
+ QVERIFY(panelSpy.count() > 0); panelSpy.clear();
+ previousRect = currentRect;
+ }
+
+ // Verify that if there is no preedit cursor then the micro focus rect is the
+ // same as it would be if it were positioned at the end of the preedit text.
+ sendPreeditText(preeditText, 0);
+ QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
+ QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCOMPARE(currentRect, previousRect);
+ QVERIFY(inputSpy.count() > 0);
+ QVERIFY(panelSpy.count() > 0);
+}
+
+void tst_qquicktextinput::inputContextMouseHandler()
+{
+ PlatformInputContext platformInputContext;
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = &platformInputContext;
+
+ QString text = "supercalifragisiticexpialidocious!";
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+
+ input->setFocus(true);
+ input->setText("");
+
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QFontMetricsF fm(input->font());
+ const qreal y = fm.height() / 2;
+ QPoint position = QPointF(fm.width(text.mid(0, 2)), y).toPoint();
+
+ QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
+ QApplication::sendEvent(input, &inputEvent);
+
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
+ QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
+ QCOMPARE(platformInputContext.m_cursorPosition, 2);
+}
+
+void tst_qquicktextinput::inputMethodComposing()
+{
+ QString text = "supercalifragisiticexpialidocious!";
+
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+ QSignalSpy spy(input, SIGNAL(inputMethodComposingChanged()));
+
+ QCOMPARE(input->isInputMethodComposing(), false);
+ {
+ QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 1);
+
+ {
+ QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(spy.count(), 1);
+
+ {
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_qquicktextinput::cursorRectangleSize()
+{
+ QQuickView *canvas = new QQuickView(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
+ QVERIFY(canvas->rootObject() != 0);
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput *>(canvas->rootObject());
+
+ // make sure cursor rectangle is not at (0,0)
+ textInput->setX(10);
+ textInput->setY(10);
+ textInput->setCursorPosition(3);
+ QVERIFY(textInput != 0);
+ textInput->setFocus(true);
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+
+ QInputMethodQueryEvent event(Qt::ImCursorRectangle);
+ qApp->sendEvent(qApp->inputPanel()->inputItem(), &event);
+ QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
+
+ QRect cursorRectFromItem = textInput->cursorRectangle();
+ QRectF cursorRectFromPositionToRectangle = textInput->positionToRectangle(textInput->cursorPosition());
+
+ // item and input query cursor rectangles match
+ QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
+
+ // item cursor rectangle and positionToRectangle calculations match
+ QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
+
+ // item-canvas transform and input item transform match
+ QCOMPARE(QQuickItemPrivate::get(textInput)->itemToCanvasTransform(), qApp->inputPanel()->inputItemTransform());
+
+ // input panel cursorRectangle property and tranformed item cursor rectangle match
+ QRectF sceneCursorRect = QQuickItemPrivate::get(textInput)->itemToCanvasTransform().mapRect(cursorRectFromItem);
+ QCOMPARE(sceneCursorRect, qApp->inputPanel()->cursorRectangle());
+
+ delete canvas;
+}
+
+void tst_qquicktextinput::tripleClickSelectsAll()
+{
+ QString qmlfile = TESTDATA("positionAt.qml");
+ QQuickView view(QUrl::fromLocalFile(qmlfile));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QQuickTextInput* input = qobject_cast<QQuickTextInput*>(view.rootObject());
+ QVERIFY(input);
+
+ QLatin1String hello("Hello world!");
+ input->setSelectByMouse(true);
+ input->setText(hello);
+
+ // Clicking on the same point inside TextInput three times in a row
+ // should trigger a triple click, thus selecting all the text.
+ QPoint pointInside = input->pos().toPoint() + QPoint(2,2);
+ QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+ QGuiApplication::processEvents();
+ QCOMPARE(input->selectedText(), hello);
+
+ // Now it simulates user moving the mouse between the second and the third click.
+ // In this situation, we don't expect a triple click.
+ QPoint pointInsideButFar = QPoint(input->width(),input->height()) - QPoint(2,2);
+ QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, pointInsideButFar);
+ QGuiApplication::processEvents();
+ QVERIFY(input->selectedText().isEmpty());
+
+ // And now we press the third click too late, so no triple click event is triggered.
+ QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+ QGuiApplication::processEvents();
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 1);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+ QGuiApplication::processEvents();
+ QVERIFY(input->selectedText().isEmpty());
+}
+
+void tst_qquicktextinput::QTBUG_19956_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::newRow("intvalidator") << "qtbug-19956int.qml";
+ QTest::newRow("doublevalidator") << "qtbug-19956double.qml";
+}
+
+void tst_qquicktextinput::keySequence_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QKeySequence>("sequence");
+ QTest::addColumn<int>("selectionStart");
+ QTest::addColumn<int>("selectionEnd");
+ QTest::addColumn<int>("cursorPosition");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("selectedText");
+
+ // 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);
+ QTest::newRow("select end of line")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
+ << 44 << standard.at(0) << standard.at(0).mid(5);
+ QTest::newRow("select end of document") // ### Not handled.
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
+ << 3 << standard.at(0) << QString();
+ QTest::newRow("select end of block")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
+ << 44 << standard.at(0) << standard.at(0).mid(18);
+ QTest::newRow("delete end of line")
+ << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
+ << 24 << standard.at(0).mid(0, 24) << QString();
+ QTest::newRow("move to start of line")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
+ << 0 << standard.at(0) << QString();
+ QTest::newRow("move to start of block")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
+ << 0 << standard.at(0) << QString();
+ 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")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
+ << 2 << standard.at(0) << QString();
+ QTest::newRow("select next char")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
+ << 24 << standard.at(0) << standard.at(0).mid(23, 1);
+ QTest::newRow("select previous char")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
+ << 18 << standard.at(0) << standard.at(0).mid(18, 1);
+ QTest::newRow("move to next word")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 10 << standard.at(0) << QString();
+ QTest::newRow("move to previous word")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 4 << standard.at(0) << QString();
+ QTest::newRow("select previous word")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
+ << 10 << standard.at(0) << standard.at(0).mid(10, 1);
+ 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();
+ 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();
+ 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();
+ 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();
+}
+
+void tst_qquicktextinput::keySequence()
+{
+ QFETCH(QString, text);
+ QFETCH(QKeySequence, sequence);
+ QFETCH(int, selectionStart);
+ QFETCH(int, selectionEnd);
+ QFETCH(int, cursorPosition);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, selectedText);
+
+ if (sequence.isEmpty()) {
+ QSKIP("Key sequence is undefined");
+ }
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; text: \"" + text + "\" }";
+ QDeclarativeComponent 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);
+
+ textInput->select(selectionStart, selectionEnd);
+
+ simulateKeys(&canvas, sequence);
+
+ QCOMPARE(textInput->cursorPosition(), cursorPosition);
+ QCOMPARE(textInput->text(), expectedText);
+ QCOMPARE(textInput->selectedText(), selectedText);
+}
+
+#define NORMAL 0
+#define REPLACE_UNTIL_END 1
+
+void tst_qquicktextinput::undo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<IntList>("insertMode");
+ QTest::addColumn<QStringList>("expectedString");
+ QTest::addColumn<bool>("use_keys");
+
+ for (int i=0; i<2; i++) {
+ QString keys_str = "keyboard";
+ bool use_keys = true;
+ if (i==0) {
+ keys_str = "insert";
+ use_keys = false;
+ }
+
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "1";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "5";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "3";
+
+ insertIndex << 1;
+ insertMode << NORMAL;
+ insertString << "2";
+
+ insertIndex << 3;
+ insertMode << NORMAL;
+ insertString << "4";
+
+ expectedString << "12345";
+ expectedString << "1235";
+ expectedString << "135";
+ expectedString << "15";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "World"; // World
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Hello"; // HelloWorld
+
+ insertIndex << 0;
+ insertMode << NORMAL;
+ insertString << "Well"; // WellHelloWorld
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "WellHelloThereWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "HelloWorld";
+ expectedString << "World";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ {
+ IntList insertIndex;
+ IntList insertMode;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << "Ensuring";
+
+ insertIndex << -1;
+ insertMode << NORMAL;
+ insertString << " instan";
+
+ insertIndex << 9;
+ insertMode << NORMAL;
+ insertString << "an ";
+
+ insertIndex << 10;
+ insertMode << REPLACE_UNTIL_END;
+ insertString << " unique instance.";
+
+ expectedString << "Ensuring a unique instance.";
+ expectedString << "Ensuring an instan";
+ expectedString << "Ensuring instan";
+ expectedString << "";
+
+ QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
+ insertString <<
+ insertIndex <<
+ insertMode <<
+ expectedString <<
+ bool(use_keys);
+ }
+ }
+}
+
+void tst_qquicktextinput::undo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(IntList, insertMode);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
+ QDeclarativeComponent 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);
+
+ int i;
+
+// STEP 1: First build up an undo history by inserting or typing some strings...
+ for (i = 0; i < insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ textInput->setCursorPosition(insertIndex[i]);
+
+ // experimental stuff
+ if (insertMode[i] == REPLACE_UNTIL_END) {
+ textInput->select(insertIndex[i], insertIndex[i] + 8);
+
+ // This is what I actually want...
+ // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
+ }
+
+ for (int j = 0; j < insertString.at(i).length(); j++)
+ QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ }
+
+// STEP 2: Next call undo several times and see if we can restore to the previous state
+ for (i = 0; i < expectedString.size() - 1; ++i) {
+ QCOMPARE(textInput->text(), expectedString[i]);
+ simulateKeys(&canvas, QKeySequence::Undo);
+ }
+
+// STEP 3: Verify that we have undone everything
+ QVERIFY(textInput->text().isEmpty());
+}
+
+void tst_qquicktextinput::redo_data()
+{
+ QTest::addColumn<QStringList>("insertString");
+ QTest::addColumn<IntList>("insertIndex");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ IntList insertIndex;
+ QStringList insertString;
+ QStringList expectedString;
+
+ insertIndex << -1;
+ insertString << "World"; // World
+ insertIndex << 0;
+ insertString << "Hello"; // HelloWorld
+ insertIndex << 0;
+ insertString << "Well"; // WellHelloWorld
+ insertIndex << 9;
+ insertString << "There"; // WellHelloThereWorld;
+
+ expectedString << "World";
+ expectedString << "HelloWorld";
+ expectedString << "WellHelloWorld";
+ expectedString << "WellHelloThereWorld";
+
+ QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
+ }
+}
+
+void tst_qquicktextinput::redo()
+{
+ QFETCH(QStringList, insertString);
+ QFETCH(IntList, insertIndex);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
+ QDeclarativeComponent 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);
+
+ int i;
+ // inserts the diff strings at diff positions
+ for (i = 0; i < insertString.size(); ++i) {
+ if (insertIndex[i] > -1)
+ textInput->setCursorPosition(insertIndex[i]);
+ for (int j = 0; j < insertString.at(i).length(); j++)
+ QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ }
+
+ // undo everything
+ while (!textInput->text().isEmpty())
+ simulateKeys(&canvas, QKeySequence::Undo);
+
+ for (i = 0; i < expectedString.size(); ++i) {
+ simulateKeys(&canvas, QKeySequence::Redo);
+ QCOMPARE(textInput->text() , expectedString[i]);
+ }
+}
+
+void tst_qquicktextinput::undo_keypressevents_data()
+{
+ QTest::addColumn<KeyList>("keys");
+ QTest::addColumn<QStringList>("expectedString");
+
+ {
+ KeyList keys;
+ QStringList expectedString;
+
+ keys << "AFRAID"
+ << Qt::Key_Home
+ << "VERY"
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << Qt::Key_Left
+ << "BE"
+ << Qt::Key_End
+ << "!";
+
+ expectedString << "BEVERYAFRAID!";
+ expectedString << "BEVERYAFRAID";
+ expectedString << "VERYAFRAID";
+ expectedString << "AFRAID";
+
+ QTest::newRow("Inserts and moving cursor") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting '1234'
+ keys << "1234" << Qt::Key_Home
+ // skipping '12'
+ << Qt::Key_Right << Qt::Key_Right
+ // selecting '34'
+ << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
+ // deleting '34'
+ << Qt::Key_Delete;
+
+ expectedString << "12";
+ expectedString << "1234";
+
+ QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'AB12'
+ keys << "AB12"
+ << Qt::Key_Home
+ // selecting 'AB'
+ << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
+ << 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;
+
+ expectedString << "AB";
+ expectedString << "AB12";
+
+ QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'ABCD'
+ keys << "abcd"
+ //move left two
+ << Qt::Key_Left << Qt::Key_Left
+ // inserting '1234'
+ << "1234"
+ // selecting '1234'
+ << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
+ // overwriting '1234' with '5'
+ << "5"
+ // undoing deletion of 'AB'
+ << QKeySequence::Undo
+ // overwriting '1234' with '6'
+ << "6";
+
+ expectedString << "ab6cd";
+ // for versions previous to 3.2 we overwrite needed two undo operations
+ expectedString << "ab1234cd";
+ expectedString << "abcd";
+
+ QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting 'ABC'
+ keys << "ABC"
+ // removes 'C'
+ << Qt::Key_Backspace;
+
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ keys << "ABC"
+ // removes 'C'
+ << Qt::Key_Backspace
+ // inserting 'Z'
+ << "Z";
+
+ expectedString << "ABZ";
+ expectedString << "AB";
+ expectedString << "ABC";
+
+ QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
+ } {
+ KeyList keys;
+ QStringList expectedString;
+
+ // inserting '123'
+ keys << "123" << Qt::Key_Home
+ // selecting '123'
+ << (Qt::Key_End | Qt::ShiftModifier)
+ // overwriting '123' with 'ABC'
+ << "ABC";
+
+ expectedString << "ABC";
+ // for versions previous to 3.2 we overwrite needed two undo operations
+ expectedString << "123";
+
+ QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
+ }
+}
+
+void tst_qquicktextinput::undo_keypressevents()
+{
+ QFETCH(KeyList, keys);
+ QFETCH(QStringList, expectedString);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
+ QDeclarativeComponent 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);
+
+ for (int i = 0; i < expectedString.size(); ++i) {
+ QCOMPARE(textInput->text() , expectedString[i]);
+ simulateKeys(&canvas, QKeySequence::Undo);
+ }
+ QVERIFY(textInput->text().isEmpty());
+}
+
+void tst_qquicktextinput::QTBUG_19956()
+{
+ QFETCH(QString, url);
+
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA(url)));
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
+ QVERIFY(input);
+ input->setFocus(true);
+ QVERIFY(input->hasActiveFocus());
+
+ QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 30);
+ QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
+ QCOMPARE(canvas.rootObject()->property("text").toString(), QString("20"));
+ QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("topvalue", 15);
+ QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 15);
+ QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("topvalue", 25);
+ QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 25);
+ QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("bottomvalue", 21);
+ QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 21);
+ QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("bottomvalue", 10);
+ QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
+ QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
+}
+
+void tst_qquicktextinput::QTBUG_19956_regexp()
+{
+ QUrl url = QUrl::fromLocalFile(TESTDATA("qtbug-19956regexp.qml"));
+
+ QString warning = url.toString() + ":11: Unable to assign [undefined] to QRegExp";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+
+ QQuickView canvas(url);
+ canvas.show();
+ canvas.requestActivateWindow();
+ QTest::qWaitForWindowShown(&canvas);
+ QVERIFY(canvas.rootObject() != 0);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
+ QVERIFY(input);
+ input->setFocus(true);
+ QVERIFY(input->hasActiveFocus());
+
+ canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
+ QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
+ QCOMPARE(canvas.rootObject()->property("text").toString(), QString("abc"));
+ QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("regexvalue", QRegExp("abcd"));
+ QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abcd"));
+ QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
+
+ canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
+ QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
+ QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
+}
+
+QTEST_MAIN(tst_qquicktextinput)
+
+#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/declarative/qquickview/data/error1.qml b/tests/auto/qtquick2/qquickview/data/error1.qml
index 09df679555..09df679555 100644
--- a/tests/auto/declarative/qquickview/data/error1.qml
+++ b/tests/auto/qtquick2/qquickview/data/error1.qml
diff --git a/tests/auto/declarative/qquickview/data/resizemodeitem.qml b/tests/auto/qtquick2/qquickview/data/resizemodeitem.qml
index ed73009b26..ed73009b26 100644
--- a/tests/auto/declarative/qquickview/data/resizemodeitem.qml
+++ b/tests/auto/qtquick2/qquickview/data/resizemodeitem.qml
diff --git a/tests/auto/qtquick2/qquickview/qquickview.pro b/tests/auto/qtquick2/qquickview/qquickview.pro
new file mode 100644
index 0000000000..d4e7c064fa
--- /dev/null
+++ b/tests/auto/qtquick2/qquickview/qquickview.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+TARGET = tst_qquickview
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickview.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+QT += core-private gui-private declarative-private quick-private testlib
diff --git a/tests/auto/qtquick2/qquickview/tst_qquickview.cpp b/tests/auto/qtquick2/qquickview/tst_qquickview.cpp
new file mode 100644
index 0000000000..953374dcab
--- /dev/null
+++ b/tests/auto/qtquick2/qquickview/tst_qquickview.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include "../../shared/util.h"
+#include <QtGui/QWindow>
+#include <QtCore/QDebug>
+
+class tst_QQuickView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuickView();
+
+private slots:
+ void resizemodeitem();
+ void errors();
+};
+
+
+tst_QQuickView::tst_QQuickView()
+{
+}
+
+void tst_QQuickView::resizemodeitem()
+{
+ QWindow window;
+ window.setGeometry(0, 0, 400, 400);
+
+ QQuickView *canvas = new QQuickView(&window);
+ QVERIFY(canvas);
+ canvas->setResizeMode(QQuickView::SizeRootObjectToView);
+ QCOMPARE(QSize(0,0), canvas->initialSize());
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
+ QQuickItem* item = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ canvas->show();
+
+ // initial size from root object
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 200.0);
+ QCOMPARE(canvas->size(), QSize(200, 200));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+ QCOMPARE(canvas->size(), canvas->initialSize());
+
+ // size update from view
+ canvas->resize(QSize(80,100));
+
+ QTRY_COMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QCOMPARE(canvas->size(), QSize(80, 100));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+
+ canvas->setResizeMode(QQuickView::SizeViewToRootObject);
+
+ // size update from view disabled
+ canvas->resize(QSize(60,80));
+ QCOMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QTest::qWait(50);
+ QCOMPARE(canvas->size(), QSize(60, 80));
+
+ // size update from root object
+ item->setWidth(250);
+ item->setHeight(350);
+ QCOMPARE(item->width(), 250.0);
+ QCOMPARE(item->height(), 350.0);
+ QTRY_COMPARE(canvas->size(), QSize(250, 350));
+ QCOMPARE(canvas->size(), QSize(250, 350));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+
+ // reset canvas
+ window.hide();
+ delete canvas;
+ canvas = new QQuickView(&window);
+ QVERIFY(canvas);
+ canvas->setResizeMode(QQuickView::SizeViewToRootObject);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
+ item = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ canvas->show();
+
+ // initial size for root object
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 200.0);
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+ QCOMPARE(canvas->size(), canvas->initialSize());
+
+ // size update from root object
+ item->setWidth(80);
+ item->setHeight(100);
+ QCOMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QTRY_COMPARE(canvas->size(), QSize(80, 100));
+ QCOMPARE(canvas->size(), QSize(80, 100));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+
+ // size update from root object disabled
+ canvas->setResizeMode(QQuickView::SizeRootObjectToView);
+ item->setWidth(60);
+ item->setHeight(80);
+ QCOMPARE(canvas->width(), 80);
+ QCOMPARE(canvas->height(), 100);
+ QCOMPARE(QSize(item->width(), item->height()), canvas->sizeHint());
+
+ // size update from view
+ canvas->resize(QSize(200,300));
+ QTest::qWait(50);
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 300.0);
+ QCOMPARE(canvas->size(), QSize(200, 300));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+
+ window.hide();
+ delete canvas;
+
+ // if we set a specific size for the view then it should keep that size
+ // for SizeRootObjectToView mode.
+ canvas = new QQuickView(&window);
+ canvas->resize(300, 300);
+ canvas->setResizeMode(QQuickView::SizeRootObjectToView);
+ QCOMPARE(QSize(0,0), canvas->initialSize());
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizemodeitem.qml")));
+ canvas->resize(300, 300);
+ item = qobject_cast<QQuickItem*>(canvas->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ canvas->show();
+ QTest::qWait(50);
+
+ // initial size from root object
+ QCOMPARE(item->width(), 300.0);
+ QCOMPARE(item->height(), 300.0);
+ QCOMPARE(canvas->size(), QSize(300, 300));
+ QCOMPARE(canvas->size(), canvas->sizeHint());
+ QCOMPARE(canvas->initialSize(), QSize(200, 200)); // initial object size
+
+ delete canvas;
+}
+
+static void silentErrorsMsgHandler(QtMsgType, const char *)
+{
+}
+
+void tst_QQuickView::errors()
+{
+ QQuickView *canvas = new QQuickView;
+ QVERIFY(canvas);
+ QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
+ canvas->setSource(QUrl::fromLocalFile(TESTDATA("error1.qml")));
+ qInstallMsgHandler(old);
+ QVERIFY(canvas->status() == QQuickView::Error);
+ QVERIFY(canvas->errors().count() == 1);
+ delete canvas;
+}
+
+
+QTEST_MAIN(tst_QQuickView)
+
+#include "tst_qquickview.moc"
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/create.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml
index 3475a0dace..3475a0dace 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/create.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/create.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/datalist-package.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/datalist-package.qml
index ae3bd81d91..ae3bd81d91 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/datalist-package.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/datalist-package.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/datalist.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/datalist.qml
index 8ce59caddc..8ce59caddc 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/datalist.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/datalist.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/groups-invalid.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups-invalid.qml
index 70c6f9f995..70c6f9f995 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/groups-invalid.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups-invalid.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/groups-package.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups-package.qml
index ea5ad5d3bd..ea5ad5d3bd 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/groups-package.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups-package.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/groups.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups.qml
index 7502dd2502..7502dd2502 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/groups.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/groups.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_listView.qml
index 103c4d2eb6..103c4d2eb6 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_listView.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_listView.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_package.qml
index b47f22dc34..b47f22dc34 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_package.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_package.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml
index bc619124fd..bc619124fd 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_pathView.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml
index e97e0dad2e..e97e0dad2e 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/itemsDestroyed_repeater.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/modelproperties.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties.qml
index 73b766f1af..73b766f1af 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/modelproperties.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/modelproperties2.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties2.qml
index ea5c240b29..ea5c240b29 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/modelproperties2.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/modelproperties2.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/objectlist.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/objectlist.qml
index b3952a8a4d..b3952a8a4d 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/objectlist.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/objectlist.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/onChanged.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/onChanged.qml
index 71dc7d72d7..71dc7d72d7 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/onChanged.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/onChanged.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/singlerole1.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole1.qml
index c471893e1d..c471893e1d 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/singlerole1.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole1.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/singlerole2.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole2.qml
index ab1798999d..ab1798999d 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/singlerole2.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/singlerole2.qml
diff --git a/tests/auto/declarative/qquickvisualdatamodel/data/visualdatamodel.qml b/tests/auto/qtquick2/qquickvisualdatamodel/data/visualdatamodel.qml
index 0d4d9e2e46..0d4d9e2e46 100644
--- a/tests/auto/declarative/qquickvisualdatamodel/data/visualdatamodel.qml
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/data/visualdatamodel.qml
diff --git a/tests/auto/qtquick2/qquickvisualdatamodel/qquickvisualdatamodel.pro b/tests/auto/qtquick2/qquickvisualdatamodel/qquickvisualdatamodel.pro
new file mode 100644
index 0000000000..8e87e10a97
--- /dev/null
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/qquickvisualdatamodel.pro
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qquickvisualdatamodel
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qquickvisualdatamodel.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private quick-private widgets testlib
diff --git a/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
new file mode 100644
index 0000000000..f0e6228d29
--- /dev/null
+++ b/tests/auto/qtquick2/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -0,0 +1,1865 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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 "../../shared/util.h"
+#include <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QStandardItemModel>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtQuick/qquickview.h>
+#include <private/qquicklistview_p.h>
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuick/private/qquickvisualdatamodel_p.h>
+#include <private/qdeclarativevaluetype_p.h>
+#include <private/qdeclarativechangeset_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <math.h>
+
+template <typename T, int N> int lengthOf(const T (&)[N]) { return N; }
+
+static void initStandardTreeModel(QStandardItemModel *model)
+{
+ QStandardItem *item;
+ item = new QStandardItem(QLatin1String("Row 1 Item"));
+ model->insertRow(0, item);
+
+ item = new QStandardItem(QLatin1String("Row 2 Item"));
+ item->setCheckable(true);
+ model->insertRow(1, item);
+
+ QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
+ item->setChild(0, childItem);
+
+ item = new QStandardItem(QLatin1String("Row 3 Item"));
+ item->setIcon(QIcon());
+ model->insertRow(2, item);
+}
+
+class SingleRoleModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ SingleRoleModel(const QByteArray &role = "name", QObject * /* parent */ = 0) {
+ QHash<int, QByteArray> roles;
+ roles.insert(Qt::DisplayRole , role);
+ setRoleNames(roles);
+ list << "one" << "two" << "three" << "four";
+ }
+
+ void emitMove(int sourceFirst, int sourceLast, int destinationChild) {
+ emit beginMoveRows(QModelIndex(), sourceFirst, sourceLast, QModelIndex(), destinationChild);
+ emit endMoveRows();
+ }
+
+ QStringList list;
+
+public slots:
+ void set(int idx, QString string) {
+ list[idx] = string;
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+protected:
+ int rowCount(const QModelIndex & /* parent */ = QModelIndex()) const {
+ return list.count();
+ }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
+ if (role == Qt::DisplayRole)
+ return list.at(index.row());
+ return QVariant();
+ }
+};
+
+
+class tst_qquickvisualdatamodel : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qquickvisualdatamodel();
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void rootIndex();
+ void updateLayout_data();
+ void updateLayout();
+ void childChanged_data();
+ void childChanged();
+ void objectListModel();
+ void singleRole();
+ void modelProperties();
+ void noDelegate_data();
+ void noDelegate();
+ void itemsDestroyed_data();
+ void itemsDestroyed();
+ void qaimRowsMoved();
+ void qaimRowsMoved_data();
+ void remove_data();
+ void remove();
+ void move_data();
+ void move();
+ void groups_data();
+ void groups();
+ void invalidGroups();
+ void get();
+ void onChanged_data();
+ void onChanged();
+ void create();
+ void incompleteModel();
+
+private:
+ template <int N> void groups_verify(
+ const SingleRoleModel &model,
+ QQuickItem *contentItem,
+ const int (&mIndex)[N],
+ const int (&iIndex)[N],
+ const int (&vIndex)[N],
+ const int (&sIndex)[N],
+ const bool (&vMember)[N],
+ const bool (&sMember)[N]);
+
+ template <int N> void get_verify(
+ const SingleRoleModel &model,
+ QQuickVisualDataModel *visualModel,
+ QQuickVisualDataGroup *visibleItems,
+ QQuickVisualDataGroup *selectedItems,
+ const int (&mIndex)[N],
+ const int (&iIndex)[N],
+ const int (&vIndex)[N],
+ const int (&sIndex)[N],
+ const bool (&vMember)[N],
+ const bool (&sMember)[N]);
+
+ bool failed;
+ QDeclarativeEngine engine;
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &objectName, int index);
+};
+
+Q_DECLARE_METATYPE(QDeclarativeChangeSet)
+
+void tst_qquickvisualdatamodel::initTestCase()
+{
+ qRegisterMetaType<QDeclarativeChangeSet>();
+}
+
+void tst_qquickvisualdatamodel::cleanupTestCase()
+{
+
+}
+class DataObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
+
+public:
+ DataObject(QObject *parent=0) : QObject(parent) {}
+ DataObject(const QString &name, const QString &color, QObject *parent=0)
+ : QObject(parent), m_name(name), m_color(color) { }
+
+
+ QString name() const { return m_name; }
+ void setName(const QString &name) {
+ if (name != m_name) {
+ m_name = name;
+ emit nameChanged();
+ }
+ }
+
+ QString color() const { return m_color; }
+ void setColor(const QString &color) {
+ if (color != m_color) {
+ m_color = color;
+ emit colorChanged();
+ }
+ }
+
+signals:
+ void nameChanged();
+ void colorChanged();
+
+private:
+ QString m_name;
+ QString m_color;
+};
+
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ T result = expr.evaluate().value<T>();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result;
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
+tst_qquickvisualdatamodel::tst_qquickvisualdatamodel()
+{
+}
+
+void tst_qquickvisualdatamodel::rootIndex()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ engine.rootContext()->setContextProperty("myModel", &model);
+
+ QQuickVisualDataModel *obj = qobject_cast<QQuickVisualDataModel*>(c.create());
+ QVERIFY(obj != 0);
+
+ QMetaObject::invokeMethod(obj, "setRoot");
+ QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
+
+ QMetaObject::invokeMethod(obj, "setRootToParent");
+ QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
+
+ QMetaObject::invokeMethod(obj, "setRoot");
+ QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
+ model.clear(); // will emit modelReset()
+ QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
+
+ delete obj;
+}
+
+void tst_qquickvisualdatamodel::updateLayout_data()
+{
+ QTest::addColumn<QUrl>("source");
+
+ QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
+ QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
+}
+
+void tst_qquickvisualdatamodel::updateLayout()
+{
+ QFETCH(QUrl, source);
+
+ QQuickView view;
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ view.rootContext()->setContextProperty("myModel", &model);
+
+ view.setSource(source);
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 1 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 1);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 2 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 2);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 3 Item"));
+
+ model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
+
+ name = findItem<QQuickText>(contentItem, "display", 0);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 3 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 1);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 2 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 2);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 1 Item"));
+}
+
+void tst_qquickvisualdatamodel::childChanged_data()
+{
+ QTest::addColumn<QUrl>("source");
+
+ QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
+ QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
+}
+
+void tst_qquickvisualdatamodel::childChanged()
+{
+ QFETCH(QUrl, source);
+
+ QQuickView view;
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ view.rootContext()->setContextProperty("myModel", &model);
+
+ view.setSource(source);
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *vdm = listview->findChild<QQuickVisualDataModel*>("visualModel");
+ vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
+ QCOMPARE(listview->count(), 1);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 2 Child Item"));
+
+ model.item(1,0)->child(0,0)->setText("Row 2 updated child");
+
+ name = findItem<QQuickText>(contentItem, "display", 0);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 2 updated child"));
+
+ model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
+ QCOMPARE(listview->count(), 2);
+
+ name = findItem<QQuickText>(contentItem, "display", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
+
+ model.item(1,0)->takeRow(1);
+ name = findItem<QQuickText>(contentItem, "display", 1);
+ QVERIFY(name == 0);
+
+ vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
+ QCOMPARE(listview->count(), 3);
+ name = findItem<QQuickText>(contentItem, "display", 0);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 1 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 1);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 2 Item"));
+ name = findItem<QQuickText>(contentItem, "display", 2);
+ QVERIFY(name);
+ QCOMPARE(name->text(), QString("Row 3 Item"));
+}
+
+void tst_qquickvisualdatamodel::objectListModel()
+{
+ QQuickView view;
+
+ QList<QObject*> dataList;
+ dataList.append(new DataObject("Item 1", "red"));
+ dataList.append(new DataObject("Item 2", "green"));
+ dataList.append(new DataObject("Item 3", "blue"));
+ dataList.append(new DataObject("Item 4", "yellow"));
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("objectlist.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "name", 0);
+ QCOMPARE(name->text(), QString("Item 1"));
+
+ QQuickText *section = findItem<QQuickText>(contentItem, "section", 0);
+ QCOMPARE(section->text(), QString("Item 1"));
+
+ dataList[0]->setProperty("name", QLatin1String("Changed"));
+ QCOMPARE(name->text(), QString("Changed"));
+}
+
+void tst_qquickvisualdatamodel::singleRole()
+{
+ {
+ QQuickView view;
+
+ SingleRoleModel model;
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole1.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
+ QCOMPARE(name->text(), QString("two"));
+
+ model.set(1, "Changed");
+ QCOMPARE(name->text(), QString("Changed"));
+ }
+ {
+ QQuickView view;
+
+ SingleRoleModel model;
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
+ QCOMPARE(name->text(), QString("two"));
+
+ model.set(1, "Changed");
+ QCOMPARE(name->text(), QString("Changed"));
+ }
+ {
+ QQuickView view;
+
+ SingleRoleModel model("modelData");
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
+ QCOMPARE(name->text(), QString("two"));
+
+ model.set(1, "Changed");
+ QCOMPARE(name->text(), QString("Changed"));
+ }
+}
+
+void tst_qquickvisualdatamodel::modelProperties()
+{
+ {
+ QQuickView view;
+
+ SingleRoleModel model;
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(),QString("two"));
+ QCOMPARE(delegate->property("test2").toString(),QString("two"));
+ QCOMPARE(delegate->property("test3").toString(),QString("two"));
+ QCOMPARE(delegate->property("test4").toString(),QString("two"));
+ QVERIFY(!delegate->property("test9").isValid());
+ QCOMPARE(delegate->property("test5").toString(),QString(""));
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ {
+ QQuickView view;
+
+ QList<QObject*> dataList;
+ dataList.append(new DataObject("Item 1", "red"));
+ dataList.append(new DataObject("Item 2", "green"));
+ dataList.append(new DataObject("Item 3", "blue"));
+ dataList.append(new DataObject("Item 4", "yellow"));
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
+ QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
+ QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
+ QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
+ QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
+ QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ {
+ QQuickView view;
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ view.rootContext()->setContextProperty("myModel", &model);
+
+ QUrl source(QUrl::fromLocalFile(TESTDATA("modelproperties2.qml")));
+
+ //3 items, 3 i each
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
+
+ view.setSource(source);
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
+ QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
+ QVERIFY(!delegate->property("test3").isValid());
+ QVERIFY(!delegate->property("test4").isValid());
+ QVERIFY(!delegate->property("test5").isValid());
+ QVERIFY(!delegate->property("test9").isValid());
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ //### should also test QStringList and QVariantList
+}
+
+void tst_qquickvisualdatamodel::noDelegate_data()
+{
+ QTest::addColumn<QUrl>("source");
+
+ QTest::newRow("item delegate") << QUrl::fromLocalFile(TESTDATA("datalist.qml"));
+ QTest::newRow("package delegate") << QUrl::fromLocalFile(TESTDATA("datalist-package.qml"));
+}
+
+void tst_qquickvisualdatamodel::noDelegate()
+{
+ QFETCH(QUrl, source);
+
+ QQuickView view;
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ view.rootContext()->setContextProperty("myModel", &model);
+
+ view.setSource(source);
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickVisualDataModel *vdm = listview->findChild<QQuickVisualDataModel*>("visualModel");
+ QVERIFY(vdm != 0);
+ QCOMPARE(vdm->count(), 3);
+
+ vdm->setDelegate(0);
+ QCOMPARE(vdm->count(), 0);
+}
+
+void tst_qquickvisualdatamodel::itemsDestroyed_data()
+{
+ QTest::addColumn<QUrl>("source");
+
+ QTest::newRow("listView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_listView.qml"));
+ QTest::newRow("package") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_package.qml"));
+ QTest::newRow("pathView") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_pathView.qml"));
+ QTest::newRow("repeater") << QUrl::fromLocalFile(TESTDATA("itemsDestroyed_repeater.qml"));
+}
+
+void tst_qquickvisualdatamodel::itemsDestroyed()
+{
+ QFETCH(QUrl, source);
+
+ QDeclarativeGuard<QQuickItem> delegate;
+
+ {
+ QQuickView view;
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+ view.rootContext()->setContextProperty("myModel", &model);
+ view.setSource(source);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QVERIFY(delegate = findItem<QQuickItem>(view.rootItem(), "delegate", 1));
+ }
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!delegate);
+}
+
+void tst_qquickvisualdatamodel::qaimRowsMoved()
+{
+ // Test parameters passed in QAIM::rowsMoved() signal are converted correctly
+ // when translated and emitted as the QListModelInterface::itemsMoved() signal
+ QFETCH(int, sourceFirst);
+ QFETCH(int, sourceLast);
+ QFETCH(int, destinationChild);
+ QFETCH(int, expectFrom);
+ QFETCH(int, expectTo);
+ QFETCH(int, expectCount);
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
+
+ SingleRoleModel model;
+ model.list.clear();
+ for (int i=0; i<30; i++)
+ model.list << ("item " + i);
+ engine.rootContext()->setContextProperty("myModel", &model);
+
+ QQuickVisualDataModel *obj = qobject_cast<QQuickVisualDataModel*>(c.create());
+ QVERIFY(obj != 0);
+
+ QSignalSpy spy(obj, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)));
+ model.emitMove(sourceFirst, sourceLast, destinationChild);
+ // QAbstractItemModel also emits the changed signal when items are moved.
+ QCOMPARE(spy.count(), 2);
+
+ bool move = false;
+ for (int i = 0; i < 2; ++i) {
+ QCOMPARE(spy[1].count(), 2);
+ QDeclarativeChangeSet changeSet = spy[i][0].value<QDeclarativeChangeSet>();
+ if (!changeSet.changes().isEmpty())
+ continue;
+ move = true;
+ QCOMPARE(changeSet.removes().count(), 1);
+ QCOMPARE(changeSet.removes().at(0).index, expectFrom);
+ QCOMPARE(changeSet.removes().at(0).count, expectCount);
+ QCOMPARE(changeSet.inserts().count(), 1);
+ QCOMPARE(changeSet.inserts().at(0).index, expectTo);
+ QCOMPARE(changeSet.inserts().at(0).count, expectCount);
+ QCOMPARE(changeSet.removes().at(0).moveId, changeSet.inserts().at(0).moveId);
+ QCOMPARE(spy[i][1].toBool(), false);
+ }
+ QVERIFY(move);
+
+ delete obj;
+}
+
+void tst_qquickvisualdatamodel::qaimRowsMoved_data()
+{
+ QTest::addColumn<int>("sourceFirst");
+ QTest::addColumn<int>("sourceLast");
+ QTest::addColumn<int>("destinationChild");
+ QTest::addColumn<int>("expectFrom");
+ QTest::addColumn<int>("expectTo");
+ QTest::addColumn<int>("expectCount");
+
+ QTest::newRow("move 1 forward")
+ << 1 << 1 << 6
+ << 1 << 5 << 1;
+
+ QTest::newRow("move 1 backwards")
+ << 4 << 4 << 1
+ << 4 << 1 << 1;
+
+ QTest::newRow("move multiple forwards")
+ << 0 << 2 << 13
+ << 0 << 10 << 3;
+
+ QTest::newRow("move multiple forwards, with same to")
+ << 0 << 1 << 3
+ << 0 << 1 << 2;
+
+ QTest::newRow("move multiple backwards")
+ << 10 << 14 << 1
+ << 10 << 1 << 5;
+}
+
+void tst_qquickvisualdatamodel::remove_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QString>("package delegate");
+
+ QTest::newRow("item delegate")
+ << QUrl::fromLocalFile(TESTDATA("groups.qml"))
+ << QString();
+ QTest::newRow("package")
+ << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
+ << QString("package.");
+}
+
+void tst_qquickvisualdatamodel::remove()
+{
+ QQuickView view;
+
+ SingleRoleModel model;
+ model.list = QStringList()
+ << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six"
+ << "seven"
+ << "eight"
+ << "nine"
+ << "ten"
+ << "eleven"
+ << "twelve";
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
+ QVERIFY(visualModel);
+
+ {
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.remove(2)");
+ QCOMPARE(listview->count(), 11);
+ QCOMPARE(visualModel->items()->count(), 11);
+ static const int mIndex[] = { 0, 1, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.remove(1, 4)");
+ QCOMPARE(listview->count(), 7);
+ QCOMPARE(visualModel->items()->count(), 7);
+ static const int mIndex[] = { 0, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
+ evaluate<void>(visualModel, "items.remove(-8, 4)");
+ QCOMPARE(listview->count(), 7);
+ QCOMPARE(visualModel->items()->count(), 7);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
+ evaluate<void>(visualModel, "items.remove(12, 2)");
+ QCOMPARE(listview->count(), 7);
+ QCOMPARE(visualModel->items()->count(), 7);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
+ evaluate<void>(visualModel, "items.remove(5, 3)");
+ QCOMPARE(listview->count(), 7);
+ QCOMPARE(visualModel->items()->count(), 7);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: invalid count");
+ evaluate<void>(visualModel, "items.remove(5, -2)");
+ QCOMPARE(listview->count(), 7);
+ QCOMPARE(visualModel->items()->count(), 7);
+ }
+}
+
+void tst_qquickvisualdatamodel::move_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QString>("package delegate");
+
+ QTest::newRow("item delegate")
+ << QUrl::fromLocalFile(TESTDATA("groups.qml"))
+ << QString();
+ QTest::newRow("package")
+ << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
+ << QString("package.");
+}
+
+void tst_qquickvisualdatamodel::move()
+{
+ QQuickView view;
+
+ SingleRoleModel model;
+ model.list = QStringList()
+ << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six"
+ << "seven"
+ << "eight"
+ << "nine"
+ << "ten"
+ << "eleven"
+ << "twelve";
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
+ QVERIFY(visualModel);
+
+ {
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.move(2, 4)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 0, 1, 3, 4, 2, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.move(4, 2)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.move(8, 0, 4)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 8, 9,10,11, 0, 1, 2, 3, 4, 5, 6, 7 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ evaluate<void>(visualModel, "items.move(3, 4, 5)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ static const int mIndex[] = { 8, 9,10,4, 11, 0, 1, 2, 3, 5, 6, 7 };
+ static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+
+ for (int i = 0; i < lengthOf(mIndex); ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
+ QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
+ QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
+ }
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: invalid count");
+ evaluate<void>(visualModel, "items.move(5, 2, -2)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ evaluate<void>(visualModel, "items.move(-6, 2, 1)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ evaluate<void>(visualModel, "items.move(15, 2, 1)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ evaluate<void>(visualModel, "items.move(11, 1, 3)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ evaluate<void>(visualModel, "items.move(2, -5, 1)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ evaluate<void>(visualModel, "items.move(2, 14, 1)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ evaluate<void>(visualModel, "items.move(2, 11, 4)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ }
+}
+
+void tst_qquickvisualdatamodel::groups_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::addColumn<QString>("part");
+
+ QTest::newRow("item delegate")
+ << QUrl::fromLocalFile(TESTDATA("groups.qml"))
+ << QString();
+ QTest::newRow("package")
+ << QUrl::fromLocalFile(TESTDATA("groups-package.qml"))
+ << QString("visualModel.parts.package.");
+}
+
+template <int N> void tst_qquickvisualdatamodel::groups_verify(
+ const SingleRoleModel &model,
+ QQuickItem *contentItem,
+ const int (&mIndex)[N],
+ const int (&iIndex)[N],
+ const int (&vIndex)[N],
+ const int (&sIndex)[N],
+ const bool (&vMember)[N],
+ const bool (&sMember)[N])
+{
+ failed = true;
+ for (int i = 0; i < N; ++i) {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", mIndex[i]);
+ QVERIFY(delegate);
+ QCOMPARE(evaluate<QString>(delegate, "test1"), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<int>(delegate, "test2") , mIndex[i]);
+ QCOMPARE(evaluate<int>(delegate, "test3") , iIndex[i]);
+ QCOMPARE(evaluate<bool>(delegate, "test4"), true);
+ QCOMPARE(evaluate<int>(delegate, "test5") , vIndex[i]);
+ QCOMPARE(evaluate<bool>(delegate, "test6"), vMember[i]);
+ QCOMPARE(evaluate<int>(delegate, "test7") , sIndex[i]);
+ QCOMPARE(evaluate<bool>(delegate, "test8"), sMember[i]);
+ QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("items") , QBool(true));
+ QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("visible") , QBool(vMember[i]));
+ QCOMPARE(evaluate<QStringList>(delegate, "test9").contains("selected"), QBool(sMember[i]));
+ }
+ failed = false;
+}
+
+#define VERIFY_GROUPS \
+ groups_verify(model, contentItem, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
+ QVERIFY(!failed)
+
+
+void tst_qquickvisualdatamodel::groups()
+{
+ QFETCH(QUrl, source);
+ QFETCH(QString, part);
+
+ QQuickView view;
+
+ SingleRoleModel model;
+ model.list = QStringList()
+ << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six"
+ << "seven"
+ << "eight"
+ << "nine"
+ << "ten"
+ << "eleven"
+ << "twelve";
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(source);
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *visualModel = listview->findChild<QQuickVisualDataModel *>("visualModel");
+ QVERIFY(visualModel);
+
+ QQuickVisualDataGroup *visibleItems = listview->findChild<QQuickVisualDataGroup *>("visibleItems");
+ QVERIFY(visibleItems);
+
+ QQuickVisualDataGroup *selectedItems = listview->findChild<QQuickVisualDataGroup *>("selectedItems");
+ QVERIFY(selectedItems);
+
+ const bool f = false;
+ const bool t = true;
+
+ {
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 0);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
+ VERIFY_GROUPS;
+ } {
+ evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 1);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
+ VERIFY_GROUPS;
+ } {
+ evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 4);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
+ static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
+ VERIFY_GROUPS;
+ } {
+ evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 11);
+ QCOMPARE(selectedItems->count(), 5);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
+ static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
+ static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
+ VERIFY_GROUPS;
+ } {
+ evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
+ static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
+ VERIFY_GROUPS;
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: invalid count");
+ evaluate<void>(visualModel, "items.addGroups(11, -4, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
+ evaluate<void>(visualModel, "items.addGroups(-1, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
+ evaluate<void>(visualModel, "items.addGroups(14, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
+ evaluate<void>(visualModel, "items.addGroups(11, 5, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: invalid count");
+ evaluate<void>(visualModel, "items.setGroups(11, -4, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
+ evaluate<void>(visualModel, "items.setGroups(-1, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
+ evaluate<void>(visualModel, "items.setGroups(14, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
+ evaluate<void>(visualModel, "items.setGroups(11, 5, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: invalid count");
+ evaluate<void>(visualModel, "items.removeGroups(11, -4, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
+ evaluate<void>(visualModel, "items.removeGroups(-1, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
+ evaluate<void>(visualModel, "items.removeGroups(14, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
+ evaluate<void>(visualModel, "items.removeGroups(11, 5, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ } {
+ evaluate<void>(visualModel, part + "filterOnGroup = \"visible\"");
+ QCOMPARE(listview->count(), 9);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("visible"));
+ } {
+ evaluate<void>(visualModel, part + "filterOnGroup = \"selected\"");
+ QCOMPARE(listview->count(), 2);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("selected"));
+ } {
+ evaluate<void>(visualModel, part + "filterOnGroup = undefined");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ QCOMPARE(evaluate<QString>(visualModel, part + "filterOnGroup"), QString("items"));
+ } {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 5);
+ QVERIFY(delegate);
+
+ evaluate<void>(delegate, "hide()");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 8);
+ QCOMPARE(selectedItems->count(), 2);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
+ static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
+ VERIFY_GROUPS;
+ } {
+ QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 5);
+ QVERIFY(delegate);
+
+ evaluate<void>(delegate, "select()");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 8);
+ QCOMPARE(selectedItems->count(), 3);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
+ static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
+ static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
+ VERIFY_GROUPS;
+ } {
+ evaluate<void>(visualModel, "items.move(2, 6, 3)");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 8);
+ QCOMPARE(selectedItems->count(), 3);
+ static const int mIndex [] = { 0, 1, 5, 6, 7, 8, 2, 3, 4, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7 };
+ static const bool vMember[] = { t, t, f, f, f, t, f, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 };
+ static const bool sMember[] = { f, f, t, f, f, t, f, f, f, t, f, f };
+ VERIFY_GROUPS;
+ }
+}
+
+template <int N> void tst_qquickvisualdatamodel::get_verify(
+ const SingleRoleModel &model,
+ QQuickVisualDataModel *visualModel,
+ QQuickVisualDataGroup *visibleItems,
+ QQuickVisualDataGroup *selectedItems,
+ const int (&mIndex)[N],
+ const int (&iIndex)[N],
+ const int (&vIndex)[N],
+ const int (&sIndex)[N],
+ const bool (&vMember)[N],
+ const bool (&sMember)[N])
+{
+ failed = true;
+ for (int i = 0; i < N; ++i) {
+ QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.name").arg(i)), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.modelData").arg(i)), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).model.index").arg(i)), mIndex[i]);
+ QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).itemsIndex").arg(i)), iIndex[i]);
+ QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inItems").arg(i)), true);
+ QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).visibleIndex").arg(i)), vIndex[i]);
+ QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inVisible").arg(i)), vMember[i]);
+ QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).selectedIndex").arg(i)), sIndex[i]);
+ QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inSelected").arg(i)), sMember[i]);
+ QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"items\")").arg(i)), true);
+ QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"visible\")").arg(i)), vMember[i]);
+ QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"selected\")").arg(i)), sMember[i]);
+
+ if (vMember[i]) {
+ QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.name").arg(vIndex[i])), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.modelData").arg(vIndex[i])), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).model.index").arg(vIndex[i])), mIndex[i]);
+ QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).itemsIndex").arg(vIndex[i])), iIndex[i]);
+ QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inItems").arg(vIndex[i])), true);
+ QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).visibleIndex").arg(vIndex[i])), vIndex[i]);
+ QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inVisible").arg(vIndex[i])), vMember[i]);
+ QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).selectedIndex").arg(vIndex[i])), sIndex[i]);
+ QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inSelected").arg(vIndex[i])), sMember[i]);
+
+ QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"items\")").arg(vIndex[i])), true);
+ QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"visible\")").arg(vIndex[i])), vMember[i]);
+ QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"selected\")").arg(vIndex[i])), sMember[i]);
+ }
+ if (sMember[i]) {
+ QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.name").arg(sIndex[i])), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.modelData").arg(sIndex[i])), model.list.at(mIndex[i]));
+ QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).model.index").arg(sIndex[i])), mIndex[i]);
+ QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).itemsIndex").arg(sIndex[i])), iIndex[i]);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inItems").arg(sIndex[i])), true);
+ QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).visibleIndex").arg(sIndex[i])), vIndex[i]);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inVisible").arg(sIndex[i])), vMember[i]);
+ QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).selectedIndex").arg(sIndex[i])), sIndex[i]);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inSelected").arg(sIndex[i])), sMember[i]);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"items\")").arg(sIndex[i])), true);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"visible\")").arg(sIndex[i])), vMember[i]);
+ QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"selected\")").arg(sIndex[i])), sMember[i]);
+ }
+ }
+ failed = false;
+}
+
+#define VERIFY_GET \
+ get_verify(model, visualModel, visibleItems, selectedItems, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
+ QVERIFY(!failed)
+
+void tst_qquickvisualdatamodel::get()
+{
+ QQuickView view;
+
+ SingleRoleModel model;
+ model.list = QStringList()
+ << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six"
+ << "seven"
+ << "eight"
+ << "nine"
+ << "ten"
+ << "eleven"
+ << "twelve";
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
+ QVERIFY(visualModel);
+
+ QQuickVisualDataGroup *visibleItems = visualModel->findChild<QQuickVisualDataGroup *>("visibleItems");
+ QVERIFY(visibleItems);
+
+ QQuickVisualDataGroup *selectedItems = visualModel->findChild<QQuickVisualDataGroup *>("selectedItems");
+ QVERIFY(selectedItems);
+
+ QV8Engine *v8Engine = QDeclarativeEnginePrivate::getV8Engine(ctxt->engine());
+ QVERIFY(v8Engine);
+
+ const bool f = false;
+ const bool t = true;
+
+ {
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 0);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 1);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 12);
+ QCOMPARE(selectedItems->count(), 4);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
+ static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 11);
+ QCOMPARE(selectedItems->count(), 5);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
+ static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
+ static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
+ static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.get(5).inVisible = false");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 8);
+ QCOMPARE(selectedItems->count(), 2);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
+ static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.get(5).inSelected = true");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 8);
+ QCOMPARE(selectedItems->count(), 3);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
+ static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
+ static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
+ VERIFY_GET;
+ } {
+ evaluate<void>(visualModel, "items.get(5).groups = [\"visible\", \"items\"]");
+ QCOMPARE(listview->count(), 12);
+ QCOMPARE(visualModel->items()->count(), 12);
+ QCOMPARE(visibleItems->count(), 9);
+ QCOMPARE(selectedItems->count(), 2);
+ static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
+ static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
+ static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
+ static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
+ static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
+ VERIFY_GET;
+ }
+}
+
+void tst_qquickvisualdatamodel::invalidGroups()
+{
+ QUrl source = QUrl::fromLocalFile(TESTDATA("groups-invalid.qml"));
+ QTest::ignoreMessage(QtWarningMsg, (source.toString() + ":12:9: QML VisualDataGroup: " + QQuickVisualDataGroup::tr("Group names must start with a lower case letter")).toUtf8());
+
+ QDeclarativeComponent component(&engine, source);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object);
+
+ QCOMPARE(evaluate<int>(object.data(), "groups.length"), 4);
+ QCOMPARE(evaluate<QString>(object.data(), "groups[0].name"), QString("items"));
+ QCOMPARE(evaluate<QString>(object.data(), "groups[1].name"), QString("persistedItems"));
+ QCOMPARE(evaluate<QString>(object.data(), "groups[2].name"), QString("visible"));
+ QCOMPARE(evaluate<QString>(object.data(), "groups[3].name"), QString("selected"));
+}
+
+void tst_qquickvisualdatamodel::onChanged_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QStringList>("tests");
+
+ QTest::newRow("item appended")
+ << QString("listModel.append({\"number\": \"five\"})")
+ << (QStringList()
+ << "verify(vm.removed, [], [], [])"
+ << "verify(vm.inserted, [4], [1], [undefined])"
+ << "verify(vi.removed, [], [], [])"
+ << "verify(vi.inserted, [4], [1], [undefined])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+ QTest::newRow("item prepended")
+ << QString("listModel.insert(0, {\"number\": \"five\"})")
+ << (QStringList()
+ << "verify(vm.removed, [], [], [])"
+ << "verify(vm.inserted, [0], [1], [undefined])"
+ << "verify(vi.removed, [], [], [])"
+ << "verify(vi.inserted, [0], [1], [undefined])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+ QTest::newRow("item inserted")
+ << QString("listModel.insert(2, {\"number\": \"five\"})")
+ << (QStringList()
+ << "verify(vm.removed, [], [], [])"
+ << "verify(vm.inserted, [2], [1], [undefined])"
+ << "verify(vi.removed, [], [], [])"
+ << "verify(vi.inserted, [2], [1], [undefined])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+
+ QTest::newRow("item removed tail")
+ << QString("listModel.remove(3)")
+ << (QStringList()
+ << "verify(vm.removed, [3], [1], [undefined])"
+ << "verify(vm.inserted, [], [], [])"
+ << "verify(vi.removed, [3], [1], [undefined])"
+ << "verify(vi.inserted, [], [], [])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+ QTest::newRow("item removed head")
+ << QString("listModel.remove(0)")
+ << (QStringList()
+ << "verify(vm.removed, [0], [1], [undefined])"
+ << "verify(vm.inserted, [], [], [])"
+ << "verify(vi.removed, [0], [1], [undefined])"
+ << "verify(vi.inserted, [], [], [])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+ QTest::newRow("item removed middle")
+ << QString("listModel.remove(1)")
+ << (QStringList()
+ << "verify(vm.removed, [1], [1], [undefined])"
+ << "verify(vm.inserted, [], [], [])"
+ << "verify(vi.removed, [1], [1], [undefined])"
+ << "verify(vi.inserted, [], [], [])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+
+
+ QTest::newRow("item moved from tail")
+ << QString("listModel.move(3, 0, 1)")
+ << (QStringList()
+ << "verify(vm.removed, [3], [1], [vm.inserted[0].moveId])"
+ << "verify(vm.inserted, [0], [1], [vm.removed[0].moveId])"
+ << "verify(vi.removed, [3], [1], [vi.inserted[0].moveId])"
+ << "verify(vi.inserted, [0], [1], [vi.removed[0].moveId])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+ QTest::newRow("item moved from head")
+ << QString("listModel.move(0, 2, 2)")
+ << (QStringList()
+ << "verify(vm.removed, [0], [2], [vm.inserted[0].moveId])"
+ << "verify(vm.inserted, [2], [2], [vm.removed[0].moveId])"
+ << "verify(vi.removed, [0], [2], [vi.inserted[0].moveId])"
+ << "verify(vi.inserted, [2], [2], [vi.removed[0].moveId])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+
+ QTest::newRow("groups changed")
+ << QString("items.setGroups(1, 2, [\"items\", \"selected\"])")
+ << (QStringList()
+ << "verify(vm.inserted, [], [], [])"
+ << "verify(vm.removed, [], [], [])"
+ << "verify(vi.removed, [1], [2], [undefined])"
+ << "verify(vi.inserted, [], [], [])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [0], [2], [undefined])");
+
+ QTest::newRow("multiple removes")
+ << QString("{ vi.remove(1, 1); "
+ "vi.removeGroups(0, 2, \"items\") }")
+ << (QStringList()
+ << "verify(vm.removed, [0, 1], [1, 1], [undefined, undefined])"
+ << "verify(vm.inserted, [], [], [])"
+ << "verify(vi.removed, [1], [1], [undefined])"
+ << "verify(vi.inserted, [], [], [])"
+ << "verify(si.removed, [], [], [])"
+ << "verify(si.inserted, [], [], [])");
+}
+
+void tst_qquickvisualdatamodel::onChanged()
+{
+ QFETCH(QString, expression);
+ QFETCH(QStringList, tests);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("onChanged.qml")));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object);
+
+ evaluate<void>(object.data(), expression);
+
+ foreach (const QString &test, tests) {
+ bool passed = evaluate<bool>(object.data(), test);
+ if (!passed)
+ qWarning() << test;
+ QVERIFY(passed);
+ }
+}
+
+void tst_qquickvisualdatamodel::create()
+{
+ QQuickView view;
+
+ SingleRoleModel model;
+ model.list = QStringList()
+ << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six"
+ << "seven"
+ << "eight"
+ << "nine"
+ << "ten"
+ << "eleven"
+ << "twelve"
+ << "thirteen"
+ << "fourteen"
+ << "fifteen"
+ << "sixteen"
+ << "seventeen"
+ << "eighteen"
+ << "nineteen"
+ << "twenty";
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(TESTDATA("create.qml")));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
+ QVERIFY(visualModel);
+
+ QCOMPARE(listview->count(), 20);
+
+ QQuickItem *delegate;
+
+ // persistedItems.includeByDefault is true, so all items belong to persistedItems initially.
+ QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 1));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+
+ // changing include by default doesn't remove persistance.
+ evaluate<void>(visualModel, "persistedItems.includeByDefault = false");
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+
+ // removing from persistedItems does.
+ evaluate<void>(visualModel, "persistedItems.remove(0, 20)");
+ QCOMPARE(listview->count(), 20);
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+
+ // Request an item instantiated by the view.
+ QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(1)")));
+ QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 1));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
+
+ evaluate<void>(delegate, "VisualDataModel.inPersistedItems = false");
+ QCOMPARE(listview->count(), 20);
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
+
+ // Request an item not instantiated by the view.
+ QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 15));
+ QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(15)")));
+ QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 15));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
+
+ evaluate<void>(visualModel, "persistedItems.remove(0)");
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
+
+ // Request an item not instantiated by the view, then scroll the view so it will request it.
+ QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 16));
+ QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(16)")));
+ QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 16));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
+
+ evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
+ QCOMPARE(listview->count(), 20);
+ evaluate<void>(delegate, "VisualDataModel.groups = [\"items\"]");
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
+
+ // Request and release an item instantiated by the view, then scroll the view so it releases it.
+ QVERIFY(findItem<QQuickItem>(contentItem, "delegate", 17));
+ QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(17)")));
+ QCOMPARE(delegate, findItem<QQuickItem>(contentItem, "delegate", 17));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
+
+ evaluate<void>(visualModel, "items.removeGroups(17, \"persistedItems\")");
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
+ evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
+ QCOMPARE(listview->count(), 20);
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
+
+ // Adding an item to the persistedItems group won't instantiate it, but if later requested by
+ // the view it will be persisted.
+ evaluate<void>(visualModel, "items.addGroups(18, \"persistedItems\")");
+ QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
+ QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 18));
+ evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
+ QCOMPARE(listview->count(), 20);
+ QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 18));
+ QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
+ evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
+ QCOMPARE(listview->count(), 20);
+ QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
+}
+
+
+void tst_qquickvisualdatamodel::incompleteModel()
+{
+ // VisualDataModel is first populated in componentComplete. Verify various functions are
+ // harmlessly ignored until then.
+
+ QDeclarativeComponent component(&engine);
+ component.setData("import QtQuick 2.0\n VisualDataModel {}", QUrl::fromLocalFile(TESTDATA("")));
+
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+
+ QQuickVisualDataModel *model = qobject_cast<QQuickVisualDataModel *>(object.data());
+ QVERIFY(model);
+
+ QSignalSpy itemsSpy(model->items(), SIGNAL(countChanged()));
+ QSignalSpy persistedItemsSpy(model->items(), SIGNAL(countChanged()));
+
+ evaluate<void>(model, "items.removeGroups(0, items.count, \"items\")");
+ QCOMPARE(itemsSpy.count(), 0);
+ QCOMPARE(persistedItemsSpy.count(), 0);
+
+ evaluate<void>(model, "items.setGroups(0, items.count, \"persistedItems\")");
+ QCOMPARE(itemsSpy.count(), 0);
+ QCOMPARE(persistedItemsSpy.count(), 0);
+
+ evaluate<void>(model, "items.addGroups(0, items.count, \"persistedItems\")");
+ QCOMPARE(itemsSpy.count(), 0);
+ QCOMPARE(persistedItemsSpy.count(), 0);
+
+ evaluate<void>(model, "items.remove(0, items.count)");
+ QCOMPARE(itemsSpy.count(), 0);
+ QCOMPARE(persistedItemsSpy.count(), 0);
+
+ evaluate<void>(model, "items.insert([ \"color\": \"blue\" ])");
+ QCOMPARE(itemsSpy.count(), 0);
+ QCOMPARE(persistedItemsSpy.count(), 0);
+
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: get: index out of range");
+ QVERIFY(evaluate<bool>(model, "items.get(0) === undefined"));
+
+ component.completeCreate();
+}
+
+template<typename T>
+T *tst_qquickvisualdatamodel::findItem(QQuickItem *parent, const QString &objectName, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->childItems().count() << "children";
+ for (int i = 0; i < parent->childItems().count(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QDeclarativeExpression e(qmlContext(item), item, "index");
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_qquickvisualdatamodel)
+
+#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/qtquick2/qtquick2.pro b/tests/auto/qtquick2/qtquick2.pro
new file mode 100644
index 0000000000..af468a6393
--- /dev/null
+++ b/tests/auto/qtquick2/qtquick2.pro
@@ -0,0 +1,63 @@
+TEMPLATE = subdirs
+
+PUBLICTESTS += \
+ examples \
+ geometry \
+ nodes \
+ qdeclarativepixmapcache
+
+PRIVATETESTS += \
+ qdeclarativeanimations \
+ qdeclarativeapplication \
+ qdeclarativebehaviors \
+ qdeclarativefontloader \
+ qdeclarativepath \
+ qdeclarativesmoothedanimation \
+ qdeclarativespringanimation \
+ qdeclarativestyledtext \
+ qdeclarativestates \
+ qdeclarativesystempalette \
+ qdeclarativetimer \
+ qdeclarativexmllistmodel
+
+# This test requires the xmlpatterns module
+!contains(QT_CONFIG,xmlpatterns):PRIVATETESTS -= qdeclarativexmllistmodel
+
+QUICKTESTS = \
+ qquickanchors \
+ qquickanimatedimage \
+ qquickborderimage \
+ qquickcanvas \
+ qquickdrag \
+ qquickdroparea \
+ qquickflickable \
+ qquickflipable \
+ qquickfocusscope \
+ qquickgridview \
+ qquickimage \
+ qquickitem \
+ qquickitem2 \
+ qquicklistview \
+ qquickloader \
+ qquickmousearea \
+ qquickmultipointtoucharea \
+ qquickpathview \
+ qquickpincharea \
+ qquickpositioners \
+ qquickrepeater \
+ qquickshadereffect \
+ qquickspriteimage \
+ qquicktext \
+ qquicktextedit \
+ qquicktextinput \
+ qquickvisualdatamodel \
+ qquickview \
+ qquickcanvasitem \
+
+
+SUBDIRS += $$PUBLICTESTS
+
+contains(QT_CONFIG, private_tests) {
+ SUBDIRS += $$PRIVATETESTS
+ SUBDIRS += $$QUICKTESTS
+}
diff --git a/tests/auto/declarative/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp
index 206094924c..206094924c 100644
--- a/tests/auto/declarative/shared/testhttpserver.cpp
+++ b/tests/auto/shared/testhttpserver.cpp
diff --git a/tests/auto/declarative/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h
index 3e8f70fea4..3e8f70fea4 100644
--- a/tests/auto/declarative/shared/testhttpserver.h
+++ b/tests/auto/shared/testhttpserver.h
diff --git a/tests/auto/declarative/shared/util.h b/tests/auto/shared/util.h
index eac2c4ec12..eac2c4ec12 100644
--- a/tests/auto/declarative/shared/util.h
+++ b/tests/auto/shared/util.h
diff --git a/tests/benchmarks/particles/affectors/affectors.pro b/tests/benchmarks/particles/affectors/affectors.pro
index 4d1926da22..17b23255ac 100644
--- a/tests/benchmarks/particles/affectors/affectors.pro
+++ b/tests/benchmarks/particles/affectors/affectors.pro
@@ -7,4 +7,4 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tests/benchmarks/particles/emission/emission.pro b/tests/benchmarks/particles/emission/emission.pro
index 6e5e8ec019..343bdf0430 100644
--- a/tests/benchmarks/particles/emission/emission.pro
+++ b/tests/benchmarks/particles/emission/emission.pro
@@ -7,4 +7,4 @@ testDataFiles.files = data
testDataFiles.path = .
DEPLOYMENT += testDataFiles
-QT += core-private gui-private v8-private declarative-private opengl-private testlib
+QT += core-private gui-private v8-private declarative-private quick-private opengl-private testlib
diff --git a/tools/qmleasing/main.cpp b/tools/qmleasing/main.cpp
index a9f1da41d4..224e23f544 100644
--- a/tools/qmleasing/main.cpp
+++ b/tools/qmleasing/main.cpp
@@ -40,10 +40,10 @@
****************************************************************************/
#include <QPainter>
-#include <QQuickView>
+#include <QtQuick/QQuickView>
#include <QApplication>
#include <QEasingCurve>
-#include <QQuickPaintedItem>
+#include <QtQuick/QQuickPaintedItem>
class EasingPlot : public QQuickPaintedItem
{
diff --git a/tools/qmleasing/qmleasing.pro b/tools/qmleasing/qmleasing.pro
index 4a64fe91e0..eb2ee86070 100644
--- a/tools/qmleasing/qmleasing.pro
+++ b/tools/qmleasing/qmleasing.pro
@@ -3,7 +3,7 @@ TARGET =
DEPENDPATH += .
INCLUDEPATH += .
-QT += declarative widgets
+QT += declarative quick widgets
CONFIG -= app_bundle
# Input
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 5e35abcc8b..c9f6cbe6c1 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -39,15 +39,19 @@
**
****************************************************************************/
-#include <QtDeclarative/QtDeclarative>
+#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/private/qdeclarativemetatype_p.h>
#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h>
-#include <QtDeclarative/private/qquickevents_p_p.h>
-#include <QtDeclarative/private/qquickpincharea_p.h>
+#include <QtQuick/private/qquickevents_p_p.h>
+#include <QtQuick/private/qquickpincharea_p.h>
#include <QtWidgets/QApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
#include <QtCore/QSet>
+#include <QtCore/QStringList>
+#include <QtCore/QTimer>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
#include <QtCore/QDebug>
@@ -674,11 +678,11 @@ int main(int argc, char *argv[])
engine.addImportPath(pluginImportPath);
}
- // load the QtQuick 1 plugin
+ // load the QtQuick 1 & 2 plugins
{
- QByteArray code("import QtQuick 1.0\nQtObject {}");
+ QByteArray code("import QtQuick 1.0 as Q1\nimport QtQuick 2.0 as Q2\nQ2.QtObject {}");
QDeclarativeComponent c(&engine);
- c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick1.qml"));
+ c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick.qml"));
c.create();
if (!c.errors().isEmpty()) {
foreach (const QDeclarativeError &error, c.errors())
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index 7db7722c62..a327bb68d9 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
CONFIG += qt uic console
DESTDIR = $$QT.declarative.bins
-QT += declarative declarative-private qtquick1 core-private widgets
+QT += declarative declarative-private quick-private qtquick1 core-private widgets
TARGET = qmlplugindump
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 336fc899cd..696686afef 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -58,8 +58,8 @@
#include <QtDeclarative/qdeclarativecontext.h>
// ### This should be private API
-#include <qquickitem.h>
-#include <qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
#define QT_NO_SCENEGRAPHITEM
diff --git a/tools/qmlscene/qmlscene.pro b/tools/qmlscene/qmlscene.pro
index d0c4ec7a20..4147c68005 100644
--- a/tools/qmlscene/qmlscene.pro
+++ b/tools/qmlscene/qmlscene.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = qmlscene
DESTDIR= $$QT.declarative.bins
-QT += declarative declarative-private qtquick1 widgets
+QT += declarative declarative-private quick qtquick1 widgets
target.path = $$[QT_INSTALL_BINS]
INSTALLS += target